加我模型论坛

 找回密码
 注册
搜索
热搜: 活动 交友 discuz
12
返回列表 发新帖
楼主: joyrus

我的第二个单片机开源项目——全比例模型遥控器摇杆位置采样与PPM编码信号输出程序

[复制链接]
 楼主| 发表于 2012-6-26 11:29:36 | 显示全部楼层
最后是主程序,所有的采样和TMR1的计数脉冲数都在主程序中计算并保存,随时可以在中断中使用。

main
   movlw  b'00000000'       ;初始化前禁止所有中断
   movwf  INTCON
   ;Bank1 初始化ADC端口/中断/输出PORT口
   ;***************
   banksel  ADCON1
   movlw  b'00001000'
   movwf  ADCON1
   movlw  b'00000001'
   movwf  PIE1
   bcf   TRISD,1
   ;Bank0 初始化常量
   ;****************
   banksel  STATUS
   bcf   PORTD,1
   ; PPM每个通道的固定间隔宽度65536-488us(0xFE18)
   movlw  0x18   
   movwf  ppm_interval_origin
   movlw  0xFE
   movwf  ppm_interval_origin+1
   ;初始化通道选择;在中断中使用
   clrf  ch_ppm_sel        
   bsf   ch_ppm_sel,0      
   ; PPM通道脉冲头标志位,首先输出脉冲头
   clrf  ppm_head_flag
   comf  ppm_head_flag,f   
   ;Bank0 初始化ADC端口
   ;****************  
   movlw  b'00000001'
   movwf  ADCON0
   movlw  b'00000001'
   movwf  T1CON
   ;全部初始化完成后开中断
   ;****************
   movlw  b'11000000'
   movwf  INTCON
ADC_catch
   
   clrf  ad_data_point       ;复位ADC数据缓冲区指针
ADC_ch0;****
   ;采样并保存   
   call  ADC_doing            ;第一次ADC转换
   incf  ad_data_point,f     ;指针位移+1指向下一个缓冲单元
   call  ADC_doing            ;第二次ADC转换
   incf  ad_data_point,f     ;指针位移+1指向下一个缓冲单元
   ;选择下一个通道-通道1
   movlw  b'00001001'
   movwf  ADCON0
   ;数据校验
   ;***************************************************************
   movf  ad_data_buff+ch0,w        ;第一次数据->w
   subwf  ad_data_buff+ch0+1,w  ;第二次数据-第一次数据->w
   sublw  ad_check_no                 ;最大误差值-w,若C=0有借位,数据不合格需要处理
   bc   Figure_ch0ppm                 ;C=1则表明数据正确,下一通道采样
   ;处理不合格数据
   movf  ad_data_buff+ch0,w       ;第一次数据->w
   addwf  ad_data_buff+ch0+1,f  ;第二次数据+第一次数据->第二次数据位
   rrf   ad_data_buff+ch0+1,f      ;两次数据和/2求平均,放入第二次数据位
   ;***************************************************************
Figure_ch0ppm ;计算PPM通道脉冲宽度
   movf  ad_data_buff+ch0+1,w  ;取最终合格的ADC数据
   clrf  ch_ppm+1                       ;高8位清0
   movwf  ch_ppm                      ;数据送到PPM计算临时区低8位
   bcf   STATUS,C
   rlf   ch_ppm                           ;连续两次左移位将ADC结果×4
   rlf   ch_ppm+1
   bcf   STATUS,C
   rlf   ch_ppm
   rlf   ch_ppm+1
   ;***************************
   ;用常数减计数值求TMR1计数初值
   movf  ch_ppm,w                       ;低位计算
   subwf  ppm_interval_origin,w    ; ppm_interval_origin减ch_ppm
   movwf  ch_ppm                       ;保存结果
   skpc                                       ;C=1没有借位跳过下面一条指令
   incf  ch_ppm+1,f                     ;有借位高位有借位,补被低位借掉的1
   movf  ch_ppm+1,w                  ;高位计算
   subwf  ppm_interval_origin+1,w  ; ppm_interval_origin+1减ch_ppm+1
   movwf  ch_ppm+1                  ;保存结果   
   ;***************************
   bcf   INTCON,GIE                   ;禁止中断,保证数据的完整
   ;***************************
   movwf  ch_ppm_buff+ch0+1        ;将数据最终存入PPM计数缓存区
   movf  ch_ppm,w
   movwf  ch_ppm_buff+ch0
   ;***************************
   bsf   INTCON,GIE                   ;打开中断
   ;***************************
            ;通道0采样PPM计数转换完成
