搜索
bottom↓
回复: 53
打印 上一主题 下一主题

谁说PIC16F用C最好,上汇编程序证明

  [复制链接]

出0入0汤圆

跳转到指定楼层
1
发表于 2014-7-10 20:58:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
谁说PIC16F用C最好,上汇编程序证明


        LIST P=PIC16F73
        INCLUDE<p16F73.INC>
         __CONFIG _BODEN_ON&_CP_ALL&_PWRTE_ON&_WDT_OFF&_XT_OSC

        CBLOCK 0X20
;通用寄存器,用于函数形参传递
R0      
R1        
R2        
R3        
R4        
;标志
FLAG         
;中断临时寄存器
W_TEMP   
PCLATH_TEMP
STATUS_TEMP
FSR_TEMP   
;定时器
T0COUNTERA  
T0COUNTERB  
;延时程序参数
COUNTERA
COUNTERB  
;1621HT形参
ADDR
DAT  
CMD  
;1MS软件延时
COUNTERMSB
;显示程序
GROUP
CHANNEL
TEMPH  ;TABLE返回之高地址数据
TEMPL  ;TABLE返回之低地址数据
;ADC
AFLVL   
RFLVL  
AFLVH   
RFLVH  
ADC_DAT
ADCDATOLDA;峰值延时参数
AFADCFLAG;
ADCDATTEMP
;PLL参数以及常数
PLL_PCTEMPH ;11位分频器高位
PLL_PCTEMPL ;11位分频器低位
PLL_SWTEMP ;7位分频器
PLL_DATTEMP
;数据RRW RLW函数寄存器
DAT_TEMP
R0_TEMP
;IIC
IIC_OUTTIME ;iic超时时间
IIC_DAT
IIC_BITS
IIC_DEVADDR  ;硬件地址
IIC_DATTEMP ;读写数据
IIC_ADDR ;读写地址
IIC_TESTFLAG  ;测试是否读写成功
;闪烁控制
FLASHCOUNTERA
FLASHCOUNTERB
;BATT_LCD;LCD上的电池框
;BATT_FLASHTEMP ;闪烁时间计数器
;IR接收解码
IR_BITS ;记录收到数据的位数
IR_DATTEMPA ;数据1
IR_DATTEMPB
IR_DATTEMPC
IR_DATTEMPD
IR_DATTEMPE  ;数据5
IR_COUNTER
RES_COUNTER ;记录脉宽
IR_DATBIT ;记录数字BIT"0"/"1"

;显示程序的参数
TABLETEMP  ;读LCD代码表形参
TABLETEMPA
TABLETEMPB
TABLETEMPC
;ABC_取模
ABC_TEMPH  
ABC_TEMPM  
ABC_TEMPL
ABC_DAT   
;数据测试,超出范围设置1
DATAA
DATAB
TEST_STA
;除法函数
DIVISOR  ;除数
DIVIDEND  ;被除数
QUOTIENT  ;结果
REMAIN ;余数
DX_BITS;计数
;乘法函数
MULTAH ;乘数
MULTAL;乘数
MULTBH ;被乘数
MULTBL ;被乘数
MULTCH ;结果
MULTCL

;读表程序***************  
TABTEMPA
TABTEMPB
;偏移量
OFFSETH
OFFSETL
;按键
KEYTEMP ;按键计数
KEYFLAGA  ;按键状态
KEYFLAGB
;ADC
ADCTEMP
;取频率表并显示
DIS1
DIS2
DIS3
DIS4
DIS5
DIS6
DISTEMP1
DISTEMP2
DISTEMP3
DISTEMP4
;AF VOL
AF_VOL
;闪烁控制
FLASHFLAG
        ENDC
        CBLOCK 0XA0
;IR 显示参数
IRDISDATA;IR显示缓冲
IRDISDATB;
IRSENDCOUNTER ;IR发送的次数
IRTEMP;IR发射缓冲
IRBITS;IR发送位数
;软件计数器2
T1CA
T1CB

        ENDC
;标志位
#DEFINE LOWBATT FLAG,0 ;由ADC子函数启动
#DEFINE BATTFLASH FLAG,1;由TIMER启动
#DEFINE LED_FLAG FLAG,2
#DEFINE IR_READY FLAG,3
#DEFINE IR_OK FLAG,4
#DEFINE DIS_FLAG FLAG,5 ;是否显示标志项
;定时器闪烁参数
#DEFINE T0A  .10
#DEFINE ASCT0A .1
#DEFINE T0B  .255
#DEFINE ASCT0B .1
;1MS函数延时时间常数
#DEFINE COUNTERMSA .10
;电池闪烁时间常数
#DEFINE BATT_FLASHTIME .8

;**************PLL配置位*****************
;PLL_SW         .1
;PLL_fC         .1  
;PLL_LDS        .1
;PLL_CS         .1

#define PLL_R     .400
#DEFINE PLL_CMD    0F0h

#DEFINE PLL_CS  PORTB,2
#DEFINE PLL_DAT PORTB,0
#DEFINE PLL_CLK PORTB,1
;参考分频比400
#DEFINE PLL_FRTEMPH 1H;14位参考分频器高位
#DEFINE PLL_FRTEMPL 90H;14位参考分频器低位

#DEFINE SCL PORTC,3
#DEFINE SDA PORTC,4

#DEFINE MAXGROUP .9
#DEFINE MAXCHANNEL .17
#DEFINE GROUPADDR .1
#DEFINE CHANNELADDR .0
#DEFINE POWERADDR .3
#DEFINE AFVOLADDR .4
#DEFINE IR_ERRTIME .50 ;高电平超时时间
;#DEFINE IR_READY FLAG,4
;#DEFINE IR_OK,FLAG,5
#DEFINE IRLINE PORTB,5
;/********************定义LCD1621B命令****************************/
#define BIAS 0X50      ;       //1/3偏压,4背极
#define RC256K 0X30    ;       //系统时钟选择为片内RC振荡器
#define WDT_DIS 0X0A    ;       //禁止WDT溢出标志输出
#define TIMER_DIS 0X08   ;        //时基输出禁止
#define SYS_EN 0X02    ;          //打开系统时钟
#define SYS_DIS 0X00    ;         //关闭系统时钟和偏压发生器
#define LCD_ON 0X06    ;        //打开LCD偏压发生器
#define LCD_OFF 0X04    ;    //关闭LCD偏压发生器
#define TONE_ON  0X12   ;    //打开音频输出
#define TONE_OFF 0X10   ;    //关闭音频输出  

;#DEFINE LED_FLAG FLAG,3
;#DEFINE LED PORTB ,3
#DEFINE LCD_DAT PORTC,4
#DEFINE LCD_WR  PORTC,3
#DEFINE LCD_CS  PORTC,5
;****POWR****************
#DEFINE POWER PORTC,0
#DEFINE RFMUTE PORTA,4

;*************KEY****************
#DEFINE POWERKEY PORTB,7
#DEFINE SETKEY PORTB,6
#DEFINE UPKEY        PORTB,5
#DEFINE DOWNKEY PORTB,4
#DEFINE ASCKEY PORTB,3
#DEFINE STOPKEY .10 ;按键计时最长时间
#DEFINE STOPPOWERKEY .30 ;POWER按键计时的最长时间
#DEFINE KEYSEL .5 ;判断按键长短按的依据

#DEFINE L_POWERKEY KEYFLAGA,0
#DEFINE S_POWERKEY KEYFLAGA,1
#DEFINE L_SETKEY KEYFLAGA,2
#DEFINE S_SETKEY KEYFLAGA,3
#DEFINE L_UPKEY KEYFLAGA,4
#DEFINE S_UPKEY KEYFLAGA,5
#DEFINE L_DOWNKEY KEYFLAGA,6
#DEFINE S_DOWNKEY KEYFLAGA,7

#DEFINE L_ASCKEY KEYFLAGB,0
#DEFINE S_ASCKEY KEYFLAGB,1

#DEFINE POWERSTA KEYFLAGB,2
#DEFINE MASTERLIST KEYFLAGB,3
#DEFINE AFVOLSTA KEYFLAGB,4
#DEFINE ASCSTA  KEYFLAGB,5
#DEFINE CHANNELSET KEYFLAGB,6
#DEFINE GROUPSET KEYFLAGB,7

#DEFINE LCD_FLASH FLASHFLAG,0 ;定义闪烁状态

;闪烁控制配置
#DEFINE FLASHTIMEA .10
#DEFINE FLASHTIMEB .10
;PWM IR
#DEFINE IRADDR 0XAA                                   
#DEFINE IRPWM  T2CON,2 ;PWM开关           
;AFADC峰值保持
#DEFINE AFADC_KEEP AFADCFLAG,0 ;峰值保持标志
#DEFINE AFADC_UPDATE AFADCFLAG,1 ;峰值更新标志   
;自由软件计数器
#DEFINE T1VOLA .2
#DEFINE T1VOLB .100
        ORG 000H      
        goto MAIN         
        ORG 0004H
;******************中断压栈****************
PUSH_ISR
        BANKSEL PORTA
        MOVWF W_TEMP
        SWAPF STATUS,W
        MOVWF STATUS_TEMP
        MOVF PCLATH,W
        MOVWF PCLATH_TEMP
        MOVF FSR,W
        MOVWF FSR_TEMP
;*************ISR*************************  
   

;***************返回出栈****************
POP_ISR
    BANKSEL PORTA
        MOVF PCLATH_TEMP,W
        MOVWF PCLATH
        SWAPF STATUS_TEMP,W
        MOVWF  STATUS
        MOVF FSR_TEMP,W
        MOVWF FSR;
        MOVF W_TEMP,W

        RETFIE
MAIN
           BANKSEL PORTA
           MOVLW .5
           MOVWF ADCON1
           CALL IO_INIT
           BCF POWER
       CALL HT1621B_INIT;
           CALL KEYIO_INIT
           CALL IIC_INIT
           CALL POWERSTACHECK       
       BTFSC POWERSTA
                 GOTO POWERON               
LOOPPOWER
           CALL KEY_SCAN
           BTFSS L_POWERKEY
                        GOTO LOOPPOWER
POWERON
           CALL DATA_INIT;
           BSF POWER
           BSF POWERSTA
           CALL POWERSTASAVE
           CALL SYSEN
           CALL LCDON;
       BANKSEL PORTB
       CALL ADC_INIT
       CLRF ADDR;
       MOVLW  0FH
       MOVWF  DAT
       CALL DISPLAY_TEST
       MOVLW .100
       CALL DELAY_MS
       MOVLW .100
       CALL DELAY_MS
       CALL PLL_INIT;
           CALL SEND_PLL_FREQUENCY
           BANKSEL PORTA
HOILPPOWERKEYA         
      BTFSS POWERKEY
             GOTO HOILPPOWERKEYA
          BCF RFMUTE
          PAGESEL BANK1SEL
          CALL TIME2_PWMINIT
loop  
       CALL ADC_RFCHANGE
       CALL ADC_AFCHANGE

           CALL LCD_RUN     
       CALL KEY_PROCE
           BTFSC L_POWERKEY
                GOTO POWEROFF
       PAGESEL MAIN
           goto loop;
POWEROFF
        BANKSEL PORTA
        BSF RFMUTE
        BCF POWERSTA
        CALL POWERSTASAVE
        CALL LCDOFF
        CALL SYSDIS
        BSF RFMUTE
        BCF POWER
HOILPPOWERKEYB         
      BTFSS POWERKEY
             GOTO HOILPPOWERKEYB
        GOTO LOOPPOWER

;**********IO_INIT*****************
IO_INIT
        BANKSEL TRISA
        MOVLW .7
        MOVWF TRISA
        CLRF TRISB
        CLRF TRISC
        BANKSEL PORTA
        MOVLW 10H
        MOVWF PORTA ;RFMUTE
        MOVLW 0F8H
        MOVWF PORTB
        CLRF PORTC  ;POWRN OFF
        RETURN
;***************KEY键值处理,菜单*****************
KEY_PROCE
        CALL KEY_SCAN
        ;检测是否是SET,菜单入口
        BTFSS S_SETKEY
          GOTO KEY_NEXT1
        BSF MASTERLIST ;菜单状态打开
        BSF GROUPSET
        BCF CHANNELSET
        BSF LCD_FLASH
        CALL LED_TIMERESET ;重设时钟,阻止退出菜单
;等待按键弹起
KEY_PROCESTOP
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN       
    CALL FLASH_TIME
        BANKSEL PORTA
        BTFSS SETKEY  ;检测SET键,等待弹起
             GOTO KEY_PROCESTOP
        ;GTOUP SET菜单
GROUPSETLOOP
        CALL KEYFUNCTION
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN
    CALL FLASH_TIME
        CALL TIME0_ISR
        BANKSEL PORTA
        BTFSS MASTERLIST
             GOTO END_MANU
        BTFSS S_SETKEY
         GOTO GROUPSETLOOP       
        BCF GROUPSET
        BSF CHANNELSET
        BSF LCD_FLASH
        CALL LED_TIMERESET ;重设时钟,阻止退出菜单
   ;CHANNEL SET菜单
CHANNELSETLOOP
        CALL KEYFUNCTION
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN
    CALL FLASH_TIME
        CALL TIME0_ISR
        BANKSEL PORTA
        BTFSS MASTERLIST
             GOTO END_MANU
        BTFSS S_SETKEY
            GOTO  CHANNELSETLOOP
END_MANU
        BCF MASTERLIST
        BCF CHANNELSET
        BCF GROUPSET
        BCF LCD_FLASH
        GOTO END_MANU2
KEY_NEXT1  ;扫描ASC按键
        BTFSS S_ASCKEY
           GOTO KEY_NEXT2
        BANKSEL PORTA
        BSF ASCSTA
   ; BCF MASTERLIST
        BANKSEL TRISB
        CLRF IRSENDCOUNTER
        INCF IRSENDCOUNTER,F
        CLRF IRDISDATA
        CALL LED_TIMERESET ;重设时钟,阻止退出菜单
IR_FUNC2
        CALL KEYFUNCTION
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN
        PAGESEL BANK1SEL
        CALL IR_SEND_DAT
        PAGESEL MAIN
        CALL IR_SEND_DIS
        CALL TIME0_ISR
        BANKSEL PORTA
        MOVLW .7
        SUBWF RFLVL,W
        SKPNC
                GOTO END_IRFUNC
        BTFSS SETKEY
            GOTO $+3
        BTFSC ASCSTA
                GOTO IR_FUNC2
END_IRFUNC
        BCF ASCSTA
        GOTO END_MANU
KEY_NEXT2 ;待机情况下检测上下按键
        BTFSS S_UPKEY
                GOTO KEY_NEXT3
        BSF AFVOLSTA
        CALL LED_TIMERESET ;重设时钟,阻止退出菜单
VOL_FUNC
        CALL KEYFUNCTION
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN
        CALL TIME0_ISR       
        BANKSEL PORTA
        BTFSS SETKEY
                GOTO ENDVOLFUNC
        BTFSS POWERKEY
                GOTO ENDVOLFUNC
        BTFSC AFVOLSTA
                GOTO VOL_FUNC
ENDVOLFUNC
        BCF AFVOLSTA
        GOTO END_MANU
