加我模型论坛

 找回密码
 注册
搜索
热搜: 活动 交友 discuz
查看: 3411|回复: 8

我的第三个单片机开源项目——通过PIC单片机的SUART与PC通信显示采样数据

[复制链接]
发表于 2012-6-26 11:44:56 | 显示全部楼层 |阅读模式
本帖最后由 joyrus 于 2012-7-6 18:40 编辑

开源项目名称:通过PIC单片机的SUART与PC通信显示采样数据

设计目的:用于实现对单片机采样的数据进行保存并通过SUART模块传输到PC的串行端口。



正在做准备工作,先学习有关SUART的相关知识和PC端软件的设计,这可能需要不少的时间。准备首先完成MCU通过SUART模块传输到PC并通过超级终端来显示,随后在设计PC端的专门程序。


对程序作了修改增加了ADC采样,数据平滑处理。通过RS232收到数据,通过调整ADC采样电位器可以看到电脑上显示出不同的字符。
 楼主| 发表于 2012-6-30 20:35:55 | 显示全部楼层
先通过对张明峰先生撰写的《PIC单片机入门与实战》的阅读和学习,摘录了其中部分的代码,作为这次我的开源项目的开始。

以下代码基本上和书籍上的内容一致,实现了向串口持续发送1234以及回车和换行字符,通过超级终端可以收到,本人对部分代码做了一些替换,以方便自己的理解。

;**********************************************************************
;程序功能说明
;本程序通过单片机USART端口与PC串口通信,程序主体摘录自张明峰先生撰写的《PIC单片机入门与实战》
;本人联系方法:沈毅;joyrus@163.netwww.joyrus.com,QQ:15953321
;**********************************************************************

; 程序定义部分

#include <p16f877A.inc>  ; 选择的单片机型号

; __CONFIG 单片机配置


;***** VARIABLE DEFINITIONS
fsr_temp EQU 0x7C  ; 因为在程序中使用间接寻址故在中断中需要保护FSR寄存器
w_temp  EQU 0x7D  ; variable used for context saving
status_temp EQU 0x7E  ; variable used for context saving
pclath_temp EQU 0x7F  ; variable used for context saving   

   cblock 0x20
tx_buff:8                     ; 定义发送数据缓冲区
tx_point                      ; 发送数据指针
tx_count                     ; 发送数据计数器
   endc

#define TX_IE PIE1,TXIE         ;定义一些中断功能寄存器功能位的替换符号方便代码理解
#define TX_IF PIR1,TXIF
#define PE_IE INTCON,PEIE
#define G_IE INTCON,GIE
 楼主| 发表于 2012-6-30 20:39:15 | 显示全部楼层
中断处理程序,发送数据


ORG     0x000             ; processor reset vector
   nop                            ; nop required for icd
   goto    main              ; go to beginning of program

ORG     0x004               ; interrupt vector location

movwf   w_temp            ; save off current W register contents
movf STATUS,w            ; move status register into W register
movwf status_temp       ; save off contents of STATUS register
movf PCLATH,w            ; move pclath register into w register
movwf pclath_temp       ; save off contents of PCLATH register
movf FSR,w                  ; 保护FSR
movwf fsr_temp  

   ;判断是否串行发送中断
   banksel  PIE1
   btfss  TX_IE
   goto  Other_int
   banksel  PIR1
   btfss  TX_IF
   goto  Other_int
   ;判断完成,间接寻址取数据
   movlw  tx_buff
   movwf  FSR
   movf  tx_point,w
   addwf  FSR,f
   movf  INDF,w
   ;发生数据
   movwf  TXREG
   ;偏移指针等准备发送下一个数据
   incf  tx_point
   decfsz  tx_count,f     ;缓冲区还有数据没有发送完毕
                                       ;保持打开TXIE中断
                                       ;一个字节发送完后产生中断继续发送后续数据
   goto  End_int
   ;缓冲区数据全部发送完毕,完成清理工作
   banksel  PIE1
   bcf   TX_IE
   ;bank0
   ;***********************
   banksel  STATUS           ; 返回Bank0

Other_int
     
End_int

movf fsr_temp,w             ; 恢复FSR寄存器
movwf FSR   
movf pclath_temp,w        ; retrieve copy of PCLATH register
movwf PCLATH                ; restore pre-isr PCLATH register contents
movf    status_temp,w     ; retrieve copy of STATUS register
movwf STATUS               ; restore pre-isr STATUS register contents
swapf   w_temp,f
swapf   w_temp,w            ; restore pre-isr W register contents
retfie                               ; return from interrupt
 楼主| 发表于 2012-6-30 20:42:23 | 显示全部楼层
主程序部分

main
   ;初始化
   ;Bank1 定义串行通信的相关寄存器
   ;*********************
   banksel  TXSTA
   movlw  b'00100100'
   movwf  TXSTA
   movlw  .25                    ; 定义9600bps
   movwf  SPBRG
   clrf  PIE1                       ; 关闭中断
   ;Bank0
   ;*********************
   banksel  RCSTA
   movlw  b'10000000'
   movwf  RCSTA
   clrf  tx_count                     
   clrf  INTCON
   bsf   PE_IE                      ; 打开中断     
   bsf   G_IE                        ; 打开中断