ADC_ch1;****
   ;采样并保存   
   call  ADC_doing              ;第一次ADC转换
   incf  ad_data_point,f      ;指针位移+1指向下一个缓冲单元
   call  ADC_doing             ;第二次ADC转换
   incf  ad_data_point,f      ;指针位移+1指向下一个缓冲单元
   ;选择下一个通道-通道2
   movlw  b'00101001'
   movwf  ADCON0
   ;数据校验
   ;***************************************************************
   movf  ad_data_buff+ch1,w        ;第一次数据->w
   subwf  ad_data_buff+ch1+1,w  ;第二次数据-第一次数据->w
   sublw  ad_check_no                 ;最大误差值-w,若C=0有借位,数据不合格需要处理
   bc   Figure_ch1ppm                 ;C=1则表明数据正确,下一通道采样
   ;处理不合格数据
   movf  ad_data_buff+ch1,w       ;第一次数据->w
   addwf  ad_data_buff+ch1+1,f  ;第二次数据+第一次数据->第二次数据位
   rrf   ad_data_buff+ch1+1,f      ;两次数据和/2求平均,放入第二次数据位
   ;***************************************************************
Figure_ch1ppm ;计算PPM通道脉冲宽度
   movf  ad_data_buff+ch1+1,w  ;取最终合格的ADC数据
   clrf  ch_ppm+1                       ;高8位清0
   movwf  ch_ppm                      ;数据送到PPM计算临时区低8位
   bcf   STATUS,C
   rlf   ch_ppm                           ;连续两次左移位将ADC结果×4
   rlf   ch_ppm+1
   bcf   STATUS,C
   rlf   ch_ppm
   rlf   ch_ppm+1
   ;***************************
   ;用常数减计数值求TMR1计数初值
   movf  ch_ppm,w                      ;低位计算
   subwf  ppm_interval_origin,w    ; ppm_interval_origin减ch_ppm
   movwf  ch_ppm                       ;保存结果
   skpc                                       ;C=1没有借位跳过下面一条指令
   incf  ch_ppm+1,f                     ;有借位高位有借位,补被低位借掉的1
   movf  ch_ppm+1,w                  ;高位计算
   subwf  ppm_interval_origin+1,w  ; ppm_interval_origin+1减ch_ppm+1
   movwf  ch_ppm+1                   ;保存结果   
   ;***************************
   bcf   INTCON,GIE                    ;禁止中断,保证数据的完整
   ;***************************
   movwf  ch_ppm_buff+ch1+1        ;将数据最终存入PPM计数缓存区
   movf  ch_ppm,w
   movwf  ch_ppm_buff+ch1
   ;***************************
   bsf   INTCON,GIE                    ;打开中断
   ;***************************
            ;通道1采样PPM计数转换完成
ADC_ch2;****
   ;采样并保存   
   call  ADC_doing              ;第一次ADC转换
   incf  ad_data_point,f     ;指针位移+1指向下一个缓冲单元
   call  ADC_doing             ;第二次ADC转换
   incf  ad_data_point,f     ;指针位移+1指向下一个缓冲单元
   ;选择下一个通道-通道3
   movlw  b'00110001'
   movwf  ADCON0
   ;数据校验
   ;***************************************************************
   movf  ad_data_buff+ch2,w         ;第一次数据->w
   subwf  ad_data_buff+ch2+1,w  ;第二次数据-第一次数据->w
   sublw  ad_check_no                 ;最大误差值-w,若C=0有借位,数据不合格需要处理
   bc   Figure_ch2ppm                  ;C=1则表明数据正确,下一通道采样
   ;处理不合格数据
   movf  ad_data_buff+ch2,w       ;第一次数据->w
   addwf  ad_data_buff+ch2+1,f  ;第二次数据+第一次数据->第二次数据位
   rrf   ad_data_buff+ch2+1,f      ;两次数据和/2求平均,放入第二次数据位
   ;***************************************************************