KEY_NEXT3
        BTFSS S_DOWNKEY
                GOTO KEY_NEXT4
        BSF AFVOLSTA
        CALL LED_TIMERESET ;重设时钟,阻止退出菜单
        GOTO VOL_FUNC
KEY_NEXT4
END_MANU2
        RETURN       
;*************IR 显示*******************
;IRSENDCOUNTER起始值必须为1
IR_SEND_DIS
        BANKSEL TRISB       
IRDISNEXT0  ;点亮第1格
        BTFSS IRSENDCOUNTER,0
                GOTO IRDISNEXT1
        CLRF IRDISDATA
        GOTO IRDISCOUNTER
IRDISNEXT1 ;点亮第2格
        BTFSS IRSENDCOUNTER,1
                GOTO IRDISNEXT2
        BSF IRDISDATA,3
        GOTO IRDISCOUNTER
IRDISNEXT2 ;点亮第3格
        BTFSS IRSENDCOUNTER,2
                GOTO IRDISNEXT3
        BSF IRDISDATA,2
        GOTO IRDISCOUNTER
IRDISNEXT3 ;点亮第4格
        BTFSS IRSENDCOUNTER,3
                GOTO IRDISNEXT4
        BSF IRDISDATA,1
        GOTO IRDISCOUNTER
IRDISNEXT4 ;点亮第5格
        BTFSS IRSENDCOUNTER,4
                GOTO IRDISCOUNTER
        BSF IRDISDATA,0
IRDISCOUNTER ;左移5位
        CLRC
        RLF IRSENDCOUNTER,F
        BTFSS IRSENDCOUNTER,6
                GOTO IRDISCOUNTEREND
        CLRF IRSENDCOUNTER
        INCF IRSENDCOUNTER,F
IRDISCOUNTEREND
        RETURN
;***********菜单上下键操作********************
KEYFUNCTION
        CALL KEY_SCAN
    BANKSEL PORTA
        ;下按键操作
        BTFSS S_DOWNKEY
            GOTO KEYFUCTION_NEXT ;下一按键
        CALL LED_TIMERESET ;重设时钟,阻止退出菜单
        BTFSS MASTERLIST
                GOTO KEYVOLSET
    BTFSS GROUPSET  ;当前是否是GROUP设置
            GOTO KEYCHANNELSET ;否则进行下一个判断
        DECFSZ GROUP,F  ;是否减到0
            GOTO $+3 ;继续
        MOVLW .9  ;减到0则设置GROUP最大值
        MOVWF GROUP
        CALL PLLDATACHANGE
KEYCHANNELSET
        BTFSS CHANNELSET
             GOTO KEYVOLSET
        DECFSZ CHANNEL,F
                GOTO $+3 ;没有,继续
        MOVLW .16  ;减到0则设置GROUP最大值
        MOVWF CHANNEL
        CALL PLLDATACHANGE
KEYVOLSET  ;按键设置--VOL
        BTFSS AFVOLSTA
                GOTO END_KEYFUNCTION
        MOVF AF_VOL,W
        SKPNZ
                GOTO END_KEYFUNCTION
        DECFSZ AF_VOL,F  ;是否减到0
            GOTO $+2
        CLRF AF_VOL
        CALL SAVE_DAT_VOL
        CALL VOL_SET
        GOTO END_KEYFUNCTION               
;*******************************
   ;上按键设置       
KEYFUCTION_NEXT
        BTFSS S_UPKEY
            GOTO KEYFUCTION_NEXT2 ;下一按键
        CALL LED_TIMERESET ;重设时钟,阻止退出菜单
        BTFSS MASTERLIST
                GOTO KEYVOLSET2
    BTFSS GROUPSET  ;当前是否是GROUP设置
            GOTO KEYCHANNELSET2 ;否则进行下一个判断
        INCF GROUP,F  ;是否减到0
        MOVLW .10
        SUBWF GROUP ,W
        SKPC
            GOTO $+3  ;没有,继续
        CLRF GROUP
        INCF GROUP,F
        CALL PLLDATACHANGE
KEYCHANNELSET2
        BTFSS CHANNELSET
             GOTO KEYVOLSET2
        INCF CHANNEL,F
        MOVLW .17
        SUBWF CHANNEL ,W
        SKPC
                GOTO $+3  ;没有,继续
        CLRF CHANNEL
        INCF CHANNEL,F
        CALL PLLDATACHANGE
KEYVOLSET2;按键设置++VOL
        BTFSS AFVOLSTA
                GOTO END_KEYFUNCTION
;        INCFSZ AF_VOL,F  ;是否+到0
;                GOTO END_KEYFUNCTION
;        COMF AF_VOL,F
        INCF AF_VOL,F
        MOVLW .64
        SUBWF AF_VOL,W
        SKPC
                GOTO $+3
        MOVLW .63
        MOVWF AF_VOL
        CALL SAVE_DAT_VOL
        CALL VOL_SET
        GOTO END_KEYFUNCTION
;ASC按键       
KEYFUCTION_NEXT2
        BTFSS S_ASCKEY
            GOTO KEYFUCTION_NEXT3
        BTFSS MASTERLIST       
                GOTO $+3
        BCF MASTERLIST
        GOTO $+2
        BCF AFVOLSTA
    BCF ASCSTA
        BCF LCD_FLASH
        GOTO END_KEYFUNCTION
;****************长按键检测,实现长按按键加减功能*************************//
KEYFUCTION_NEXT3
        BTFSC MASTERLIST
        BTFSS L_UPKEY  ;上按键长按功能
                GOTO KEYFUCTION_NEXT4
        BCF LCD_FLASH ;关闭闪烁
        BTFSS GROUPSET
                GOTO KEYFUCTION_CHANNELLONGKEYSET;是不是组设置,不是跳出
;GROUP快速+设置
GROUP_LONGUPSET
        BANKSEL PORTA
        BTFSC UPKEY  ;长按弹起后退出
                GOTO PLLDATACHANGE
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN
    MOVLW .30
    CALL DELAY_MS
        INCF GROUP,F
        MOVLW .10
        SUBWF GROUP,W
        SKPC
                GOTO $+3
        CLRF GROUP
        INCF GROUP,F
        GOTO GROUP_LONGUPSET
;CHANNEL 快速+设置
KEYFUCTION_CHANNELLONGKEYSET
        BTFSC UPKEY  ;长按弹起后退出
                GOTO PLLDATACHANGE
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN
    MOVLW .30
    CALL DELAY_MS
        INCF CHANNEL,F
        MOVLW .16
        SUBWF CHANNEL,W
        SKPC
                GOTO $+3
        CLRF CHANNEL
        INCF CHANNEL,F
        GOTO KEYFUCTION_CHANNELLONGKEYSET        
;下按键长按功能
KEYFUCTION_NEXT4
        BTFSC MASTERLIST
        BTFSS L_DOWNKEY
                   GOTO KEYFUCTION_NEXT5
        BCF LCD_FLASH ;关闭闪烁
        BTFSS GROUPSET
                GOTO KEYFUCTION_CHANNELLONGKEYSET2;是不是组设置,不是跳出
;GROUP快速-减设置
GROUP_LONGUPSET1
        BTFSC DOWNKEY  ;长按弹起后退出
                GOTO PLLDATACHANGE
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN
    MOVLW .30
    CALL DELAY_MS
        DECFSZ GROUP,F
                GOTO $+3
        MOVLW .9
        MOVWF GROUP
        GOTO GROUP_LONGUPSET1
;CHANNEL 快速-减设置
KEYFUCTION_CHANNELLONGKEYSET2
        BTFSC DOWNKEY  ;长按弹起后退出
                GOTO PLLDATACHANGE
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN
    MOVLW .30
    CALL DELAY_MS
        DECFSZ CHANNEL,F
                GOTO $+3
        MOVLW .16
        MOVWF CHANNEL       
        GOTO KEYFUCTION_CHANNELLONGKEYSET2        
PLLDATACHANGE
    CALL SEND_PLL_FREQUENCY
        CALL SAVE_DAT
        GOTO END_KEYFUNCTION
;*************待机长按实现音量快速+/-
;AF VOL ++
KEYFUCTION_NEXT5  
        BTFSC AFVOLSTA
        BTFSS L_UPKEY
                GOTO KEYFUCTION_NEXT6
AFVOLLOOPSET
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN
    MOVLW .20
    CALL DELAY_MS
        INCF AF_VOL,F
        MOVLW .64
        SUBWF AF_VOL,W
        SKPC
                GOTO $+3
        MOVLW .63
        MOVWF AF_VOL
        CALL SAVE_DAT_VOL
        CALL VOL_SET
        BTFSS UPKEY
                GOTO AFVOLLOOPSET       
;AF VOL --       
KEYFUCTION_NEXT6
        BTFSC AFVOLSTA
        BTFSS L_DOWNKEY
                GOTO KEYFUCTION_NEXT7
AFVOLLOOPSET2
        CALL ADC_RFCHANGE
        CALL ADC_AFCHANGE
        CALL LCD_RUN
    MOVLW .20
    CALL DELAY_MS
        MOVF AF_VOL,W
        SKPNZ
                GOTO $+3
        DECFSZ AF_VOL,F  ;是否减到0
            GOTO $+2 ;没有,继续
        CLRF AF_VOL
        CALL SAVE_DAT_VOL
        CALL VOL_SET
        BTFSS DOWNKEY
                GOTO AFVOLLOOPSET2
;此处可以加上其他功能
KEYFUCTION_NEXT7
        NOP ;此处可以加上其他功能
END_KEYFUNCTION
        RETURN

;***********KEY********************
KEYIO_INIT
        BANKSEL TRISB
        MOVLW 8FH
        IORWF TRISB,F
        RETURN               
KEY_SCAN
;判断POWER按键
        BANKSEL PORTB
        CLRF KEYFLAGA
        MOVLW 0FCH
        ANDWF KEYFLAGB,F
        BTFSC POWERKEY
            GOTO KEY_NEXTA  ;处理下一个按键
        MOVLW .10
        CALL DELAY_MS  
KEYLOOP1
        BTFSC POWERKEY
            GOTO KEYEND1
        INCF KEYTEMP,F  ;延时20MS后计数
        MOVLW .20
        CALL DELAY_MS         
        MOVLW STOPPOWERKEY
        SUBWF KEYTEMP,W
        BTFSC STATUS,C
                GOTO KEYEND1 ;按键超时退出处理键值
        GOTO KEYLOOP1 ;否则进行按键处理
KEYEND1
        CLRC ;判断长短按
        MOVLW KEYSEL
        SUBWF KEYTEMP,W
        SKPNC
                GOTO P_L
        BSF S_POWERKEY
        BCF L_POWERKEY       
        GOTO P_S
P_L BCF S_POWERKEY
        BSF L_POWERKEY       
P_S        
        CLRF KEYTEMP
        GOTO KEY_STOP
;判断SET按键
KEY_NEXTA
        BTFSC SETKEY
            GOTO KEY_NEXTB  ;处理下一个按键
        MOVLW .10
        CALL DELAY_MS  
KEYLOOP2
        BTFSC SETKEY
            GOTO KEYEND2
        INCF KEYTEMP,F  ;延时20MS后计数
        MOVLW .20
        CALL DELAY_MS         
        MOVLW STOPKEY
        SUBWF KEYTEMP,W
        BTFSC STATUS,C
                GOTO KEYEND2 ;按键超时退出处理键值
        GOTO KEYLOOP2 ;否则进行按键处理
KEYEND2
;        CLRC ;判断长短按
        MOVLW KEYSEL
        SUBWF KEYTEMP,W
        SKPNC
                GOTO S_L
        BSF S_SETKEY
        BCF L_SETKEY       
        GOTO S_S
S_L BCF S_SETKEY
        BSF L_SETKEY       
S_S        
        CLRF KEYTEMP
        GOTO KEY_STOP
;判断UP按键
KEY_NEXTB
        BTFSC UPKEY
            GOTO KEY_NEXTC  ;处理下一个按键
        MOVLW .10
        CALL DELAY_MS  
KEYLOOP3
        BTFSC UPKEY
            GOTO KEYEND3
        INCF KEYTEMP,F  ;延时20MS后计数
        MOVLW .20
        CALL DELAY_MS         
        MOVLW STOPKEY
        SUBWF KEYTEMP,W
        BTFSC STATUS,C
                GOTO KEYEND3 ;按键超时退出处理键值
        GOTO KEYLOOP3 ;否则进行按键处理
KEYEND3
;        CLRC ;判断长短按
        MOVLW KEYSEL
        SUBWF KEYTEMP,W
        SKPNC
                GOTO U_L
        BSF S_UPKEY
        BCF L_UPKEY       
        GOTO S_S
U_L BCF S_UPKEY
        BSF L_UPKEY       
U_S        
        CLRF KEYTEMP
        GOTO KEY_STOP
;判断DOWN按键
KEY_NEXTC
        BTFSC DOWNKEY
            GOTO KEY_NEXTD  ;处理下一个按键
        MOVLW .10
        CALL DELAY_MS  
KEYLOOP4
        BTFSC DOWNKEY
            GOTO KEYEND4
        INCF KEYTEMP,F  ;延时20MS后计数
        MOVLW .20
        CALL DELAY_MS         
        MOVLW STOPKEY
        SUBWF KEYTEMP,W
        BTFSC STATUS,C
                GOTO KEYEND4 ;按键超时退出处理键值
        GOTO KEYLOOP4 ;否则进行按键处理
KEYEND4
;        CLRC ;判断长短按
        MOVLW KEYSEL
        SUBWF KEYTEMP,W
        SKPNC
                GOTO D_L
        BSF S_DOWNKEY
        BCF L_DOWNKEY       
        GOTO D_S
D_L BCF S_DOWNKEY
        BSF L_DOWNKEY       
D_S        
        CLRF KEYTEMP
        GOTO KEY_STOP
;判断ASC按键
KEY_NEXTD
        BTFSC ASCKEY
            GOTO KEY_STOP  ;处理下一个按键
        MOVLW .10
        CALL DELAY_MS  
KEYLOOP5
        BTFSC ASCKEY
            GOTO KEYEND5
        INCF KEYTEMP,F  ;延时20MS后计数
        MOVLW .20
        CALL DELAY_MS         
        MOVLW STOPKEY
        SUBWF KEYTEMP,W
        BTFSC STATUS,C
                GOTO KEYEND5 ;按键超时退出处理键值
        GOTO KEYLOOP5 ;否则进行按键处理
KEYEND5
;        CLRC ;判断长短按
        MOVLW KEYSEL
        SUBWF KEYTEMP,W
        SKPNC
                GOTO A_L
        BSF S_ASCKEY
        BCF L_ASCKEY       
        GOTO A_S
A_L BCF S_ASCKEY
        BSF L_ASCKEY       
A_S        
        CLRF KEYTEMP
KEY_STOP
        RETURN
;*********************DATA INIT**********************/
DATA_INIT
;**********将内存清零
    BANKSEL PORTA;
RAM_CLR
        MOVLW 20h
        MOVWF FSR
CLRNEXT
        CLRF INDF
        INCF FSR,F
        MOVLW 7FH
        SUBWF FSR,W       
        SKPC
                GOTO CLRNEXT
        BANKSEL TRISB
        MOVLW 0A0h
        MOVWF FSR