ADC_doing
   call  Send_data                 ; 调用数据发送子程序
   goto  $-1                         ; 重复循环发送数据
 楼主| 发表于 2012-6-30 20:43:49 | 显示全部楼层
发送数据子程序

;===================================
;  数据发送子程序
;===================================
Send_data
   ;Bank0
   ;**********************
   banksel  STATUS     ;选择Bank0
   movf  tx_count,w
   skpz                      ;数据是否发送完
   return                    ;还有数据未发送完返回
   ;装载新数据
   movlw  '1'
   movwf  tx_buff+0
   movlw  '2'
   movwf  tx_buff+1
   movlw  '3'
   movwf  tx_buff+2
   movlw  '4'
   movwf  tx_buff+3
   movlw  0x0B
   movwf  tx_buff+4
   movlw  0x0A
   movwf  tx_buff+5      ;完成数据装载
   movlw  .6
   movwf  tx_count       ;设定发送数据的数量
   clrf  tx_point             ;复位偏移指针
   ;Bank1
   ;***********************
   banksel  PIE1
   bsf   TX_IE               ;开启发送中断,立即发送数据
   ;Bank0
   ;***********************
   banksel  STATUS       ; 返回Bank0
   return
;=====================================
   
END                       ; directive 'end of program'
 楼主| 发表于 2012-6-30 20:47:53 | 显示全部楼层
通过这个发送程序,我可以借此来调试PC段的接受软件,本人正在使用C语言编写一个简单的串口数据接收程序来接受数据并转换成需要的方式来显示,比如通过ADC采样0-5V的电压,然后通过串口发送数据到PC上显示出电压,这就相当于一个0-5V的简易数字电压表。
 楼主| 发表于 2012-7-6 18:33:53 | 显示全部楼层
在继续学习C语言的同时,修改了上面的最基本的数据传输程序,加入了ADC采样,然后对数据取平均值,最后放到结果寄存器中,随时等待中断调用数据并发送到RS232端口。

程序如下:中断发送程序没有什么变化

;**********************************************************************
;程序功能说明
;本程序通过单片机USART端口与PC串口通信
;本程序有很大的优化空间和存在安全漏洞,这个程序只是本人的学习过程,和大家共同探讨的载体
;本人联系方法:沈毅;joyrus@163.netwww.joyrus.com,QQ:15953321
;**********************************************************************
list  p=16f877A ; list directive to define processor
#include <p16f877A.inc> ; processor specific variable definitions

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _XT_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF

; '__CONFIG' directive is used to embed configuration data within .asm file.
; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.

;***** VARIABLE DEFINITIONS
fsr_temp EQU 0x7C       ; variable used for context saving
w_temp  EQU 0x7D       ; variable used for context saving
status_temp EQU 0x7E  ; variable used for context saving
pclath_temp EQU 0x7F   ; variable used for context saving   
   cblock 0x20
tx_buff:8
tx_point
tx_count
ad_data_buff: 8            ;采样数据缓冲区
ad_data_point              ;采样数据缓冲区偏移指针
ad_data_L                  ;采样数据平滑处理单元低8位
ad_data_H                  ;采样数据平滑处理单元高8位
ad_result_L                ;最终采样数据低8位
ad_result_H                ;最终采样数据高8位
   endc
#define TX_IE PIE1,TXIE
#define TX_IF PIR1,TXIF
#define PE_IE INTCON,PEIE
#define G_IE INTCON,GIE
;**********************************************************************
ORG     0x000             ; processor reset vector
nop                            ; nop required for icd
   goto    main              ; go to beginning of program

ORG     0x004             ; interrupt vector location
movwf   w_temp            ; save off current W register contents
movf STATUS,w          ; move status register into W register
movwf status_temp       ; save off contents of STATUS register
movf PCLATH,w          ; move pclath register into w register
movwf pclath_temp       ; save off contents of PCLATH register
movf FSR,w
movwf fsr_temp   
   ;Bank1 判断是否串行发送
   ;**********************
   banksel  PIE1
   btfss  TX_IE
   goto  Other_int
   banksel  PIR1
   btfss  TX_IF
   goto  Other_int
   ;判断完成,间接寻址取数据
   movlw  tx_buff
   movwf  FSR
   movf  tx_point,w
   addwf  FSR,f
   movf  INDF,w
   ;发送数据
   movwf  TXREG
   ;偏移指针等准备发送下一个数据
   incf  tx_point
   decfsz  tx_count,f          ;缓冲区还有数据没有发送完毕
                                       ;保持打开TXIE中断
                                       ;一个字节发送完后产生中断继续发送后续数据
   goto  End_int
   ;缓冲区数据全部发送完毕,完成清理工作
   banksel  PIE1
   bcf   TX_IE
   ;bank0
   ;***********************
   banksel  STATUS
Other_int
     
