joyrus 发表于 2012-6-26 11:29:36

最后是主程序,所有的采样和TMR1的计数脉冲数都在主程序中计算并保存,随时可以在中断中使用。

main
   movlwb'00000000'       ;初始化前禁止所有中断
   movwfINTCON
   ;Bank1 初始化ADC端口/中断/输出PORT口
   ;***************
   bankselADCON1
   movlwb'00001000'
   movwfADCON1
   movlwb'00000001'
   movwfPIE1
   bcf   TRISD,1
   ;Bank0 初始化常量
   ;****************
   bankselSTATUS
   bcf   PORTD,1
   ; PPM每个通道的固定间隔宽度65536-488us(0xFE18)
   movlw0x18   
   movwfppm_interval_origin
   movlw0xFE
   movwfppm_interval_origin+1
   ;初始化通道选择;在中断中使用
   clrfch_ppm_sel      
   bsf   ch_ppm_sel,0      
   ; PPM通道脉冲头标志位,首先输出脉冲头
   clrfppm_head_flag
   comfppm_head_flag,f   
   ;Bank0 初始化ADC端口
   ;****************
   movlwb'00000001'
   movwfADCON0
   movlwb'00000001'
   movwfT1CON
   ;全部初始化完成后开中断
   ;****************
   movlwb'11000000'
   movwfINTCON
ADC_catch
   
   clrfad_data_point       ;复位ADC数据缓冲区指针
ADC_ch0;****
   ;采样并保存   
   callADC_doing            ;第一次ADC转换
   incfad_data_point,f   ;指针位移+1指向下一个缓冲单元
   callADC_doing            ;第二次ADC转换
   incfad_data_point,f   ;指针位移+1指向下一个缓冲单元
   ;选择下一个通道-通道1
   movlwb'00001001'
   movwfADCON0
   ;数据校验
   ;***************************************************************
   movfad_data_buff+ch0,w      ;第一次数据->w
   subwfad_data_buff+ch0+1,w;第二次数据-第一次数据->w
   sublwad_check_no               ;最大误差值-w,若C=0有借位,数据不合格需要处理
   bc   Figure_ch0ppm               ;C=1则表明数据正确,下一通道采样
   ;处理不合格数据
   movfad_data_buff+ch0,w       ;第一次数据->w
   addwfad_data_buff+ch0+1,f;第二次数据+第一次数据->第二次数据位
   rrf   ad_data_buff+ch0+1,f      ;两次数据和/2求平均,放入第二次数据位
   ;***************************************************************
Figure_ch0ppm ;计算PPM通道脉冲宽度
   movfad_data_buff+ch0+1,w;取最终合格的ADC数据
   clrfch_ppm+1                     ;高8位清0
   movwfch_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计数初值
   movfch_ppm,w                     ;低位计算
   subwfppm_interval_origin,w    ; ppm_interval_origin减ch_ppm
   movwfch_ppm                     ;保存结果
   skpc                                       ;C=1没有借位跳过下面一条指令
   incfch_ppm+1,f                     ;有借位高位有借位,补被低位借掉的1
   movfch_ppm+1,w                  ;高位计算
   subwfppm_interval_origin+1,w; ppm_interval_origin+1减ch_ppm+1
   movwfch_ppm+1                  ;保存结果   
   ;***************************
   bcf   INTCON,GIE                   ;禁止中断,保证数据的完整
   ;***************************
   movwfch_ppm_buff+ch0+1      ;将数据最终存入PPM计数缓存区
   movfch_ppm,w
   movwfch_ppm_buff+ch0
   ;***************************
   bsf   INTCON,GIE                   ;打开中断
   ;***************************
            ;通道0采样PPM计数转换完成
ADC_ch1;****
   ;采样并保存   
   callADC_doing            ;第一次ADC转换
   incfad_data_point,f      ;指针位移+1指向下一个缓冲单元
   callADC_doing             ;第二次ADC转换
   incfad_data_point,f      ;指针位移+1指向下一个缓冲单元
   ;选择下一个通道-通道2
   movlwb'00101001'
   movwfADCON0
   ;数据校验
   ;***************************************************************
   movfad_data_buff+ch1,w      ;第一次数据->w
   subwfad_data_buff+ch1+1,w;第二次数据-第一次数据->w
   sublwad_check_no               ;最大误差值-w,若C=0有借位,数据不合格需要处理
   bc   Figure_ch1ppm               ;C=1则表明数据正确,下一通道采样
   ;处理不合格数据
   movfad_data_buff+ch1,w       ;第一次数据->w
   addwfad_data_buff+ch1+1,f;第二次数据+第一次数据->第二次数据位
   rrf   ad_data_buff+ch1+1,f      ;两次数据和/2求平均,放入第二次数据位
   ;***************************************************************
Figure_ch1ppm ;计算PPM通道脉冲宽度
   movfad_data_buff+ch1+1,w;取最终合格的ADC数据
   clrfch_ppm+1                     ;高8位清0
   movwfch_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计数初值
   movfch_ppm,w                      ;低位计算
   subwfppm_interval_origin,w    ; ppm_interval_origin减ch_ppm
   movwfch_ppm                     ;保存结果
   skpc                                       ;C=1没有借位跳过下面一条指令
   incfch_ppm+1,f                     ;有借位高位有借位,补被低位借掉的1
   movfch_ppm+1,w                  ;高位计算
   subwfppm_interval_origin+1,w; ppm_interval_origin+1减ch_ppm+1
   movwfch_ppm+1                   ;保存结果   
   ;***************************
   bcf   INTCON,GIE                  ;禁止中断,保证数据的完整
   ;***************************
   movwfch_ppm_buff+ch1+1      ;将数据最终存入PPM计数缓存区
   movfch_ppm,w
   movwfch_ppm_buff+ch1
   ;***************************
   bsf   INTCON,GIE                  ;打开中断
   ;***************************
            ;通道1采样PPM计数转换完成