Figure_ch2ppm ;计算PPM通道脉冲宽度
   movf  ad_data_buff+ch2+1,w  ;取最终合格的ADC数据
   clrf  ch_ppm+1                       ;高8位清0
   movwf  ch_ppm                      ;数据送到PPM计算临时区低8位
   bcf   STATUS,C
   rlf   ch_ppm                           ;连续两次左移位将ADC结果×4
   rlf   ch_ppm+1
   bcf   STATUS,C
   rlf   ch_ppm
   rlf   ch_ppm+1
   ;***************************
   ;用常数减计数值求TMR1计数初值
   movf  ch_ppm,w                      ;低位计算
   subwf  ppm_interval_origin,w    ; ppm_interval_origin减ch_ppm
   movwf  ch_ppm                        ;保存结果
   skpc                                       ;C=1没有借位跳过下面一条指令
   incf  ch_ppm+1,f                     ;有借位高位有借位,补被低位借掉的1
   movf  ch_ppm+1,w                  ;高位计算
   subwf  ppm_interval_origin+1,w  ; ppm_interval_origin+1减ch_ppm+1
   movwf  ch_ppm+1                   ;保存结果   
   ;***************************
   bcf   INTCON,GIE                   ;禁止中断,保证数据的完整
   ;***************************
   movwf  ch_ppm_buff+ch2+1        ;将数据最终存入PPM计数缓存区
   movf  ch_ppm,w
   movwf  ch_ppm_buff+ch2
   ;***************************
   bsf   INTCON,GIE                  ;打开中断
   ;***************************
            ;通道2采样PPM计数转换完成
ADC_ch3;****
   ;采样并保存   
   call  ADC_doing             ;第一次ADC转换
   incf  ad_data_point,f      ;指针位移+1指向下一个缓冲单元
   call  ADC_doing             ;第二次ADC转换
   incf  ad_data_point,f     ;指针位移+1指向下一个缓冲单元
   ;选择下一个通道-通道0
   movlw  b'00000001'
   movwf  ADCON0
   ;数据校验
   ;***************************************************************
   movf  ad_data_buff+ch3,w        ;第一次数据->w
   subwf  ad_data_buff+ch3+1,w  ;第二次数据-第一次数据->w
   sublw  ad_check_no                  ;最大误差值-w,若C=0有借位,数据不合格需要处理
   bc   Figure_ch3ppm                  ;C=1则表明数据正确,下一通道采样
   ;处理不合格数据
   movf  ad_data_buff+ch3,w       ;第一次数据->w
   addwf  ad_data_buff+ch3+1,f  ;第二次数据+第一次数据->第二次数据位
   rrf   ad_data_buff+ch3+1,f      ;两次数据和/2求平均,放入第二次数据位
   ;***************************************************************
Figure_ch3ppm ;计算PPM通道脉冲宽度
   movf  ad_data_buff+ch3+1,w  ;取最终合格的ADC数据
   clrf  ch_ppm+1                       ;高8位清0
   movwf  ch_ppm                      ;数据送到PPM计算临时区低8位
   bcf   STATUS,C
   rlf   ch_ppm                          ;连续两次左移位将ADC结果×4
   rlf   ch_ppm+1
   bcf   STATUS,C
   rlf   ch_ppm
   rlf   ch_ppm+1
   ;***************************
   ;用常数减计数值求TMR1计数初值
   movf  ch_ppm,w                       ;低位计算
   subwf  ppm_interval_origin,w    ; ppm_interval_origin减ch_ppm
   movwf  ch_ppm                        ;保存结果
   skpc                                        ;C=1没有借位跳过下面一条指令
   incf  ch_ppm+1,f                     ;有借位高位有借位,补被低位借掉的1
   movf  ch_ppm+1,w                  ;高位计算
   subwf  ppm_interval_origin+1,w  ; ppm_interval_origin+1减ch_ppm+1
   movwf  ch_ppm+1                   ;保存结果   
   ;***************************
   bcf   INTCON,GIE                   ;禁止中断,保证数据的完整
   ;***************************
   movwf  ch_ppm_buff+ch3+1        ;将数据最终存入PPM计数缓存区
   movf  ch_ppm,w
   movwf  ch_ppm_buff+ch3
   ;***************************
   bsf   INTCON,GIE                   ;打开中断
   ;***************************
            ;通道3采样PPM计数转换完成
   ;
   goto  ADC_catch

;ADC转换子程序
;**********************************************************************
ADC_doing
   bsf   ADCON0,GO           ;开始ADC
   btfsc  ADCON0,GO         ;ADC是否结束
   goto  $-1                      ;等待ADC结束
   ;保存ADC结果
   movlw  ad_data_buff       ;取ADC数据缓冲区首地址
   movwf  FSR                    ;FSR相对寻址
   movf  ad_data_point,w   ;取相对位移指针
   addwf  FSR,f                  ;相对地址+位移指针
   movf  ADRESH,w            ;取ADC转换结果
   movwf  INDF                  ;放入ADC转换结果
   ;incf  ad_data_point,f     ;指针位移+1指向下一个缓冲单元
                                      ;这一步在每个通道的主程序中完成
   return
;***********************************************************************
   
END                       ; directive 'end of program'
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2019-5-24 18:06 , Processed in 0.128419 second(s), 14 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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