CLRNEXT2
        MOVLW 0A0H
        MOVWF FSR
CLRNEXT3
        CLRF INDF
        INCF FSR,F
        MOVLW 0FFH
        SUBWF FSR,W       
        SKPC
                GOTO CLRNEXT3       
;********读取上次保持的数据**************************
READ_DATA
        BANKSEL PORTA
    CLRF IIC_DATTEMP
    MOVLW CHANNELADDR
    MOVWF IIC_ADDR
    MOVLW 0A0H
    MOVWF IIC_DEVADDR
    CALL READ_IIC
        MOVF IIC_DATTEMP,W
        MOVWF DATAA
   

    CLRF IIC_DATTEMP
    MOVLW GROUPADDR
    MOVWF IIC_ADDR
        MOVLW 0A0H
        MOVWF IIC_DEVADDR
        CALL READ_IIC
        MOVF IIC_DATTEMP,W
        MOVWF DATAB

        BANKSEL PORTA
    CLRF IIC_DATTEMP
    MOVLW AFVOLADDR
    MOVWF IIC_ADDR
    MOVLW 0A0H
    MOVWF IIC_DEVADDR
    CALL READ_IIC
        MOVF IIC_DATTEMP,W
        MOVWF AF_VOL
        MOVLW .64
        SUBWF AF_VOL,W
        SKPNC
                GOTO RESETAFVOL
        GOTO $+3
RESETAFVOL
        MOVLW .63
        MOVWF AF_VOL       
        CALL VOL_SET       
;***********检测数据正确性************
;GOTO OK_DATA
        CALL TEST_DATA
;**********显示数据,IR数据初始化************

        RETURN
;************数据测试,正确返回0,不正确返回1************
TEST_DATA
  ;测试CHANENL ,GROUP
    MOVLW MAXCHANNEL
        SUBWF DATAA,W       
        SKPC
             GOTO OK_NEXT ;说明F<16,数据正常
    GOTO RESET_DATA
OK_NEXT
    MOVLW MAXGROUP
        SUBWF DATAB,W       
        SKPC
                     GOTO OK_DAT ;说明F<16,数据正常
RESET_DATA
    CLRF CHANNEL
        CLRF GROUP
        INCF CHANNEL,F
        INCF GROUP,F
        GOTO DATA_NEXT
OK_DAT
        MOVF DATAA,W
        MOVWF CHANNEL
        MOVF DATAB,W
    MOVWF GROUP   
DATA_NEXT
        RETURN
;*************************LCD刷屏显示程序**********************
LCD_RUN
      BANKSEL PORTA
;*********显示组号***************
          BSF DIS_FLAG ;显示RF LV标尺;
          BTFSS MASTERLIST ;如果不是菜单状态
               GOTO NONMASTERLIST
          BTFSC LCD_FLASH
               GOTO LCD_MANUFLASH
NONMASTERLIST
;不闪烁状态
      MOVLW .0
      MOVWF ADDR
      MOVF GROUP ,W
      CALL DISPLAY_720HT     ;显示组号

      MOVLW .2
      MOVWF ADDR
      MOVF CHANNEL,W
          MOVWF ABC_DAT
          CALL CHANGE_ABC
          MOVF ABC_TEMPM,W ;提取CHANNEL的高位
      CALL DISPLAY_720HT ;显示通道号

      MOVLW .4
      MOVWF ADDR
      MOVF CHANNEL,W
          MOVWF ABC_DAT
          CALL CHANGE_ABC
          MOVF ABC_TEMPL,W ;提取CHANNEL的低位
      CALL DISPLAY_720HT ;显示通道号
          GOTO LCD_FRQDIS
;闪烁状态
LCD_MANUFLASH
          BTFSS GROUPSET
             GOTO CHANNELSET_FLASH ;当前是CHANNELSET
          CLRF ADDR
          CLRF DAT
      CALL WR_HT1621BDAT       
      INCF ADDR,F
          INCF DAT,F ;显示标志
      CALL WR_HT1621BDAT       

      MOVLW .2
      MOVWF ADDR
      MOVF CHANNEL,W
          MOVWF ABC_DAT
          CALL CHANGE_ABC
          MOVF ABC_TEMPM,W ;提取CHANNEL的高位
      CALL DISPLAY_720HT ;显示通道号

      MOVLW .4
      MOVWF ADDR
      MOVF CHANNEL,W
          MOVWF ABC_DAT
          CALL CHANGE_ABC
          MOVF ABC_TEMPL,W ;提取CHANNEL的低位
      CALL DISPLAY_720HT ;显示通道号
          GOTO LCD_FRQDIS
CHANNELSET_FLASH
           CLRF ADDR
       MOVF GROUP ,W
       CALL DISPLAY_720HT     ;显示组号

          MOVLW .2
          MOVWF  ADDR
          CLRF DAT
      CALL WR_HT1621BDAT       
      INCF ADDR,F
          INCF DAT ,F;显示标志
      CALL WR_HT1621BDAT       
      INCF ADDR,F
      CLRF DAT
      CALL WR_HT1621BDAT
      INCF ADDR,F
          INCF DAT ,F;显示标志
      CALL WR_HT1621BDAT


;******************显示频率表********************、
LCD_FRQDIS
          BTFSC AFVOLSTA
                    GOTO AFVOLDIS
          PAGESEL LCD_GETFRQDIS
          CALL LCD_GETFRQDIS                
      MOVLW .6  
      MOVWF ADDR
      MOVF DIS1,W
     CALL DISPLAY_720HT ;AF LV*********
      MOVLW .8
      MOVWF ADDR
      MOVF DIS2,W
     CALL DISPLAY_720HT
      MOVLW .10
      MOVWF ADDR
      MOVF DIS3,W
     CALL DISPLAY_720HT
      MOVLW .12
      MOVWF ADDR
      MOVF DIS4,W
     CALL DISPLAY_720HT
      MOVLW .14
      MOVWF ADDR
      MOVF DIS5,W
     CALL DISPLAY_720HT
      MOVLW .16
      MOVWF ADDR
      MOVF DIS6,W
     CALL DISPLAY_720HT
      BCF DIS_FLAG
    PAGESEL MAIN
         GOTO DIS_NEXT
;**************待机显示音量模式*****************************
AFVOLDIS
        BCF DIS_FLAG
;显示VOL
        MOVLW .6
        MOVWF ADDR
    MOVLW .7
    MOVWF DAT
    CALL WR_HT1621BDAT
    INCF ADDR,F
    MOVLW 0BH
    MOVWF DAT
    CALL WR_HT1621BDAT                

    MOVLW .8
    MOVWF ADDR
    MOVLW .0
    CALL DISPLAY_720HT

        MOVLW .10
        MOVWF ADDR
    MOVLW .1
    MOVWF DAT
    CALL WR_HT1621BDAT
    INCF ADDR,F
    MOVLW 0AH
    MOVWF DAT
    CALL WR_HT1621BDAT       
;显示AF数字
      BANKSEL PORTA
      MOVLW .12
      MOVWF ADDR
      MOVF AF_VOL,W
          MOVWF DIVIDEND
          MOVLW .100
          MOVWF DIVISOR
     ; PAGESEL DX_DATA
          CALL DX_DATA
          MOVF QUOTIENT,W ;提取AFVOL的高位
     ; PAGESEL MAIN
      CALL DISPLAY_720HT ;

      MOVLW .14  ;提取AFVOL的中间位
      MOVWF ADDR
          MOVF REMAIN,W ;
          MOVWF DIVIDEND
          MOVLW .10
          MOVWF DIVISOR
     ; PAGESEL DX_DATA
          CALL DX_DATA
     ; PAGESEL MAIN
          MOVF QUOTIENT,W
      CALL DISPLAY_720HT ;

      MOVLW .16  ;提取AFVOL的低位
      MOVWF ADDR
          MOVF REMAIN,W
      CALL DISPLAY_720HT ;

;**********IR********************
;不采用闪烁显示
DIS_NEXT
IR_DIS
        BTFSS ASCSTA
                GOTO NONIR
;        BTFSS LCD_FLASH
;            GOTO NONIR
        MOVLW .18
        MOVWF ADDR
;        MOVLW .0
        BANKSEL TRISB
        MOVF IRDISDATA,W
        BANKSEL PORTA
        MOVWF DAT
    CALL WR_HT1621BDAT
        BANKSEL PORTA
        INCF ADDR,F
        MOVLW 0ch ;显示标志和第1格
;        BANKSEL TRISB
;        MOVF IRDISDATB,W
;        BANKSEL PORTA
        MOVWF DAT
        CALL WR_HT1621BDAT       
        GOTO DIS_NEXT2
NONIR
        MOVLW .18
        MOVWF ADDR
        CLRF DAT
    CALL WR_HT1621BDAT
        INCF ADDR,F
        CALL WR_HT1621BDAT
;*********RF AF 显示**********
DIS_NEXT2
        MOVLW .20
        MOVWF ADDR
    MOVLW 0FH
    MOVWF DAT
    CALL WR_HT1621BDAT ;AF水平标尺

    INCF ADDR,F
    MOVF AFLVH,W
    MOVWF DAT
    CALL WR_HT1621BDAT

    INCF ADDR,F
    MOVLW 0FH
    MOVWF DAT
    CALL WR_HT1621BDAT ;AF水平标尺

    INCF ADDR,F
    MOVF AFLVL,W
    MOVWF DAT
    CALL WR_HT1621BDAT

    INCF ADDR,F
    MOVLW 0FH
    MOVWF DAT
    CALL WR_HT1621BDAT ;RF水平标尺

    INCF ADDR,F
    MOVF RFLVH,W
    MOVWF DAT
    CALL WR_HT1621BDAT

    INCF ADDR,F
    MOVLW 0FH
    MOVWF DAT
    CALL WR_HT1621BDAT;RF水平标尺

    INCF ADDR,F
    MOVF RFLVL,W
    MOVWF DAT
    CALL WR_HT1621BDAT

          RETURN
;***************从频率表中取6个数字,发送并显示*********
;DISTEMP1,求表地址
LCD_GETFRQDIS
        BANKSEL PORTA
;求表起始地址
        DECF GROUP,W
        MOVWF MULTAL
        CLRF MULTAH
        MOVLW .96
        MOVWF MULTBL
        CLRF MULTBH
        CALL MULT_DATA
        ;取运算结果并保持       
        MOVF MULTCL,W
        MOVWF DISTEMP1
        MOVF MULTCH,W
        MOVWF DISTEMP2

        MOVF CHANNEL,W
        MOVWF MULTAL
        CLRF MULTAH
        MOVLW .6
    MOVWF MULTBL
        CLRF MULTBH       
        CALL MULT_DATA
    ;计算绝对地址
    MOVF MULTCL,W
        ADDWF DISTEMP1,F
        SKPC
          GOTO NOCARRY
        INCF MULTCH,W
        ADDWF DISTEMP2,W
        GOTO ADDOFFSET
NOCARRY       
    MOVF MULTCH,W
        ADDWF DISTEMP2,W
ADDOFFSET
        MOVWF OFFSETH
        MOVF DISTEMP1,W
        MOVWF OFFSETL



;一共需要取6位数据
;        MOVWF OFFSETL
        PAGESEL TABLE_DISP
        CALL TABLE_DISP
        PAGESEL MAIN
        MOVWF DIS1
        INCF OFFSETL,F
        PAGESEL TABLE_DISP
        CALL TABLE_DISP
        PAGESEL MAIN
        MOVWF DIS2       
        INCF OFFSETL,F
        PAGESEL TABLE_DISP
        CALL TABLE_DISP
        PAGESEL MAIN
        MOVWF DIS3       
        INCF OFFSETL,F
        PAGESEL TABLE_DISP
        CALL TABLE_DISP
        PAGESEL MAIN
        MOVWF DIS4       
        INCF OFFSETL,F
        PAGESEL TABLE_DISP
        CALL TABLE_DISP
        PAGESEL MAIN
        MOVWF DIS5       
        INCF OFFSETL,F
        PAGESEL TABLE_DISP
        CALL TABLE_DISP
        PAGESEL MAIN
        MOVWF DIS6
        RETURN


;****************两位数取模**********
;参数ABC_DAT
CHANGE_ABC
        BANKSEL PORTA
        CLRF ABC_TEMPL
    CLRF ABC_TEMPM
        CLRF ABC_TEMPH
        BCF STATUS,C
        MOVLW .10
        SUBWF ABC_DAT,W
        SKPNC
                GOTO $+4
        MOVF ABC_DAT,W
        MOVWF ABC_TEMPL
        GOTO $+3
        MOVWF ABC_TEMPL;
        INCF ABC_TEMPM,F;               
END_ABC
        RETURN         
;**********************显示一个字程序***************************/
;形参 TABLETEMPW  ADDR
DISPLAY_720HT
    BANKSEL PORTA
         MOVWF TABLETEMP
    CLRF OFFSETH
        PAGESEL LCD_GETDAT
           CALL LCD_GETDAT
    PAGESEL MAIN
    MOVF TEMPL,W
    MOVWF DAT
    CALL WR_HT1621BDAT
    INCF ADDR,F
    MOVF TEMPH,W
    MOVWF DAT
    CALL WR_HT1621BDAT
        RETURN

;***************T0中断设置函数******************************
TMRO_INIT
  ;形参 W
   ANDLW 07h; 将R1与0XF8相与
   BANKSEL TRISB
   CLRF OPTION_REG
   BSF OPTION_REG,7
   IORWF  OPTION_REG,f;  写入OPTION低3位
   BANKSEL PORTA
   MOVLW T0A;
   MOVWF T0COUNTERA;
   MOVLW T0B;
   MOVWF T0COUNTERB;
   CLRF TMR0;
   BCF INTCON,T0IF;清零T0IF
   BSF INTCON,T0IE;允许中断
   RETURN
;**********************显示测试程序*******************/
;用到ADDR 与DAT参数
DISPLAY_TEST
        BANKSEL PORTA
DISPLAY_TESTA
    CALL WR_HT1621BDAT
    INCF ADDR,F
    BTFSS ADDR,5   
        goto DISPLAY_TESTA
    RETURN
;*******************LCD_IO口设置函数********************
HT1621B_INIT
   BANKSEL PORTC
   MOVLW 038H
   IORWF PORTC,F;
   BANKSEL TRISC;
   MOVLW 0C7H
   ANDWF TRISC,F; 设置输出
   BANKSEL PORTA
   MOVLW .5
   CALL DELAY_MS
   MOVLW BIAS
   MOVWF CMD
   CALL WR_HT1621BCMD
   MOVLW .5
   CALL DELAY_MS
   MOVLW RC256K
   MOVWF CMD
   CALL WR_HT1621BCMD
   MOVLW .5
   CALL DELAY_MS
   CALL SYSEN
   MOVLW WDT_DIS
   MOVWF CMD
   CALL WR_HT1621BCMD
   MOVLW .5
   CALL DELAY_MS
   MOVLW TIMER_DIS
   MOVWF CMD
   CALL WR_HT1621BCMD
   MOVLW .5
   CALL DELAY_MS
LCDOFF
   MOVLW LCD_OFF
   MOVWF CMD
   CALL WR_HT1621BCMD
   MOVLW .5
   CALL DELAY_MS
   RETURN