ADC_ch2;****
   ;采样并保存   
   callADC_doing            ;第一次ADC转换
   incfad_data_point,f   ;指针位移+1指向下一个缓冲单元
   callADC_doing             ;第二次ADC转换
   incfad_data_point,f   ;指针位移+1指向下一个缓冲单元
   ;选择下一个通道-通道3
   movlwb'00110001'
   movwfADCON0
   ;数据校验
   ;***************************************************************
   movfad_data_buff+ch2,w         ;第一次数据->w
   subwfad_data_buff+ch2+1,w;第二次数据-第一次数据->w
   sublwad_check_no               ;最大误差值-w,若C=0有借位,数据不合格需要处理
   bc   Figure_ch2ppm                  ;C=1则表明数据正确,下一通道采样
   ;处理不合格数据
   movfad_data_buff+ch2,w       ;第一次数据->w
   addwfad_data_buff+ch2+1,f;第二次数据+第一次数据->第二次数据位
   rrf   ad_data_buff+ch2+1,f      ;两次数据和/2求平均,放入第二次数据位
   ;***************************************************************
Figure_ch2ppm ;计算PPM通道脉冲宽度
   movfad_data_buff+ch2+1,w;取最终合格的ADC数据
   clrfch_ppm+1                     ;高8位清0
   movwfch_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计数初值
   movfch_ppm,w                      ;低位计算
   subwfppm_interval_origin,w    ; ppm_interval_origin减ch_ppm
   movwfch_ppm                        ;保存结果
   skpc                                       ;C=1没有借位跳过下面一条指令
   incfch_ppm+1,f                     ;有借位高位有借位,补被低位借掉的1
   movfch_ppm+1,w                  ;高位计算
   subwfppm_interval_origin+1,w; ppm_interval_origin+1减ch_ppm+1
   movwfch_ppm+1                   ;保存结果   
   ;***************************
   bcf   INTCON,GIE                   ;禁止中断,保证数据的完整
   ;***************************
   movwfch_ppm_buff+ch2+1      ;将数据最终存入PPM计数缓存区
   movfch_ppm,w
   movwfch_ppm_buff+ch2
   ;***************************
   bsf   INTCON,GIE                  ;打开中断
   ;***************************
            ;通道2采样PPM计数转换完成
ADC_ch3;****
   ;采样并保存   
   callADC_doing             ;第一次ADC转换
   incfad_data_point,f      ;指针位移+1指向下一个缓冲单元
   callADC_doing             ;第二次ADC转换
   incfad_data_point,f   ;指针位移+1指向下一个缓冲单元
   ;选择下一个通道-通道0
   movlwb'00000001'
   movwfADCON0
   ;数据校验
   ;***************************************************************
   movfad_data_buff+ch3,w      ;第一次数据->w
   subwfad_data_buff+ch3+1,w;第二次数据-第一次数据->w
   sublwad_check_no                  ;最大误差值-w,若C=0有借位,数据不合格需要处理
   bc   Figure_ch3ppm                  ;C=1则表明数据正确,下一通道采样
   ;处理不合格数据
   movfad_data_buff+ch3,w       ;第一次数据->w
   addwfad_data_buff+ch3+1,f;第二次数据+第一次数据->第二次数据位
   rrf   ad_data_buff+ch3+1,f      ;两次数据和/2求平均,放入第二次数据位
   ;***************************************************************
Figure_ch3ppm ;计算PPM通道脉冲宽度
   movfad_data_buff+ch3+1,w;取最终合格的ADC数据
   clrfch_ppm+1                     ;高8位清0
   movwfch_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计数初值
   movfch_ppm,w                     ;低位计算
   subwfppm_interval_origin,w    ; ppm_interval_origin减ch_ppm
   movwfch_ppm                        ;保存结果
   skpc                                        ;C=1没有借位跳过下面一条指令
   incfch_ppm+1,f                     ;有借位高位有借位,补被低位借掉的1
   movfch_ppm+1,w                  ;高位计算
   subwfppm_interval_origin+1,w; ppm_interval_origin+1减ch_ppm+1
   movwfch_ppm+1                   ;保存结果   
   ;***************************
   bcf   INTCON,GIE                   ;禁止中断,保证数据的完整
   ;***************************
   movwfch_ppm_buff+ch3+1      ;将数据最终存入PPM计数缓存区
   movfch_ppm,w
   movwfch_ppm_buff+ch3
   ;***************************
   bsf   INTCON,GIE                   ;打开中断
   ;***************************
            ;通道3采样PPM计数转换完成
   ;
   gotoADC_catch

;ADC转换子程序
;**********************************************************************
ADC_doing
   bsf   ADCON0,GO         ;开始ADC
   btfscADCON0,GO         ;ADC是否结束
   goto$-1                      ;等待ADC结束
   ;保存ADC结果
   movlwad_data_buff       ;取ADC数据缓冲区首地址
   movwfFSR                  ;FSR相对寻址
   movfad_data_point,w   ;取相对位移指针
   addwfFSR,f                  ;相对地址+位移指针
   movfADRESH,w            ;取ADC转换结果
   movwfINDF                  ;放入ADC转换结果
   ;incfad_data_point,f   ;指针位移+1指向下一个缓冲单元
                                    ;这一步在每个通道的主程序中完成
   return
;***********************************************************************
   
END                     ; directive 'end of program'
页: 1 [2]
查看完整版本: 我的第二个单片机开源项目——全比例模型遥控器摇杆位置采样与PPM编码信号输出程序