End_int
movf fsr_temp,w
movwf FSR   
movf pclath_temp,w         ; retrieve copy of PCLATH register
movwf PCLATH                 ; restore pre-isr PCLATH register contents
movf    status_temp,w     ; retrieve copy of STATUS register
movwf STATUS               ; restore pre-isr STATUS register contents
swapf   w_temp,f
swapf   w_temp,w          ; restore pre-isr W register contents
retfie                             ; return from interrupt
 楼主| 发表于 2012-7-6 18:37:57 | 显示全部楼层
主程序部分变化比较大

加入了ADC采样,数据平滑处理等

main
   ;初始化
   ;Bank1 初始化USART
   ;*********************
   banksel  TXSTA
   movlw  b'00100100'
   movwf  TXSTA
   movlw  .25
   movwf  SPBRG
   clrf  PIE1
   ;Bank1 初始化ADC端口
   ;***************
   movlw  b'0000000'
   movwf  ADCON1
   ;Bank0 初始化USART
   ;*********************
   banksel  RCSTA
   movlw  b'10000000'
   movwf  RCSTA
   clrf  tx_count
   clrf  INTCON
   bsf   PE_IE
   bsf   G_IE
   ;Bank0 初始化ADC端口
   ;****************  
   movlw  b'00000001'
   movwf  ADCON0
   ;clrf  ad_data_point       ;复位ADC数据缓冲区指针
Loop
   call  ADC_doing             ;调用子程序处理
   call  ADC_average          ;调用子程序处理
   call  ADC_send               ;调用子程序处理
   goto  Loop
 楼主| 发表于 2012-7-6 18:39:04 | 显示全部楼层
三个子程序:

;===================================
;  ADC数据发送子程序
;===================================
ADC_send
   ;Bank0
   ;**********************
   banksel  STATUS
   movf  tx_count,w
   skpz                      ;数据是否发送完
   return                    ;还有数据未发送完返回
   ;装载新数据
   movf  ad_result_L,w
   movwf  tx_buff+0
   ;movlw  '2'
   movwf  tx_buff+1
   ;movlw  '3'
   movwf  tx_buff+2
   ;movlw  '4'
   movwf  tx_buff+3
   movlw  0x0B
   movwf  tx_buff+4
   movlw  0x0A
   movwf  tx_buff+5      ;完成数据装载
   movlw  .6
   movwf  tx_count       ;设定发送数据的数量
   clrf  tx_point       ;复位偏移指针
   ;Bank1
   ;***********************
   banksel  PIE1
   bsf   TX_IE          ;开启发送中断,立即发送数据
   ;Bank0
   ;***********************
   banksel  STATUS
   return
;=====================================
;===================================
;  ADC转换子程序
;===================================
ADC_doing
   ;Bank0
   ;**********************
   banksel  STATUS
   movlw  0x08
   movwf  ad_data_point     ;设置位移指针
   ;开始采样
   bsf   ADCON0,GO           ;开始ADC
   btfsc  ADCON0,GO         ;ADC转换是否结束
   goto  $-1                      ;等待ADC结束
   ;保存ADC结果
   movlw  ad_data_buff-1    ;取ADC数据缓冲区首地址
   movwf  FSR                    ;FSR相对寻址
   movf  ad_data_point,w   ;取相对位移指针
   addwf  FSR,f                  ;相对地址+位移指针
   movf  ADRESH,w             ;取ADC转换结果
   movwf  INDF                   ;放入ADC转换结果
   decfsz  ad_data_point,f   ;指针位移-1指向下一个缓冲单元
   goto  $-.9                       ;ad_data_point不等于0则继续转换
   return
;=====================================
;===================================
;  ADC数据平滑处理
;===================================
ADC_average
   ;Bank0
   ;**********************
   banksel  STATUS
   movlw  0x08
   movwf  ad_data_point     ;设置位移指针
   clrf  ad_data_L                ;累加单元清空
   clrf  ad_data_H         
   ;开始累加
   movlw  ad_data_buff-1    ;取ADC数据缓冲区首地址
   movwf  FSR                     ;FSR相对寻址
   movf  ad_data_point,w   ;取相对位移指针
   addwf  FSR,f                  ;相对地址+位移指针
   movf  INDF,w                 ;取数据到w
   addwf  ad_data_L,f         ;进行累加
   skpnc                             ;是否有进位
   incf  ad_data_H,f             ;有进位高位加1
   decfsz  ad_data_point,f   ;指针位移-1指向下一个缓冲单元
   goto  $-.9                       ;ad_data_point不等于0则继续累加
   ;累加完成求平均/除8右移3次
   bcf   STATUS,C
   rrf   ad_data_H,f
   rrf   ad_data_L,f
   bcf   STATUS,C
   rrf   ad_data_H,f
   rrf   ad_data_L,f
   bcf   STATUS,C
   rrf   ad_data_H,f
   rrf   ad_data_L,f
   ;关中断送最终结果   
   bcf   G_IE              ;关中断
   movf  ad_data_L,w
   movwf  ad_result_L
   movf  ad_data_H,w
   movwf  ad_result_H
   bsf   G_IE              ;开中断
   return
;=====================================
END                       ; directive 'end of program'
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|JOYRUS.com

GMT+8, 2019-5-22 10:36 , Processed in 0.112956 second(s), 16 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表