LCDON
   MOVLW LCD_ON
   MOVWF CMD
   CALL WR_HT1621BCMD
   MOVLW .5
   CALL DELAY_MS
   RETURN
SYSEN
   MOVLW SYS_EN
   MOVWF CMD
   CALL WR_HT1621BCMD
   MOVLW .5
   CALL DELAY_MS
   RETURN
SYSDIS
   MOVLW SYS_DIS
   MOVWF CMD
   CALL WR_HT1621BCMD
   MOVLW .5
   CALL DELAY_MS
   RETURN
;***********************1621HT数据函数************************
;地址ADDR  数据DAT,不能》16 用到R0/R1:ADDR/R2:DAT
WR_HT1621BDAT
   BANKSEL PORTA
  ;ADDR 左移3次
   MOVLW .2
   MOVWF R0;
   MOVF ADDR,W
   MOVWF R1
HT1621B1
   BCF STATUS,C
   RLF R1,F
   DECFSZ R0,F
     GOTO HT1621B1
   ;DAT左移4次
   MOVF DAT,W
   MOVWF R2
   MOVLW .4
   MOVWF R0;
HT1621B2
   BCF STATUS,C
   RLF R2,F
   DECFSZ R0,F
     GOTO HT1621B2
   BCF LCD_CS;
   BCF LCD_WR;
   BSF LCD_DAT;1
   BSF LCD_WR;

   BCF LCD_WR
   BCF LCD_DAT;0
   BSF LCD_WR

   BCF LCD_WR
   BSF LCD_DAT;1
   BSF LCD_WR
   ;写5位地址数据
   MOVLW .6
   MOVWF R0;
HT1621B3 ;左移5次
   BCF LCD_WR
   RLF R1,F
   BTFSS STATUS,C
       GOTO $+3
   BSF LCD_DAT ;写数据1
   GOTO $+2
   BCF LCD_DAT;写数据0
   BSF LCD_WR
   DECFSZ R0,F;判断是否有5次?
     GOTO HT1621B3
   ;写4位数据
   MOVLW .4
   MOVWF R0;
HT1621B4 ;左移4次
   BCF LCD_WR
   RLF R2,F
   BTFSS STATUS,C
       GOTO $+3
   BSF LCD_DAT ;写数据1
   GOTO $+2
   BCF LCD_DAT;写数据0
   BSF LCD_WR
   DECFSZ R0,F;判断是否有4次?
     GOTO HT1621B4  
   BSF LCD_CS
   RETURN
;***********************1621HT命令函数************************
;形参CMD 用到R0/R1
WR_HT1621BCMD
   BANKSEL PORTA
   MOVLW .8
   MOVWF R0;
   MOVF CMD,W
   MOVWF R1
   ;写数据头
   BCF LCD_CS;
   BCF LCD_WR;
   BSF LCD_DAT;1
   BSF LCD_WR;

   BCF LCD_WR
   BCF LCD_DAT;0
   BSF LCD_WR

   BCF LCD_WR
   BCF LCD_DAT;0
   BSF LCD_WR

   BCF LCD_WR
   BCF LCD_DAT;0
   BSF LCD_WR
   ;写数据
HT1621B5 ;左移8次
   BCF LCD_WR
   RLF R1,F
   BTFSS STATUS,C
      GOTO $+3
   BSF LCD_DAT ;写数据1
   GOTO $+2
   BCF LCD_DAT;写数据0
   BSF LCD_WR
   DECFSZ R0,F;判断是否有8次?
     GOTO HT1621B5  
   BSF LCD_CS
   RETURN
;*************************写1621*****************************

;*********************延时*MS*******************************************
DELAY_MS;形参用W传送
        BANKSEL PORTA
        MOVWF COUNTERMSB
    MOVLW .10
DELAY_MS1
    CALL DELAY_100US
    DECFSZ COUNTERMSB,F
         GOTO DELAY_MS1
       RETURN
;**********************延时100US函数**********************************
DELAY_100US;形参用W传送
           ;条件判断为真时指令周期为2US,为假时1US,RETURN 2US
            ;T=1+{[1+1+(1+2)*(B-1)+2+(1+2)]*(A-1)+2+2
   BANKSEL PORTA
    MOVWF COUNTERA; 1US         
DELAY_US1
    MOVLW .32       ;单位为100US
    MOVWF COUNTERB;   
DELAY_US2
    DECFSZ COUNTERB,F
       GOTO DELAY_US2;内循环
    DECFSZ COUNTERA,F
      GOTO DELAY_US1;外循环
   
   RETURN
;*******************PLL驱动程序*****************
PLL_INIT
    BANKSEL TRISC
        BCF TRISB,0
        BCF TRISB,1
        BCF TRISB,2
        BANKSEL PORTC
        BSF PLL_CS
        BSF PLL_DAT
        BSF PLL_CLK

    BANKSEL PORTC
    BCF PLL_CS        ;拉低,开始写数据
        MOVLW PLL_CMD
        MOVWF PLL_DATTEMP
        MOVLW .4  ;写4位控制位
    MOVWF R0  
        CALL  WR_PLLDAT

        MOVLW PLL_FRTEMPH;写6位高位参考分频器
        MOVWF PLL_DATTEMP   
    RLF PLL_DATTEMP,F  ;左移两位
        RLF PLL_DATTEMP,F
        MOVLW .6
        MOVWF R0   
        CALL  WR_PLLDAT ;写6位

        MOVLW PLL_FRTEMPL ;写8位低位参考分频器
        MOVWF PLL_DATTEMP   
        MOVLW .8
        MOVWF R0
        CALL  WR_PLLDAT

        BCF PLL_CLK  ;写分频器选择位
        BSF PLL_DAT
        BSF PLL_CLK
        BSF PLL_CS
    RETURN  
;***********************SEND FRUENCY**********************
SEND_PLL_FREQUENCY
    BANKSEL PORTC
    BCF PLL_CS        ;拉低,开始写数据
;**********读表**************
;        MOVLW .5
;        MOVWF CHANNEL
;        MOVLW .7
;        MOVWF GROUP
    DECF GROUP,W
    MOVWF MULTAL
        CLRF MULTAH
    MOVLW .48
        MOVWF MULTBL
        CLRF MULTBH
    CALL MULT_DATA
        MOVF MULTCL,W
        MOVWF TABTEMPA;
    MOVF MULTCH,W
        MOVWF TABTEMPB

    MOVF CHANNEL,W
    MOVWF MULTAL
        CLRF MULTAH
    MOVLW .3
        MOVWF MULTBL
        CLRF MULTBH
    CALL MULT_DATA
        ;计算绝对地址
    MOVF MULTCL,W
        ADDWF TABTEMPA,F
        SKPC
           GOTO $+4
        INCF MULTCH,W
        ADDWF TABTEMPB,W
    GOTO $+3
        MOVF MULTCH,W
        ADDWF TABTEMPB,W
   
        MOVWF OFFSETH
        MOVF TABTEMPA,W
        MOVWF OFFSETL
    ;取3个数据
        PAGESEL TABLE_PROG
    CALL TABLE_PROG;
        PAGESEL MAIN
    MOVWF PLL_PCTEMPH
        INCF OFFSETL,F
        PAGESEL TABLE_PROG
    CALL TABLE_PROG;
        PAGESEL MAIN
    MOVWF PLL_PCTEMPL
        INCF OFFSETL,F
        PAGESEL TABLE_PROG
    CALL TABLE_PROG;
        PAGESEL MAIN
    MOVWF PLL_SWTEMP
       
;写锁相环
    MOVLW .5
    MOVWF R0_TEMP
        MOVF PLL_PCTEMPH,W
        MOVWF DAT_TEMP
        CALL DAT_RLW
    MOVWF PLL_DATTEMP
    MOVLW .3
        MOVWF R0
        CALL WR_PLLDAT

        MOVF PLL_PCTEMPL,W
    MOVWF PLL_DATTEMP
        MOVLW .8
        MOVWF R0
        CALL WR_PLLDAT

        MOVF PLL_SWTEMP,W
    MOVWF PLL_DATTEMP
        RLF PLL_DATTEMP,F
        MOVLW .7
        MOVWF R0
        CALL WR_PLLDAT

        BCF PLL_CLK  ;写分频器选择位
        BCF PLL_DAT
        BSF PLL_CLK
        BSF PLL_CS
    RETURN  
;******************写PLL******************
;freq=(M*N+A)*(fosc/R) 取M=128 R=400
;R0 发送BIT数,PLL_DATEMP发送的数据
WR_PLLDAT
   BANKSEL PORTC
WR_PLLDAT1 ;左移R0次       
   BCF PLL_CLK
   RLF PLL_DATTEMP,F
   BTFSS STATUS,C
      GOTO $+3
   BSF PLL_DAT ;写数据1
   GOTO $+2
   BCF PLL_DAT;写数据0
   BSF PLL_CLK
   DECFSZ R0,F;判断是否有8次?
     GOTO WR_PLLDAT1  
   RETURN  
;**************************ATX IIC*****************************
IIC_INIT
        BANKSEL TRISC
        BCF TRISC,3
        BCF TRISC,4
        BANKSEL PORTC
        BSF SCL
        BSF SDA
        RETURN
IIC_TEST
        BANKSEL TRISC
        BCF TRISC,4
        BANKSEL PORTC
        BSF SDA
        BANKSEL TRISC
        BSF TRISC,4       
        BANKSEL PORTC
        BTFSS SDA;
            RETLW .1
        RETLW .0
IIC_START
        BANKSEL TRISC
        BCF TRISC,4
        BANKSEL PORTC
        BSF SDA
        BSF SCL
        NOP
        NOP
        NOP
        NOP
        BCF SDA
        NOP
        NOP
        NOP
        NOP
        NOP
        BCF SCL
    RETURN
IIC_STOP
        BANKSEL TRISC
        BCF TRISC,4
        BANKSEL PORTC
        BCF SDA
        BSF SCL
        NOP
        NOP
        NOP
        NOP
        BSF SDA
        NOP
        NOP
        NOP
        NOP
        NOP
    RETURN               
IIC_WAIT_ACK
        BANKSEL TRISC
        BSF TRISC,4
        BANKSEL PORTC
        BSF SCL
        NOP
        NOP
        NOP
        NOP
        BANKSEL PORTC
IIC_ACK1
        BTFSC SDA  ;检测应答是否超时
           GOTO $+2 ;超时检测
    GOTO $+13 ;应答成功
        BCF STATUS,C
    MOVLW .1
        ;CALL DELAY_MS
        NOP
        INCF IIC_OUTTIME,F               
    BTFSS IIC_OUTTIME,4
           GOTO IIC_ACK1  ;继续等待最大255MS
    BANKSEL TRISC ;等待非应答
        BCF TRISC,4
        BANKSEL PORTC
        BCF SCL
    CLRF IIC_OUTTIME
        RETLW .1
    BANKSEL TRISC ;应答成功
        BCF TRISC,4   
        BANKSEL PORTC
        BCF SCL
    CLRF IIC_OUTTIME
        RETLW .0
IIC_SEND_ACK
        BANKSEL TRISC
        BCF TRISC,3
        BCF TRISC,4
        BANKSEL PORTC
        BCF SCL
        BCF SDA
        BSF SCL
        NOP
        NOP
        NOP
        NOP
        BCF SCL
;        BSF SDA
        NOP
        RETURN
IIC_SEND_NOACK
        BANKSEL TRISC
        BCF TRISC,3
        BCF TRISC,4
        BANKSEL PORTC
        BCF SCL
        BSF SDA
        NOP
        NOP
        BSF SCL
        NOP
        NOP
        BCF SCL
;        BCF SDA
        RETURN         
IIC_SEND_BYTE
        ;用到IIC_DAT ,  
        BANKSEL TRISC
        BCF TRISC,3
        BCF TRISC,4
        BANKSEL PORTC
    BCF SCL
        MOVLW .8
        MOVWF IIC_BITS
IIC_SENDA
        BCF STATUS,C
        RLF IIC_DAT,F
        BTFSS STATUS,C
           GOTO $+2; “0”
        GOTO $+3;“1"
        BCF SDA
        GOTO $+2
        BSF SDA
        NOP
        NOP
        BSF SCL
        NOP
        NOP
        NOP
        NOP
        NOP
        BCF SCL
        NOP
        NOP
        NOP
        DECFSZ IIC_BITS,F
             GOTO IIC_SENDA
        RETURN
IIC_READ_BYTE
        BANKSEL TRISC
        BSF TRISC,4
    BANKSEL PORTA
        MOVLW .8
        MOVWF IIC_BITS
        CLRF IIC_DAT
IIC_READ1
        BCF SCL
        NOP
        NOP
        NOP
        NOP
        BTFSS SDA
                   GOTO $+2;read "0"
    GOTO $+4 ;read "1"
    BCF STATUS,C
        RLF IIC_DAT,F
    GOTO $+3
    BSF STATUS,C
        RLF IIC_DAT,F
        NOP
        NOP
    BSF SCL
        NOP
        NOP
        NOP
        NOP
        DECFSZ IIC_BITS,F
          GOTO IIC_READ1
        RETLW IIC_DAT
;***********************写IIC一个字******************************
WRITE_IIC
        BANKSEL PORTC
    CLRF IIC_TESTFLAG
        ;CALL IIC_TEST
        CALL IIC_START;发起始位

        MOVF IIC_DEVADDR,W
        MOVWF IIC_DAT
        BCF IIC_DAT,0
        CALL IIC_SEND_BYTE;发送器件地址
        CALL IIC_WAIT_ACK;等待应答
    MOVWF IIC_TESTFLAG

        MOVF IIC_ADDR,W
        MOVWF IIC_DAT
        CALL IIC_SEND_BYTE;发送存储器地址
    CALL IIC_WAIT_ACK;等待应答
    MOVWF IIC_TESTFLAG

        MOVF IIC_DATTEMP,W
        MOVWF IIC_DAT
        CALL IIC_SEND_BYTE;发送数据
        CALL IIC_WAIT_ACK
    MOVWF IIC_TESTFLAG

        CALL IIC_STOP ;发停止位
        MOVLW .2
        CALL DELAY_MS;
    RETLW IIC_TESTFLAG
       
;**********************读IIC一个字*******************************
READ_IIC
        BANKSEL PORTC
    CLRF IIC_TESTFLAG
        ;CALL IIC_TEST
        CALL IIC_START ;发送起始

        MOVF IIC_DEVADDR,W
        MOVWF IIC_DAT
        BCF IIC_DAT,0
        CALL IIC_SEND_BYTE ;发送器件地址
        CALL IIC_WAIT_ACK;等待应答
    MOVWF IIC_TESTFLAG

        MOVF IIC_ADDR,W
        MOVWF IIC_DAT
        CALL IIC_SEND_BYTE;发送存储地址
        CALL IIC_WAIT_ACK
    MOVWF IIC_TESTFLAG

        CALL IIC_START;发送起始位

        MOVF IIC_DEVADDR,W
        MOVWF IIC_DAT
        BSF IIC_DAT,0
        CALL IIC_SEND_BYTE;发送器件地址
        CALL IIC_WAIT_ACK;等待应答
    MOVWF IIC_TESTFLAG

        CALL IIC_READ_BYTE;读储存器
    MOVF IIC_DAT,W
        MOVWF IIC_DATTEMP
    CALL IIC_SEND_NOACK;不应答

        CALL IIC_STOP;发送结束位
    RETLW IIC_TESTFLAG
;************SET VOL************************************
VOL_SET
        BANKSEL PORTA
        MOVLW 58H       
        MOVWF IIC_DEVADDR
        CLRF IIC_ADDR
        MOVF AF_VOL,W
        MOVWF IIC_DATTEMP
        CLRC
        RLF IIC_DATTEMP,F
        CLRC
        RLF IIC_DATTEMP,F
        CALL WRITE_IIC
        RETURN       
;****************SAVE DATA********************************
SAVE_DAT
        BANKSEL PORTA
        MOVLW 0A0H       
        MOVWF IIC_DEVADDR
        MOVLW CHANNELADDR
        MOVWF IIC_ADDR
        MOVF CHANNEL,W
        MOVWF IIC_DATTEMP
        CALL WRITE_IIC

        MOVLW 0A0H       
        MOVWF IIC_DEVADDR
        MOVLW GROUPADDR
        MOVWF IIC_ADDR
        MOVF GROUP,W
        MOVWF IIC_DATTEMP
        CALL WRITE_IIC       
        RETURN
SAVE_DAT_VOL
        BANKSEL PORTA
        MOVLW 0A0H       
        MOVWF IIC_DEVADDR
        MOVLW AFVOLADDR
        MOVWF IIC_ADDR
        MOVF AF_VOL,W
        MOVWF IIC_DATTEMP
        CALL WRITE_IIC       
        RETURN

POWERSTACHECK
        BANKSEL PORTA
        MOVLW 0A0H       
        MOVWF IIC_DEVADDR
        MOVLW POWERADDR
        MOVWF IIC_ADDR
        CLRF IIC_DATTEMP
        CALL READ_IIC       
        MOVLW 55H
        XORWF IIC_DATTEMP,W
        SKPZ
          GOTO $+3
        BSF POWERSTA
        GOTO $+2
        BCF POWERSTA
        RETURN
POWERSTASAVE
        BANKSEL PORTA
    BTFSS POWERSTA
           GOTO $+4
        MOVLW 055H
        MOVWF IIC_DATTEMP
        GOTO $+3
        MOVLW 0AAH
        MOVWF IIC_DATTEMP
    MOVLW POWERADDR
    MOVWF IIC_ADDR
    MOVLW 0A0H
    MOVWF IIC_DEVADDR
    CALL WRITE_IIC  
        RETURN   
;**************************数据左右移动N次***********************
;数据用R1传送,W移动次数,W返回数据 R0次数寄存
DAT_RLW
        BANKSEL PORTA

DAT_RLW1
   BCF STATUS,C
   RLF DAT_TEMP,F
   DECFSZ R0_TEMP,F
     GOTO DAT_RLW1
   MOVF  DAT_TEMP,W
   RETURN        
;右移       
DAT_RRW
        BANKSEL PORTA

DAT_RRW1
   BCF STATUS,C
   RRF DAT_TEMP,F
   DECFSZ R0_TEMP,F
     GOTO DAT_RRW1
   MOVF DAT_TEMP,W
   RETURN        
;*************************ADC**********************/
ADC_INIT
    BANKSEL ADCON1
        MOVLW .4
        MOVWF ADCON1
        BANKSEL TRISA
        BSF TRISA,0
        BSF TRISA,1
        BANKSEL PORTA
        MOVLW 40h;F/8 通道0
        MOVWF ADCON0
        MOVLW .1
        IORWF ADCON0,F
    RETURN
ADC_READ
        MOVLW .4
        IORWF ADCON0,F;ADC RUN
ADC_LOOP
        BTFSC ADCON0,2
          GOTO ADC_LOOP
        MOVF ADRES,W
        MOVWF ADC_DAT
        RETURN
;***********************读ADC并转换成LCD代码*******************
ADC_RFCHANGE
        BANKSEL PORTA
    CLRF RFLVH
        CLRF RFLVL
        BSF ADCON0,3
        CALL ADC_READ
        MOVLW .60
        SUBWF ADC_DAT,W
        BTFSC STATUS,C ;减法运算为负值时发生借位,C=0,反之减法为正值时C=1
             GOTO RFLV1        ;ADC值>139           
    CLRF RFLVL ;低压 ADC值<139  空电压
    CLRF RFLVH
;        BSF LOWBATT  ;启动低压标志
    GOTO RFADC_END
RFLV1                
    MOVLW .102
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO RFLV2;
        INCF RFLVL,F   
        GOTO RFADC_END
RFLV2
    MOVLW .129
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO RFLV3
    MOVLW .3  ;两格
    MOVWF RFLVL ;ADC<170
        GOTO RFADC_END  
RFLV3
    MOVLW .153
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO RFLV4
    MOVLW .7  ;三格
    MOVWF RFLVL ;ADC<170
        GOTO RFADC_END
RFLV4
    MOVLW .180
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO RFLV5
    MOVLW .15 ;四格
        MOVWF RFLVL
        GOTO RFADC_END
RFLV5
        MOVLW 0FH
        MOVWF RFLVL
    MOVLW .180
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO RFLV6
    MOVLW .1 ;四格
        MOVWF RFLVH
        GOTO RFADC_END
RFLV6
    MOVLW .205
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO RFLV7
    MOVLW .3 ;
        MOVWF RFLVH
        GOTO RFADC_END
RFLV7
    MOVLW .230
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO RFLV8
    MOVLW .7 ;
        MOVWF RFLVH
        GOTO RFADC_END
RFLV8
        MOVLW 0FH
        MOVWF RFLVH
;        MOVWF BATT_LCD ;显示电池框
   ; BCF LOWBATT  ;关闭 低压标志
RFADC_END
    RETURN

;AF
ADC_AFCHANGE

;        GOTO AFADC_END

        BANKSEL PORTA
    CLRF AFLVL
        CLRF AFLVH
        BCF ADCON0,3
        CALL ADC_READ
        MOVLW .30
        SUBWF ADC_DAT,W
        BTFSC STATUS,C ;减法运算为负值时发生借位,C=0,反之减法为正值时C=1
             GOTO AFLV1        ;ADC值>139           
    CLRF AFLVL ;低压 ADC值<139  空电压
        CLRF AFLVH
;        BSF LOWBATT  ;启动低压标志
    GOTO AFADC_END
AFLV1                
    MOVLW .50
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO AFLV2;
        INCF AFLVL,F   
        GOTO AFADC_END
AFLV2
    MOVLW .70
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO AFLV3
    MOVLW .3  ;两格
    MOVWF AFLVL ;ADC<170
        GOTO AFADC_END  
AFLV3
    MOVLW .100
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO AFLV4
    MOVLW .7  ;三格
    MOVWF AFLVL ;ADC<170
        GOTO AFADC_END
AFLV4
    MOVLW .150
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO AFLV5
    MOVLW .15 ;四格
        MOVWF AFLVL
        GOTO AFADC_END
AFLV5
        MOVLW 0FH
        MOVWF AFLVL
    MOVLW .180
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO AFLV6
    MOVLW .1 ;四格
        MOVWF AFLVH
        GOTO AFADC_END
AFLV6
    MOVLW .205
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO AFLV7
    MOVLW .3 ;
        MOVWF AFLVH
        GOTO AFADC_END
AFLV7
    MOVLW .230
        SUBWF ADC_DAT,W
        BTFSC STATUS,C
          GOTO AFLV8
    MOVLW .7 ;
        MOVWF AFLVH
        GOTO AFADC_END
AFLV8
        MOVLW 0FH
        MOVWF AFLVH
;        MOVWF BATT_LCD ;显示电池框
   ; BCF LOWBATT  ;关闭 低压标志
AFADC_END
;**************峰值延时功能*********************
AFADCCHECK
        BANKSEL PORTA
        MOVF AFLVH,W
        MOVWF ADCDATTEMP
        CLRC
        RLF ADCDATTEMP,F
        CLRC
        RLF ADCDATTEMP,F
        CLRC
        RLF ADCDATTEMP,F
        CLRC
        RLF ADCDATTEMP,W
        IORWF AFLVL,W
        MOVWF ADCDATTEMP
       
        MOVF ADCDATOLDA,W
        SKPNZ
                GOTO AFADCUPDATE ;排除初值为零时的情况
        SUBWF ADCDATTEMP,W ;判断新转换值是否>上次的旧值
        SKPC
                GOTO AFDADCISSET                 ;<设置峰值显示
        GOTO AFADCUPDATE        ;>        旧值更新
;旧值更新
AFADCUPDATE
        BCF AFADC_KEEP       
        BCF AFADC_UPDATE
        MOVF ADCDATTEMP,W
        MOVWF ADCDATOLDA
        CALL TIME_COUNTER_RESET
        GOTO AFADC_END2
;峰值保持延时显示设置
AFDADCISSET       
        BTFSC AFADC_UPDATE ;保持时间到,强制更新峰值
                GOTO AFADCUPDATE                       
        MOVLW 0FFH
        SUBWF ADCDATOLDA,W
        SKPZ
           GOTO AFADCDISSET2
        BSF AFLVH,3
        GOTO AFADC_END2
AFADCDISSET2
        MOVLW 7FH
        SUBWF ADCDATOLDA,W
        SKPZ
           GOTO AFADCDISSET3
        BSF AFLVH,2
        GOTO AFADC_END2
AFADCDISSET3
        MOVLW 3FH
        SUBWF ADCDATOLDA,W
        SKPZ
           GOTO AFADCDISSET4
        BSF AFLVH,1
        GOTO AFADC_END2
AFADCDISSET4
        MOVLW 1FH
        SUBWF ADCDATOLDA,W
        SKPZ
           GOTO AFADCDISSET5
        BSF AFLVH,0
        GOTO AFADC_END2
AFADCDISSET5
        MOVLW 0FH
        SUBWF ADCDATOLDA,W
        SKPZ
           GOTO AFADCDISSET6
        BSF AFLVL,3
        GOTO AFADC_END2
AFADCDISSET6
        MOVLW 7H
        SUBWF ADCDATOLDA,W
        SKPZ
           GOTO AFADCDISSET7
        BSF AFLVL,2
        GOTO AFADC_END2
AFADCDISSET7
        MOVLW 3H
        SUBWF ADCDATOLDA,W
        SKPZ
           GOTO AFADCDISSET8
        BSF AFLVL,1
        GOTO AFADC_END2
AFADCDISSET8
        MOVLW 1H
        SUBWF ADCDATOLDA,W
        SKPZ
           GOTO AFADC_END2
        BSF AFLVL,0
;        GOTO AFADC_END2
AFADC_END2
CALL TIMER_COUNTER
    RETURN
;**************计时,退出峰值延时******************
TIMER_COUNTER
        BANKSEL TRISB
        MOVF T1CB,W
        SKPNZ
                GOTO TIME_COUNTER_RESET
        MOVF T1CA,W
        SKPNZ
                GOTO TIME_COUNTER_RESET
    DECFSZ T1CB,F ;内循环相减
              GOTO END_TIMER_COUNTER;跳到下一个子函数
    DECFSZ T1CA,F ;外循环减      
         GOTO TIME_COUNTER_NEXT ;跳到内循环
     GOTO TIMEOUT_COUNTER; 当完成外循环:LED——OFF
TIME_COUNTER_RESET
        BANKSEL TRISB
    MOVLW T1VOLA
    MOVWF T1CA;
TIME_COUNTER_NEXT  ;恢复R1,以进行R1*N次的自减
     MOVLW T1VOLB
     MOVWF T1CB;   
    GOTO END_TIMER_COUNTER  
TIMEOUT_COUNTER
        BANKSEL PORTA
        BCF AFADC_KEEP
        BSF AFADC_UPDATE
        GOTO TIME_COUNTER_RESET
END_TIMER_COUNTER
        RETURN
;***************相乘结果<255的乘法函数***********************************
; MULTAH/L 乘数 ,MULTBH/L 被乘数 MULTCH/L 结果
;思路。按照10进制的乘法思路实现,1*0=0 1*1=1 0*0=0
;    1010  10D
;  X  101  5D
;----------
;    1010
;= 110010 32H
;注意,暂时不实现16位*16位
MULT_DATA
        CLRF MULTCH
        CLRF MULTCL
MULT_LOOP1 ;判断乘数第0BIT,用乘数的每一位*被乘数,移位后结果相加
        BTFSS MULTAL,0
                GOTO MULT_NEXT2 ;第0位为0
        MOVF MULTBL,W
        ADDWF MULTCL,F
        SKPC   ;相加是否有进位?
                GOTO MULT_NEXT1       
        INCF MULTCH,F  ;需要加上进位
MULT_NEXT1
        MOVF MULTBH,W
        ADDWF MULTCH,F ;
MULT_NEXT2
        CLRC
        RLF MULTBL,F
        RLF MULTBH,F  ;被乘数<<1

        CLRC
        RRF MULTAL,F
        RRF MULTAH,F ;乘数>>1

        ;判断乘数是否为零,不为零继续
        MOVLW .0
        XORWF MULTAL,W
    SKPZ
           GOTO MULT_LOOP1
        RETURN
;***************二进制除法***********
DX_DATA
        BANKSEL PORTA
        CLRF DX_BITS;
        CLRF QUOTIENT;
        CLRF REMAIN;
        MOVF DIVIDEND,W
        SKPNZ
           GOTO DX_END
        MOVLW .8
        MOVWF DX_BITS
DX_LOOP1
          RLF DIVIDEND,F
        SKPC
                GOTO $+2
        INCF REMAIN,F
        MOVF DIVISOR,W
        SUBWF REMAIN,W
        SKPC
                GOTO $+4
        INCF QUOTIENT,F
        MOVF DIVISOR,W
        SUBWF REMAIN,F       
        DECFSZ DX_BITS,F
                GOTO DX_LOOP2
        GOTO DX_END
DX_LOOP2
        CLRC
        RLF QUOTIENT,F
        CLRC
        RLF REMAIN,F
        GOTO DX_LOOP1       
DX_END
        RETURN
;****************TIME0 ISR*****************
TIME0_ISR
;实现自动退出菜单
;    BTFSC INTCON,T0IF;为0跳出
  ;  BTFSS INTCON,T0IE
  ;     goto END_TIME0_ISR
;定时器定时程序
  ;  BCF INTCON,T0IF ;清零标志
;        MOVLW .250
;   CLRF TMR0;
;        MOVWF TMR0;
        BANKSEL PORTA
   ; BTFSS MASTERLIST
   ;如果LED状态时关闭的,那么将定时器数据恢复
        ;         GOTO LED_TIMERESET
    ;LED OFF 延时自减
    DECFSZ T0COUNTERB,F ;内循环相减
             goto END_TIME0_ISR ;跳到下一个子函数
    DECFSZ T0COUNTERA,F ;外循环减      
        goto ISR_NEXT ;跳到内循环
    goto LED_OFF; 当完成外循环:LED——OFF
LED_TIMERESET
        BTFSS ASCSTA
                GOTO $+3
    MOVLW ASCT0A
        GOTO $+2
    MOVLW T0A
    MOVWF T0COUNTERA;
ISR_NEXT ;恢复R1,以进行R1*N次的自减
        BTFSS ASCSTA
                GOTO $+3
    MOVLW ASCT0B
        GOTO $+2
    MOVLW T0B
    MOVWF T0COUNTERB;   
    goto END_TIME0_ISR          
LED_OFF
        BCF MASTERLIST
        BCF ASCSTA
        BCF AFVOLSTA
END_TIME0_ISR
        RETURN
;*****************闪烁显示****************************
FLASH_TIME
        ;内循环
        INCF FLASHCOUNTERB,F
        MOVLW FLASHTIMEB
        SUBWF FLASHCOUNTERB,W
        SKPC
            GOTO END_TIME0 ;计数时间未到,转出ISR       
        ;内循环计数时间到
        CLRF FLASHCOUNTERB
        INCF FLASHCOUNTERA,F
        MOVLW FLASHTIMEA
        SUBWF FLASHCOUNTERA,W
        SKPC
                 GOTO END_TIME0 ;外循环计数时间未到
    ;时间到,改变状态
        CLRF FLASHCOUNTERA       
        BTFSS LCD_FLASH
                GOTO FLASHON
        BCF LCD_FLASH
        GOTO END_TIME0
FLASHON
        BSF LCD_FLASH
END_TIME0
    RETURN
;*****************BANK1****************
        ORG 0800H
BANK1SEL
        NOP
        RETURN
;**************TIM2 PWM********************  
TIME2_PWMINIT
        BANKSEL TRISC
        BCF TRISC,2
        MOVLW .25
        MOVWF PR2;38.4K
        BANKSEL CCP1CON
        MOVLW .9
        MOVWF CCPR1L
        CLRF CCP1CON
        MOVLW 30H
        IORWF CCP1CON,F
        BANKSEL T2CON
        CLRF T2CON ;1:1F分频
        MOVLW 0FH
        IORWF CCP1CON,F;PWM
        BCF T2CON,2;关闭PWM
        RETURN       
;*************TIME1 INIT*****************
TIME1_INIT
        BANKSEL T1CON
        CLRF T1CON
        CLRF TMR1H
        CLRF TMR1L
        BANKSEL PIR1
        BCF PIR1,TMR1IF
        BANKSEL PIE1
        BCF PIE1,TMR1IE
        RETURN
;****************TIME1  DELAY 计数补偿50US**********
TIME1_DELAY_9MS
        BANKSEL T1CON
        MOVLW 0DCH
        MOVWF TMR1H
        MOVLW 0A5H
        MOVWF TMR1L       
        BSF T1CON,0
        GOTO TIME1_LOOP
TIME1_DELAY_4.5MS  ;延时4.5MS
        BANKSEL T1CON
        MOVLW 0EEH
        MOVWF TMR1H
        MOVLW 039H
        MOVWF TMR1L       
        BSF T1CON,0
        GOTO TIME1_LOOP
TIME1_DELAY_3MS
        BANKSEL T1CON
        MOVLW 0F4H
        MOVWF TMR1H
        MOVLW 015H
        MOVWF TMR1L       
        BSF T1CON,0
        GOTO TIME1_LOOP
TIME1_DELAY_2MS
        BANKSEL T1CON
        MOVLW 0F7H
        MOVWF TMR1H
        MOVLW 0FDH
        MOVWF TMR1L       
        BSF T1CON,0
        GOTO TIME1_LOOP
TIME1_DELAY_1MS
        BANKSEL T1CON
        MOVLW 0FBH
        MOVWF TMR1H
        MOVLW 0E0H
        MOVWF TMR1L       
        BSF T1CON,0
        GOTO TIME1_LOOP
TIME1_DELAY100US
        BANKSEL T1CON
        MOVLW .255
        MOVWF TMR1H
        MOVLW .160
        MOVWF TMR1L
        BSF T1CON,0
TIME1_LOOP
        BANKSEL PIR1
        BTFSS PIR1,TMR1IF
                GOTO TIME1_LOOP
        BANKSEL T1CON
        BCF T1CON,0
        BCF PIR1,TMR1IF
        RETURN
;**********************IR发射程序******************
IR_START
        CALL TIME1_INIT
        BANKSEL PORTA
        BSF IRPWM
        CALL TIME1_DELAY_9MS
        BANKSEL PORTA
        BCF IRPWM
        CALL TIME1_DELAY_4.5MS       
        RETURN
IR_STOP
        BANKSEL PORTA
        BSF IRPWM
        CALL TIME1_DELAY_1MS
        BANKSEL PORTA         
        BCF IRPWM
        CALL TIME1_DELAY_3MS
        BANKSEL PORTA       
        BSF IRPWM
        CALL TIME1_DELAY_1MS
        BANKSEL PORTA       
        BCF IRPWM
        CALL TIME1_DELAY_9MS
;        CALL TIME1_DELAY_9MS
;        CALL TIME1_DELAY_9MS
;        CALL TIME1_DELAY_9MS
        RETURN
IR_DAT1
        BANKSEL PORTA
        BSF IRPWM
        CALL TIME1_DELAY_1MS
        BANKSEL PORTA
        BCF IRPWM
        CALL TIME1_DELAY_2MS
        RETURN
IR_DAT0
        BANKSEL PORTA
        BSF IRPWM
        CALL TIME1_DELAY_1MS
        BANKSEL PORTA
        BCF IRPWM
        CALL TIME1_DELAY_1MS
        RETURN
IR_SEND_BYTE
        BANKSEL TRISB
        MOVLW .8
        MOVWF IRBITS
IR_LOOPS
        RLF IRTEMP,F
        SKPC
                GOTO IR0
        GOTO IR1
IR0
        CALL IR_DAT0
        GOTO IRNEXT
IR1
        CALL IR_DAT1
IRNEXT
        BANKSEL TRISB
        DECFSZ IRBITS,F
                GOTO IR_LOOPS       
        RETURN
;***********IR发送一次************
IR_SEND_DAT
        CALL IR_START
;ID
        BANKSEL TRISB
        MOVLW IRADDR
        MOVWF IRTEMP
        PAGESEL BANK1SEL
        CALL IR_SEND_BYTE
;CHANNEL
        BANKSEL PORTA
        MOVF CHANNEL,W
        BANKSEL TRISB
        MOVWF IRTEMP
        PAGESEL BANK1SEL
        CALL IR_SEND_BYTE
;~CHANNEL
        BANKSEL PORTA
        COMF CHANNEL,W
        BANKSEL TRISB
        MOVWF IRTEMP
        CALL IR_SEND_BYTE
;GROUP         
        BANKSEL PORTA
        MOVF GROUP,W
        BANKSEL TRISB
        MOVWF IRTEMP
        PAGESEL BANK1SEL
        CALL IR_SEND_BYTE
;~GROUP
        BANKSEL PORTA
        COMF GROUP,W
        BANKSEL TRISB
        MOVWF IRTEMP
        PAGESEL BANK1SEL       
        CALL IR_SEND_BYTE
        CALL IR_STOP

        RETURN                               

;****************************************************



;**********************LCD显示屏代码**********************/
;形参TABLETEMP,返回TEMPH/TEMPL 数字第一个地址TMEPL 第二个地址TEMPH
LCD_GETDAT
    BANKSEL PORTA
        MOVF TABLETEMP,W
        CALL TABLE
    MOVWF TEMPL
    ANDLW 0FH
    MOVWF TEMPH
    MOVLW .4
    MOVWF R0
LCD_GETDAT1
   BCF STATUS,C
   RRF TEMPL,F
   DECFSZ R0,F
      GOTO LCD_GETDAT1       
   BTFSS DIS_FLAG ;是否需要显示字符?
            GOTO $+3
   MOVLW .1 ;显示标签
   IORWF TEMPH,F   
   RETURN   
TABLE
    PAGESEL TABLEB
TABLEB
    MOVWF OFFSETL
        MOVLW HIGH(TABLEC)
        ADDWF OFFSETH,W
        MOVWF PCLATH
        MOVLW LOW(TABLEC)
        ADDWF OFFSETL,W
        BTFSC STATUS,C
        INCF  PCLATH,F
        MOVWF PCL
TABLEC
    DT 0FAH,060H,0D6H,0F4H,06CH,0BCH,0BEH,0E0H,0FEH,0FCH ;0  
;*******************读取PLL数据表****************************
;---------TABLE_PROG-----------
TABLE_PROG     ;分频比表
;        CLRF OFFSETH
;        CLRF OFFSETL
;        PAGESEL TABLE_PCL
TABLE_PCL
        MOVLW HIGH(FREQPROG)
        ADDWF OFFSETH,W
        MOVWF PCLATH
        MOVLW LOW(FREQPROG)
        ADDWF OFFSETL,W
        BTFSC STATUS,C
        INCF  PCLATH,F
        MOVWF PCL
FREQPROG:   
DT 000H,000H,000H
DT 001H,0C1H,03AH ;  0 719.850 Mhz
DT 001H,0C2H,013H ;  1 720.475 Mhz
DT 001H,0C2H,03DH ;  2 721.525 Mhz
DT 001H,0C3H,016H ;  3 722.150 Mhz
DT 001H,0C4H,036H ;  4 724.550 Mhz
DT 001H,0C5H,032H ;  5 726.050 Mhz
DT 001H,0C6H,03AH ;  6 727.850 Mhz
DT 001H,0C8H,002H ;  7 729.650 Mhz
DT 001H,0C9H,00FH ;  8 731.575 Mhz
DT 001H,0C9H,03DH ;  9 732.725 Mhz
DT 001H,0CBH,00EH ; 10 734.750 Mhz
DT 001H,0CBH,03AH ; 11 735.850 Mhz
DT 001H,0CDH,002H ; 12 737.650 Mhz
DT 001H,0CEH,03DH ; 13 740.725 Mhz
DT 001H,0CFH,036H ; 14 742.150 Mhz
DT 001H,0D0H,010H ; 15 742.800 Mhz

DT 001H,0C2H,010H ;  0 720.400 Mhz
DT 001H,0C3H,000H ;  1 721.600 Mhz
DT 001H,0C3H,035H ;  2 722.925 Mhz
DT 001H,0C4H,000H ;  3 723.200 Mhz
DT 001H,0C4H,03DH ;  4 724.725 Mhz
DT 001H,0C6H,00EH ;  5 726.750 Mhz
DT 001H,0C7H,010H ;  6 728.400 Mhz
DT 001H,0C8H,023H ;  7 730.475 Mhz
DT 001H,0C9H,024H ;  8 732.100 Mhz
DT 001H,0CAH,027H ;  9 733.775 Mhz
DT 001H,0CBH,010H ; 10 734.800 Mhz
DT 001H,0CCH,010H ; 11 736.400 Mhz
DT 001H,0CDH,018H ; 12 738.200 Mhz
DT 001H,0CEH,000H ; 13 739.200 Mhz
DT 001H,0CFH,027H ; 14 741.775 Mhz
DT 001H,0D0H,00EH ; 15 742.750 Mhz

DT 001H,0C1H,03BH ;  0 719.875 Mhz
DT 001H,0C2H,012H ;  1 720.450 Mhz
DT 001H,0C2H,03EH ;  2 721.550 Mhz
DT 001H,0C3H,017H ;  3 722.175 Mhz
DT 001H,0C4H,037H ;  4 724.575 Mhz
DT 001H,0C5H,033H ;  5 726.075 Mhz
DT 001H,0C6H,03BH ;  6 727.875 Mhz
DT 001H,0C8H,014H ;  7 730.100 Mhz
DT 001H,0C9H,00EH ;  8 731.550 Mhz
DT 001H,0C9H,03CH ;  9 732.700 Mhz
DT 001H,0CBH,00FH ; 10 734.775 Mhz
DT 001H,0CBH,03BH ; 11 735.875 Mhz
DT 001H,0CDH,001H ; 12 737.625 Mhz
DT 001H,0CEH,03CH ; 13 740.700 Mhz
DT 001H,0CFH,037H ; 14 742.175 Mhz
DT 001H,0D0H,00FH ; 15 742.775 Mhz

DT 001H,0C3H,001H ;  0 721.625 Mhz
DT 001H,0C3H,014H ;  1 722.100 Mhz
DT 001H,0C3H,022H ;  2 722.450 Mhz
DT 001H,0C3H,036H ;  3 722.950 Mhz
DT 001H,0C4H,021H ;  4 724.025 Mhz
DT 001H,0C5H,03CH ;  5 726.300 Mhz
DT 001H,0C7H,011H ;  6 728.425 Mhz
DT 001H,0C8H,001H ;  7 729.625 Mhz
DT 001H,0CAH,028H ;  8 733.800 Mhz
DT 001H,0CAH,03AH ;  9 734.250 Mhz
DT 001H,0CCH,013H ; 10 736.475 Mhz
DT 001H,0CCH,03EH ; 11 737.550 Mhz
DT 001H,0CDH,037H ; 12 738.975 Mhz
DT 001H,0CEH,005H ; 13 739.325 Mhz
DT 001H,0CEH,038H ; 14 740.600 Mhz
DT 001H,0CFH,03CH ; 15 742.300 Mhz

DT 001H,0C1H,03CH ;  0 719.900 Mhz
DT 001H,0C2H,011H ;  1 720.425 Mhz
DT 001H,0C2H,03FH ;  2 721.575 Mhz
DT 001H,0C3H,018H ;  3 722.200 Mhz
DT 001H,0C4H,038H ;  4 724.600 Mhz
DT 001H,0C5H,034H ;  5 726.100 Mhz
DT 001H,0C6H,03CH ;  6 727.900 Mhz
DT 001H,0C8H,015H ;  7 730.125 Mhz
DT 001H,0C9H,021H ;  8 732.025 Mhz
DT 001H,0C9H,03BH ;  9 732.675 Mhz
DT 001H,0CAH,03CH ; 10 734.300 Mhz
DT 001H,0CBH,03CH ; 11 735.900 Mhz
DT 001H,0CDH,000H ; 12 737.600 Mhz
DT 001H,0CDH,03AH ; 13 739.050 Mhz
DT 001H,0CEH,03BH ; 14 740.675 Mhz
DT 001H,0CFH,035H ; 15 742.125 Mhz

DT 001H,0C3H,002H ;  0 721.650 Mhz
DT 001H,0C3H,023H ;  1 722.475 Mhz
DT 001H,0C3H,037H ;  2 722.975 Mhz
DT 001H,0C4H,00DH ;  3 723.525 Mhz
DT 001H,0C4H,022H ;  4 724.050 Mhz
DT 001H,0C6H,00FH ;  5 726.775 Mhz
DT 001H,0C7H,012H ;  6 728.450 Mhz
DT 001H,0C8H,000H ;  7 729.600 Mhz
DT 001H,0CAH,029H ;  8 733.825 Mhz
DT 001H,0CAH,039H ;  9 734.225 Mhz
DT 001H,0CCH,012H ; 10 736.450 Mhz
DT 001H,0CCH,03DH ; 11 737.525 Mhz
DT 001H,0CDH,036H ; 12 738.950 Mhz
DT 001H,0CEH,00DH ; 13 739.525 Mhz
DT 001H,0CEH,037H ; 14 740.575 Mhz
DT 001H,0CFH,03BH ; 15 742.275 Mhz

DT 001H,0C1H,03DH ;  0 719.925 Mhz
DT 001H,0C3H,019H ;  1 722.225 Mhz
DT 001H,0C3H,03CH ;  2 723.100 Mhz
DT 001H,0C4H,039H ;  3 724.625 Mhz
DT 001H,0C5H,035H ;  4 726.125 Mhz
DT 001H,0C6H,03DH ;  5 727.925 Mhz
DT 001H,0C8H,016H ;  6 730.150 Mhz
DT 001H,0C8H,03FH ;  7 731.175 Mhz
DT 001H,0C9H,022H ;  8 732.050 Mhz
DT 001H,0C9H,03AH ;  9 732.650 Mhz
DT 001H,0CAH,03BH ; 10 734.275 Mhz
DT 001H,0CBH,03DH ; 11 735.925 Mhz
DT 001H,0CCH,03FH ; 12 737.575 Mhz
DT 001H,0CDH,039H ; 13 739.025 Mhz
DT 001H,0CEH,03AH ; 14 740.650 Mhz
DT 001H,0CFH,034H ; 15 742.100 Mhz

DT 001H,0C3H,038H ;  0 723.000 Mhz
DT 001H,0C4H,004H ;  1 723.300 Mhz
DT 001H,0C4H,00FH ;  2 723.575 Mhz
DT 001H,0C4H,024H ;  3 724.100 Mhz
DT 001H,0C5H,027H ;  4 725.775 Mhz
DT 001H,0C6H,010H ;  5 726.800 Mhz
DT 001H,0C7H,03DH ;  6 729.525 Mhz
DT 001H,0C8H,038H ;  7 731.000 Mhz
DT 001H,0C9H,038H ;  8 732.600 Mhz
DT 001H,0CAH,038H ;  9 734.200 Mhz
DT 001H,0CCH,011H ; 10 736.425 Mhz
DT 001H,0CDH,015H ; 11 738.125 Mhz
DT 001H,0CDH,036H ; 12 738.950 Mhz
DT 001H,0CEH,036H ; 13 740.550 Mhz
DT 001H,0CFH,028H ; 14 741.800 Mhz
DT 001H,0CFH,03AH ; 15 742.250 Mhz

DT 001H,0C1H,03EH ;  0 719.950 Mhz
DT 001H,0C3H,021H ;  1 722.425 Mhz
DT 001H,0C3H,03DH ;  2 723.125 Mhz
DT 001H,0C4H,03AH ;  3 724.650 Mhz
DT 001H,0C5H,036H ;  4 726.150 Mhz
DT 001H,0C6H,03EH ;  5 727.950 Mhz
DT 001H,0C8H,017H ;  6 730.175 Mhz
DT 001H,0C9H,000H ;  7 731.200 Mhz
DT 001H,0C9H,022H ;  8 732.050 Mhz
DT 001H,0C9H,039H ;  9 732.625 Mhz
DT 001H,0CAH,03AH ; 10 734.250 Mhz
DT 001H,0CBH,03EH ; 11 735.950 Mhz
DT 001H,0CDH,014H ; 12 738.100 Mhz
DT 001H,0CDH,038H ; 13 739.000 Mhz
DT 001H,0CEH,039H ; 14 740.625 Mhz
DT 001H,0CFH,038H ; 15 742.200 Mhz

DT 001H,0C3H,03AH ;  0 723.050 Mhz
DT 001H,0C4H,005H ;  1 723.325 Mhz
DT 001H,0C4H,023H ;  2 724.075 Mhz
DT 001H,0C5H,028H ;  3 725.800 Mhz
DT 001H,0C5H,03BH ;  4 726.275 Mhz
DT 001H,0C7H,03FH ;  5 729.575 Mhz
DT 001H,0C8H,018H ;  6 730.200 Mhz
DT 001H,0C8H,03AH ;  7 731.050 Mhz
DT 001H,0C9H,037H ;  8 732.575 Mhz
DT 001H,0CAH,037H ;  9 734.175 Mhz
DT 001H,0CBH,03EH ; 10 735.950 Mhz
DT 001H,0CDH,016H ; 11 738.150 Mhz
DT 001H,0CDH,023H ; 12 738.475 Mhz
DT 001H,0CEH,024H ; 13 740.100 Mhz
DT 001H,0CFH,02AH ; 14 741.850 Mhz
DT 001H,0CFH,039H ; 15 742.225 Mhz



;---------TABLE_DISP----------------------------   
TABLE_DISP     ;频率显示码表
;        CLRF OFFSETH
;        PAGESEL DISP_PCL
;DISP_PCL
        MOVLW HIGH(FREQDISP)
        ADDWF OFFSETH,W
        MOVWF PCLATH
        MOVLW LOW(FREQDISP)
        ADDWF OFFSETL,W
        BTFSC STATUS,C
        INCF  PCLATH,F
        MOVWF PCL
FREQDISP:  
;1      
DT 0,0,0,0,0,0
DT 7,9,0,8,5,0
DT 7,9,1,4,7,5
DT 7,9,2,5,2,5
DT 7,9,3,1,5,0
DT 7,9,5,5,5,0
DT 7,9,7,0,5,0
DT 7,9,8,8,5,0
DT 8,0,0,6,5,0
DT 8,0,2,5,7,5
DT 8,0,3,7,2,5
DT 8,0,5,7,5,0
DT 8,0,6,8,5,0
DT 8,0,8,6,5,0
DT 8,1,1,7,2,5
DT 8,1,3,1,5,0
DT 8,1,3,8,0,0
;2
DT 7,9,1,4,0,0
DT 7,9,2,6,0,0
DT 7,9,3,9,2,5
DT 7,9,4,2,0,0
DT 7,9,5,7,2,5
DT 7,9,7,7,5,0
DT 7,9,9,4,0,0
DT 8,0,1,4,7,5
DT 8,0,3,1,0,0
DT 8,0,4,7,7,5
DT 8,0,5,8,0,0
DT 8,0,7,4,0,0
DT 8,0,9,2,0,0
DT 8,1,0,2,0,0
DT 8,1,2,7,7,5
DT 8,1,3,7,5,0
;3
DT 7,9,0,8,7,5
DT 7,9,1,4,5,0
DT 7,9,2,5,5,0
DT 7,9,3,1,7,5
DT 7,9,5,5,7,5
DT 7,9,7,0,7,5
DT 7,9,8,8,7,5
DT 8,0,1,1,0,0
DT 8,0,2,5,5,0
DT 8,0,3,7,0,0
DT 8,0,5,7,7,5
DT 8,0,6,8,7,5
DT 8,0,8,6,2,5
DT 8,1,1,7,0,0
DT 8,1,3,1,7,5
DT 8,1,3,7,7,5
;4
DT 7,9,2,6,2,5
DT 7,9,3,1,0,0
DT 7,9,3,4,5,0
DT 7,9,3,9,5,0
DT 7,9,5,0,2,5
DT 7,9,7,3,0,0
DT 7,9,9,4,2,5
DT 8,0,0,6,2,5
DT 8,0,4,8,0,0
DT 8,0,5,2,5,0
DT 8,0,7,4,7,5
DT 8,0,8,5,5,0
DT 8,0,9,9,7,5
DT 8,1,0,3,2,5
DT 8,1,1,6,0,0
DT 8,1,3,3,0,0

;5
DT 7,9,0,9,0,0
DT 7,9,1,4,2,5
DT 7,9,2,5,7,5
DT 7,9,3,2,0,0
DT 7,9,5,6,0,0
DT 7,9,7,1,0,0
DT 7,9,8,9,0,0
DT 8,0,1,1,2,5
DT 8,0,3,0,2,5
DT 8,0,3,6,7,5
DT 8,0,5,3,0,0
DT 8,0,6,9,0,0
DT 8,0,8,6,0,0
DT 8,1,0,0,5,0
DT 8,1,1,6,7,5
DT 8,1,3,1,2,5
;6
DT 7,9,2,6,5,0
DT 7,9,3,4,7,5
DT 7,9,3,9,7,5
DT 7,9,4,5,2,5
DT 7,9,5,0,5,0
DT 7,9,7,7,7,5
DT 7,9,9,4,5,0
DT 8,0,0,6,0,0
DT 8,0,4,8,2,5
DT 8,0,5,2,2,5
DT 8,0,7,4,5,0
DT 8,0,8,5,2,5
DT 8,0,9,9,5,0
DT 8,1,0,5,2,5
DT 8,1,1,5,7,5
DT 8,1,3,2,7,5
;7
DT 7,9,0,9,2,5
DT 7,9,3,2,2,5
DT 7,9,4,1,0,0
DT 7,9,5,6,2,5
DT 7,9,7,1,2,5
DT 7,9,8,9,2,5
DT 8,0,1,1,5,0
DT 8,0,2,1,7,5
DT 8,0,3,0,5,0
DT 8,0,3,6,5,0
DT 8,0,5,2,7,5
DT 8,0,6,9,2,5
DT 8,0,8,5,7,5
DT 8,1,0,0,2,5
DT 8,1,1,6,5,0
DT 8,1,3,1,0,0

DT 7,9,4,0,0,0
DT 7,9,4,3,0,0
DT 7,9,4,5,7,5
DT 7,9,5,1,0,0
DT 7,9,6,7,7,5
DT 7,9,7,8,0,0
DT 8,0,0,5,2,5
DT 8,0,2,0,0,0
DT 8,0,3,6,0,0
DT 8,0,5,2,0,0
DT 8,0,7,4,2,5
DT 8,0,9,1,2,5
DT 8,0,9,9,5,0
DT 8,1,1,5,5,0
DT 8,1,2,8,0,0
DT 8,1,3,2,5,0

DT 7,9,0,9,5,0
DT 7,9,3,4,2,5
DT 7,9,4,1,2,5
DT 7,9,5,6,5,0
DT 7,9,7,1,5,0
DT 7,9,8,9,5,0
DT 8,0,1,1,7,5
DT 8,0,2,2,0,0
DT 8,0,3,0,5,0
DT 8,0,3,6,2,5
DT 8,0,5,2,5,0
DT 8,0,6,9,5,0
DT 8,0,9,1,0,0
DT 8,1,0,0,0,0
DT 8,1,1,6,2,5
DT 8,1,3,2,0,0

DT 7,9,4,0,5,0
DT 7,9,4,3,2,5
DT 7,9,5,0,7,5
DT 7,9,6,8,0,0
DT 7,9,7,2,7,5
DT 8,0,0,5,7,5
DT 8,0,1,2,0,0
DT 8,0,2,0,5,0
DT 8,0,3,5,7,5
DT 8,0,5,1,7,5
DT 8,0,6,9,5,0
DT 8,0,9,1,5,0
DT 8,0,9,4,7,5
DT 8,1,1,1,0,0
DT 8,1,2,8,5,0
DT 8,1,3,2,2,5

        END

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

2
发表于 2014-7-10 21:24:14 | 只看该作者
汇编看着着实头大

出0入17汤圆

3
发表于 2014-7-10 21:32:24 | 只看该作者
好神奇,我居然看玩了。不过是鼠标自动滚动的,呵呵

出0入0汤圆

4
发表于 2014-7-10 21:34:22 | 只看该作者
我看不懂……还是觉得C好,起码能看懂……

出0入0汤圆

5
发表于 2014-7-10 22:06:31 | 只看该作者
大牛!
表示佩服!!!!!!!!!!!!!!!!!!!

出0入0汤圆

6
发表于 2014-7-10 22:15:23 来自手机 | 只看该作者
只会汇编的表示看着头大。

出0入0汤圆

7
发表于 2014-7-10 22:19:23 | 只看该作者
繁琐.........

出0入90汤圆

8
发表于 2014-7-10 22:22:30 | 只看该作者
费了好大的劲终于翻到能写评论的地方了。。。

出0入0汤圆

9
发表于 2014-7-10 22:25:59 | 只看该作者
楼主有论点论据,差论证了。

出0入0汤圆

10
发表于 2014-7-10 22:27:33 | 只看该作者
汇编看着着实头大

出0入4汤圆

11
发表于 2014-7-10 22:40:13 来自手机 | 只看该作者
为什么不用C?

出0入0汤圆

12
 楼主| 发表于 2014-7-10 23:22:28 | 只看该作者
lcofjp 发表于 2014-7-10 22:25
楼主有论点论据,差论证了。

可以上视频,不过第一次发,稍等

出0入0汤圆

13
 楼主| 发表于 2014-7-10 23:23:18 | 只看该作者

只有4KROOM 存储表格用了0.6K左右,用C不行的。公司的产品就这样

出0入134汤圆

14
发表于 2014-7-10 23:30:32 | 只看该作者
首先你有必要明确下是谁说PIC16F用C最好?

出0入4汤圆

15
发表于 2014-7-10 23:38:54 | 只看该作者
潇湘夜雨 发表于 2014-7-10 23:23
只有4KROOM 存储表格用了0.6K左右,用C不行的。公司的产品就这样

我就一直用C,如果不嫌麻烦,用函数指针,查表什么的,和汇编差不了多少的。
4K ROM已能写很多东西了,PIC的ROM是15位的,也就是差不多8K BYTE了。

出0入0汤圆

16
 楼主| 发表于 2014-7-10 23:51:22 | 只看该作者
lcofjp 发表于 2014-7-10 22:25
楼主有论点论据,差论证了。

没有优酷、土豆账号,用红米拍的视频居然104M 3GP文件,我就视频截图。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

17
 楼主| 发表于 2014-7-10 23:56:33 | 只看该作者
laujc 发表于 2014-7-10 23:38
我就一直用C,如果不嫌麻烦,用函数指针,查表什么的,和汇编差不了多少的。
4K ROM已能写很多东西了,PI ...

主要是液晶屏不断的刷屏,查找数据,闪烁,长按、短按,数字单一加减、快速加减,红外,锁相环,串口,液晶屏菜单,汇编16*16和16/16,以及用6位数的同步显示,进度指示~~~液晶屏需要存放12*16*6个8位数据+12*16*3个锁相环数据以及其他符合代码。
所以不能用C,上述功能需要塞进4K空间里面,汇编编译大概95%

出0入0汤圆

18
发表于 2014-7-11 00:10:38 来自手机 | 只看该作者
除了特殊要求! 一个项目 还需要后期维护和扩展。汇编维护起来很麻烦。

出0入4汤圆

19
发表于 2014-7-11 00:18:36 | 只看该作者
潇湘夜雨 发表于 2014-7-10 23:56
主要是液晶屏不断的刷屏,查找数据,闪烁,长按、短按,数字单一加减、快速加减,红外,锁相环,串口,液 ...

如果我做的话,宁愿加几毛钱换个ROM大点的。
辛苦你了。

出0入25汤圆

20
发表于 2014-7-11 01:10:41 来自手机 | 只看该作者
同样的价格买其他单片机16k flash都不成问题吧

出0入0汤圆

21
发表于 2014-7-11 08:26:01 | 只看该作者
呵呵,都是costdown逼的。

出0入0汤圆

22
发表于 2014-7-11 08:29:42 | 只看该作者
想当年在深圳, 好几年时间都只用固定的几种湾湾MCU, 兼容PIC的, ROM分别是512, 1024, 2048, 然后所有项目都要往这几颗IC上靠, 不管行不行的通,都先试试再说, 实在不行, 老板会跟客户说, 这单我们做不了, 反正不管如何折腾, 就是不换芯. 写程序当然是用汇编, 最开始乘除法都是从北航的一本PIC单片机书上摘抄整理的, 到后来我离职的时候, 16位的乘除我发现已经背下来了, 能直接默写出来... 就这样,其间我还挣扎过用PICC在上面折腾, 后来发现全是无用功, 到头来总是要用汇编重写一遍, PIC16系列MCU的架构, 实在是不太好用C语言, 局限性很大. 后来换工作了都是一直C/C++,去年用过一段时间DELPHI. 因为那段时间的汇编经历, 我现在写C代码的时候, 如果是我常用的MCU, 都会直接猜中编译器什么编译出什么样的机器码,  命中率85%以上, 这也算是用了几年汇编的一种收获吧.

出0入25汤圆

23
发表于 2014-7-11 09:10:37 | 只看该作者
tomhe666 发表于 2014-7-11 08:29
想当年在深圳, 好几年时间都只用固定的几种湾湾MCU, 兼容PIC的, ROM分别是512, 1024, 2048, 然后所有项目都 ...


大侠好厉害,,,

最近在分析Cortex-M0做float乘法的运算量问题,因为MDK库没有源代码只能看调试窗口的汇编代码,深感Cortex-M0的汇编难懂啊,分析到一半就看不下去了,,,另外发现浮点加法比浮点乘法的运算量多多了,更加不敢入手分析了

大侠有什么好的建议可以更简单的看汇编代码吗???


__aeabi_fmul:32位浮点乘法
Cortex-M0 61条指令
0x08001148 4602      MOV      r2,r0       //R0存储的是被乘数                        
0x0800114A B570      PUSH     {r4-r6,lr}

0x0800114C 404A      EORS     r2,r2,r1    //R1存储的是  乘数
0x0800114E 0FD3      LSRS     r3,r2,#31
0x08001150 07DB      LSLS     r3,r3,#31   //判断乘数和被乘数符号是否相同

0x08001152 0040      LSLS     r0,r0,#1
0x08001154 D02D      BEQ      0x080011B2  //判断被乘数是否为0,若为0直接返回
0x08001156 004A      LSLS     r2,r1,#1
0x08001158 D02A      BEQ      0x080011B0  //判断  乘数是否为0,若为0直接返回

0x0800115A 0E01      LSRS     r1,r0,#24
0x0800115C 0E14      LSRS     r4,r2,#24
0x0800115E 1909      ADDS     r1,r1,r4    //提取被乘数和乘数的指数,并相加

0x08001160 0200      LSLS     r0,r0,#8
0x08001162 0212      LSLS     r2,r2,#8
0x08001164 0A40      LSRS     r0,r0,#9
0x08001166 0A52      LSRS     r2,r2,#9    //提取被乘数和乘数的尾数

至此,R0和R2分别存储被乘数和乘数的尾数,R1存储被乘数和乘数的指数的和,R3存储的是数值0或1:0表示被乘数和乘数正负符号相同,1表示被乘数和乘数正负符号不同

0x08001168 1884      ADDS     r4,r0,r2
0x0800116A 01E5      LSLS     r5,r4,#7
0x0800116C 4604      MOV      r4,r0
0x0800116E 4354      MULS     r4,r2,r4

0x08001170 0A00      LSRS     r0,r0,#8
0x08001172 0A12      LSRS     r2,r2,#8
0x08001174 042E      LSLS     r6,r5,#16
0x08001176 4350      MULS     r0,r2,r0
0x08001178 19A4      ADDS     r4,r4,r6
0x0800117A 1942      ADDS     r2,r0,r5
0x0800117C 0C20      LSRS     r0,r4,#16
0x0800117E 43C5      MVNS     r5,r0
0x08001180 18AA      ADDS     r2,r5,r2
0x08001182 0C12      LSRS     r2,r2,#16
0x08001184 2501      MOVS     r5,#0x01
0x08001186 397F      SUBS     r1,r1,#0x7F
0x08001188 1C52      ADDS     r2,r2,#1
0x0800118A 03AD      LSLS     r5,r5,#14
0x0800118C 1952      ADDS     r2,r2,r5
0x0800118E 0412      LSLS     r2,r2,#16
0x08001190 0424      LSLS     r4,r4,#16
0x08001192 D000      BEQ      0x08001196
0x08001194 1C52      ADDS     r2,r2,#1
0x08001196 4310      ORRS     r0,r0,r2
0x08001198 D401      BMI      0x0800119E
0x0800119A 0040      LSLS     r0,r0,#1
0x0800119C 1E49      SUBS     r1,r1,#1
0x0800119E B2C2      UXTB     r2,r0
0x080011A0 060C      LSLS     r4,r1,#24
0x080011A2 09C0      LSRS     r0,r0,#7
0x080011A4 1820      ADDS     r0,r4,r0
0x080011A6 1C40      ADDS     r0,r0,#1
0x080011A8 0840      LSRS     r0,r0,#1
0x080011AA 2A80      CMP      r2,#0x80
0x080011AC D002      BEQ      0x080011B4
0x080011AE E003      B        0x080011B8
0x080011B0 2000      MOVS     r0,#0x00
0x080011B2 BD70      POP      {r4-r6,pc}
0x080011B4 0840      LSRS     r0,r0,#1
0x080011B6 0040      LSLS     r0,r0,#1
0x080011B8 2900      CMP      r1,#0x00
0x080011BA DA00      BGE      0x080011BE
0x080011BC 2000      MOVS     r0,#0x00
0x080011BE 4318      ORRS     r0,r0,r3
0x080011C0 BD70      POP      {r4-r6,pc}

出0入0汤圆

24
发表于 2014-7-11 12:36:46 | 只看该作者
XIVN1987 发表于 2014-7-11 09:10
大侠好厉害,,,

最近在分析Cortex-M0做float乘法的运算量问题,因为MDK库没有源代码只能看调试窗口的 ...

不好意思, 水平不够, 做不了大侠, 你这个问题我也不会

出0入34汤圆

25
发表于 2014-7-11 16:26:54 | 只看该作者
本帖最后由 epwwm 于 2014-7-11 16:35 编辑

这是U段无线咪接收机的频率表怎么跟我N年前开发的一模一样??

出0入0汤圆

26
 楼主| 发表于 2014-7-11 21:52:25 | 只看该作者
tomhe666 发表于 2014-7-11 08:29
想当年在深圳, 好几年时间都只用固定的几种湾湾MCU, 兼容PIC的, ROM分别是512, 1024, 2048, 然后所有项目都 ...

有同感,PIC其实合适汇编,其他空间大的MCU绝对不汇编

出0入0汤圆

27
 楼主| 发表于 2014-7-11 21:54:56 | 只看该作者
epwwm 发表于 2014-7-11 16:26
这是U段无线咪接收机的频率表怎么跟我N年前开发的一模一样??

频率表示移植的,在开发工具上码那么多字辛苦呀。
现在的无线麦频点都差不多

出0入0汤圆

28
 楼主| 发表于 2014-7-11 21:56:12 | 只看该作者
laujc 发表于 2014-7-11 00:18
如果我做的话,宁愿加几毛钱换个ROM大点的。
辛苦你了。

PIC公司用了整整10年了,现在还有用1K的没有中断的PIC,还要做32*32的整数乘除

出0入0汤圆

29
发表于 2014-7-11 23:05:11 | 只看该作者
曾经用了2年PIC汇编。如果专职就做软件,每天就写程序那没啥问题。如果事情多,要画板,要设计硬件,要焊接,要认证,想想汇编就头大。

出0入20汤圆

30
发表于 2014-7-12 07:40:45 | 只看该作者
10多年前在C51时代,就一直讨论用C好还是用汇编好,没有想到现在又开始在PIC上讨论C与汇编的好处了。个人结论:说汇编好的人,往往不会C,或者说没有用C开发过东西。
PIC的型号有很多,可以选择用大ROM的片子+C,也贵不了几个钱。但产品的维护性,排错性,多人合作性大幅提高。

出0入4汤圆

31
发表于 2014-7-12 08:46:08 | 只看该作者
mon51 发表于 2014-7-12 07:40
10多年前在C51时代,就一直讨论用C好还是用汇编好,没有想到现在又开始在PIC上讨论C与汇编的好处了。个人结 ...

同感,我刚开始做项目时,周边同事全部是用汇编的。
我以前在学校也是用汇编写程序。开始用c写时各种不适应。同事也是“另眼相看”,等着看笑话的样子。
现在用c熟练了,再不想用汇编了。PIC我们公司也在用,全部C,当然是不差线的用法,空间不够就直接换大的。老板只看早返率。这点成本不是问题。

出0入0汤圆

32
发表于 2014-7-12 14:40:40 来自手机 | 只看该作者
以前用汇编,现在改用c,再也不用汇编了,维护是大问题。

出0入0汤圆

33
发表于 2014-7-12 19:46:49 | 只看该作者
讨论汇编还是C 现在没有什么意义了,现在大家都在讨论构架。

出0入0汤圆

34
发表于 2014-7-12 21:08:15 | 只看该作者
后人接手你的项目,不易维护。

出0入0汤圆

35
发表于 2014-7-14 10:07:29 | 只看该作者
C和汇编灵活应用,仔细写C code,再看看优化后的汇编,理论差距有点,但是不是想象的大。

出0入0汤圆

36
发表于 2014-7-19 11:37:45 | 只看该作者
都用不更好,混合编程。HItech C挺接近汇编的

出0入0汤圆

37
发表于 2014-8-8 16:17:26 | 只看该作者
经常看看list文件,对提高自己写C有好处,出于维护性考虑,除了核心的几个,其它可以用C。。。汇编当年写了XXXX行。。。

出0入0汤圆

38
发表于 2014-8-8 17:08:34 | 只看该作者
等级不同啊            

出0入0汤圆

39
发表于 2014-8-8 17:08:49 | 只看该作者
我是用CCS C 的, 真的, 我不会汇编。。。
我知道新颖的PIC 的指令,是亲和C, 和C 优化的  (Optimization for C)

出0入0汤圆

40
发表于 2014-9-12 15:26:54 | 只看该作者
敲字敲得有点累

出0入0汤圆

41
发表于 2014-9-12 15:34:26 | 只看该作者
樓主如果自認爲自己寫的匯編代碼,比XC8編譯出來的要好,那你還等甚麼?趕快去MicroChip工作啊!他們太需要你這樣的人才了!

出0入0汤圆

42
发表于 2014-9-12 15:52:46 | 只看该作者
应该说现代的工程师比较幸福吧,尤其ARM又起来了,可用高阶来写,想当初用四位机时代,我只祈求编译器要强大点,其实就跟高阶差别不是很大了!

出0入0汤圆

43
发表于 2014-9-12 16:41:16 | 只看该作者
hyper320 发表于 2014-9-12 15:52
应该说现代的工程师比较幸福吧,尤其ARM又起来了,可用高阶来写,想当初用四位机时代,我只祈求编译器要强大点, ...

你用4 bit 的mcu? Intel 4004 那是CPU了,还得自己搭建外围电路,倒是接触过 Z80,

出0入0汤圆

44
发表于 2014-9-12 22:08:33 | 只看该作者
4004那是更早的了,二十几年前那时哪有这么多mcu阿,更别提OTP,了,FLASH可能还没出生,大多是日系的IC,如SANYO,NEC,TOSHIBA等,验证IC只能和原厂借ICE,因为买不起,太贵了,用ICE仿真完之后,要验证产品只能用PIGI-BACK,就是上面有可以插ROM的IC,然后把CODE烧到27C32,64等IC,而那时只有开窗,常需要用紫外灯清除,所以你绝对无法验证电器特性,因为连OTP都没有,等验证OK了,就要投CODE做MASK,也就是掩模,这一下CODE就要等三个月IC才能出炉,所以那时做产品都是战战兢兢的,深怕哪里没注意到,导致投的IC全部阵亡,后来慢慢的才有了OTP,并且验证IC也进步了,是开窗可清除的,记得那时用的第一种OTP就是MicroChip出的PIC16C54,55,56,57,开始用PIC16C54时还没ICE,还是用开窗IC烧进程序,验证程序看有没有问题,有问题要思考程序哪里出问题,改了程序再烧,这样子才把东西试出来!
所以感觉现代的工程师真是太幸福了!!

出0入0汤圆

45
发表于 2014-9-12 22:14:40 | 只看该作者
用汇编的都是牛人啊,看着就头痛

出0入0汤圆

46
发表于 2018-11-2 12:22:25 | 只看该作者
PIC16大多只有35条指令,习惯用汇编还是很爽的。

出0入0汤圆

47
发表于 2018-11-8 10:25:11 | 只看该作者
看汇编头大啊,如果没有特别详尽的注释,这么长的汇编,别说写,就是看都看不下去。

出0入0汤圆

48
发表于 2018-11-8 11:47:56 | 只看该作者
四年的帖子了,也不知道如今的编译器效率如何。
自己工作后第一个项目,就是汇编写的,PIC16F73芯片,一千多行。那会就一本张明峰的书,学校学的又是计算机软件开发,但就那么硬生生把汇编给啃下来了。
工作十年见过太多别人写的代码,会考虑执行效率的寥寥无几。所以只能说绝大多数人,还没把芯片用到需要汇编的地步,好好考虑下程序结构都能提升30%的效率和空间利用了。
不过真要建议所有做底层开发的工程师,若想提高一定要去学学汇编。汇编可以说是进入一款芯片内核的捷径。迄今为止,我的很多收获,依然是因为当年啃下了汇编。

出0入0汤圆

49
发表于 2018-11-9 17:41:39 来自手机 | 只看该作者
首先必须会用汇编,不然逆向没法搞。然后必须C语言,不然跟不上时代。会汇编不代表牛逼,不会的只能说基础不扎实。不管是会C还是汇编其实都不重要,都可以活得很好,当然也可能过得很苦逼.关键不是会什么技术,而是要会赚钱,把技术上的苦逼部分让别人做,这样才不会受制于技术而超越技术。

出0入0汤圆

50
发表于 2018-11-9 17:50:59 | 只看该作者
虽然是老帖子,我也说下自己,刚毕业用了四年汇编,用了10多种单片机,但是没有公司平台以后,自己耽误了一年,才重新定位。换句话说,前5年时间除了经验外,自己在c编程上没有任何长进。后来的公司不会给你用汇编的机会,以至于现在也是二八刷子。

出0入20汤圆

51
发表于 2018-11-13 17:14:18 | 只看该作者
这么老的帖子又翻出来了。估计楼主现在已经开始用C了。

出0入0汤圆

52
发表于 2018-11-13 17:18:19 | 只看该作者
pic啊,,,敬而远之,就好了,,,,

出0入0汤圆

53
发表于 2020-10-10 15:12:07 | 只看该作者
好神奇,我居然看玩了。不过是鼠标自动滚动的,呵呵

出0入0汤圆

54
发表于 2020-10-10 15:59:07 | 只看该作者
想相也用了好几年4位汇编。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 06:28

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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