;pIC16f627键盘显示+E2PROM存取+模拟I2C总线通信等模块示例程序
;已经调试通过,愿与各位初学者共享
list p=16f627 ; list directive to define processor
#include
;__CONFIG (_INCRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF & _PWRTE_ON & _BODEN_ON & _WDT_ON);
;数据寄存器及标号定义:
SDA EQU 2 ;PA2
SCL EQU 3 ;PA3
DSL EQU 4 ;PA4,LED低位
DSH EQU 7 ;PB7,LED高位
S1 EQU 1 ;PA1, UP
S2 EQU 0 ;PA0, DOWN
LED_L EQU 20H ;LED 低位数据积存器
LED_H EQU 21H ;LED 高位数据积存器
LED_NL EQU 22H ;LED 低位计数器
LED_NH EQU 23H ;LED 高位计数器
CH_X EQU 24H ;频道值寄存器
ADDR EQU 25H ;EEPROM 读写地址
VALU EQU 26H ;EEPROM 写入值
REC_ EQU 27H ;EEPROM 读计数
WRC_ EQU 28H ;EEPROM 写计数
DATA0 EQU 29H ;EEPROM 读出值
MD_ADDR_W EQU 0C8H ;3050 ADDRESS /WRITE
MD_ADDR_R EQU 0C9H ;3050 ADDRESS READ
DATA1 EQU 2AH ;3050寄存器组
DATA2 EQU 2BH ;
DATA3 EQU 2CH ;
DATA4 EQU 2DH ;
SG_S1 EQU 2FH ;SIGN_S1
SG_S2 EQU 30H ;SIGN_S2
W_TEMP EQU 31H
;W_TEMP EQU 0B1H
STATUS_TEMP EQU 32H
;STATUS_TEMP EQU 0B2H
WW EQU 33H ;通用寄存器
WW_TEMP EQU 34H
SG_DIS EQU 35H ;LED高低位显示标志
UVHF EQU 36H ;
BIT_SG EQU 37H ;
F0 EQU 0 ;I2C通信中应答信号正常(0)与不正常(1)标志
KEY_U EQU 1
KEY_D EQU 2
KEY_UOK EQU 3
KEY_DOK EQU 4
CUNT1 EQU 38H
CUNT2 EQU 39H
TIM_CUNT1 EQU 3AH ;
TIM_CUNT2 EQU 3BH ;
CUNT3 EQU 3EH
CUNT4 EQU 3FH
;////////////////////////////////////////////////////////////////////////////
;////////////////////////////////////////////////////////////////////////////
;---------------PROGRAM FILE-------------------
ORG 00H ; processor reset vector
GOTO START
ORG 04H
BTFSC PIR1,TMR1IF
GOTO T0_INT
RETFIE
ORG 10H
;////////////////////////////////////////////////////////////////
LED_VALU: MOVWF PCL ;
LED_TAB: RETLW 10H ;0
RETLW 73H ;1
RETLW 44H ;2
RETLW 41H ;3
RETLW 23H ;4
RETLW 09H ;5
RETLW 08H ;6
RETLW 53H ;7
RETLW 00H ;8
RETLW 01H ;9
;/////////////////////////////////////////////////////////////////
CXA_VALU1: MOVWF PCL
CXA_TAB1: DT 19H,24H ;CH0 DATA2, DATA3
DT 19H,24H ;CH1
……
DT 38H,04H ;CH12
CXA_VALU2: MOVWF PCL
CXA_TAB2: DT 75H,0C4H ;CH21 DATA2, DATA3
DT 77H,0C4H ;CH22
……
DT 0D5H,0C4H ;CH69
CXA_VALU3: MOVWF PCL
CXA_TAB3: DT 0ECH,62H ;CH21 DATA1, DATA4
DT 0ECH,62H ;CH22
……
DT 0ECH,62H ;CH69
START:
;CALL 3FFH
;MOVWF OSCCAL
CLRWDT
BSF STATUS,RP0 ;BANK1
BCF STATUS,RP1
BSF PCON,OSCF ;选择内部4M RC 震荡器
BCF STATUS,RP0 ;BANK0
CLRF PORTA ;I/O口设置
CLRF PORTB
MOVLW 07H
MOVWF CMCON
BSF STATUS,RP0 ;BANK1
MOVLW 0E3H ;PA.0.1.5.6.7为输入,其余为输出
MOVWF TRISA
MOVLW 00H
MOVWF TRISB
BCF STATUS,RP0 ;BANK0
MOVLW 20H ;寄存器20H/7FH清零
MOVWF FSR
LOOP: CLRF INDF
INCF FSR
BTFSS FSR,7
GOTO LOOP
;首次开机判别
NOP
NOP
MOVLW 00H ;检测EEPROM地址00H是否为55H
MOVWF ADDR ;EEPROM 地址→ADDR
CALL EEPROM_R ;ADDR 内容读至 DATA0
MOVF DATA0,W
ANDLW 0AAH
BTFSC STATUS,Z
GOTO OLD_CH
NOP ;首次开机 21 频道设定
MOVLW 00H ;EEPROM 的00H地址放首次开机标志
MOVWF ADDR
MOVLW 55H
MOVWF VALU
CALL EEPROM_W
MOVLW 01H ;EEPROM 的01H地址放频道值CH_X
MOVWF ADDR
MOVLW 15H ;05H ;
MOVWF VALU
CALL EEPROM_W
NOP
MOVLW 02H ;02H地址做 CH_X 备份,以防出错
MOVWF ADDR
MOVLW 05H
MOVWF VALU
CALL EEPROM_W
MOVLW 15H ;05H ;首次开机选择 CH5 频道
MOVWF CH_X
GOTO CH_SET
NOP
OLD_CH: MOVLW 01H
MOVWF ADDR
CALL EEPROM_R
MOVWF CH_X
CH_SET: CALL LED_HL
NOP
NOP
CALL CXA
NOP
;定时器1初始化
BSF INTCON,GIE ;总中断使能
BSF INTCON,PEIE ;
BCF PIR1,TMR1IF ;
BSF STATUS,RP0 ;BANK1
BSF PIE1,TMR1IE ;开定时器1中断
BCF STATUS,RP0 ;BANK0
MOVLW 0D8H ;TIM1 中断周期 10 ms
MOVWF TMR1H ;
MOVLW 0EFH
MOVWF TMR1L
CLRF T1CON
BSF T1CON,TMR1ON ;定时器1启动
GOTO MAIN
MAIN: NOP
NOP
CLRWDT
NOP
NOP
;GOTO MAIN
;CALL DELAY ;延时10毫秒
NOP
NOP
NOP
NOP
BTFSC BIT_SG,KEY_U
CALL KEY_INC
NOP
NOP
NOP
NOP
BTFSC BIT_SG,KEY_D
CALL KEY_DEC
NOP
NOP
NOP
NOP
BTFSC BIT_SG,KEY_DOK
GOTO KEY_DEC_OK
NOP
NOP
NOP
NOP
BTFSC BIT_SG,KEY_UOK
GOTO KEY_INC_OK
NOP
NOP
NOP
NOP
GOTO MAIN
KEY_DEC_OK: NOP
CALL KEY_DEC ;确认有 DOWN 键按下并放开
NOP
BCF BIT_SG,KEY_DOK
GOTO CH_NEW
KEY_INC_OK: NOP
CALL KEY_INC ;确认有 UP 键按下并放开
NOP
BCF BIT_SG,KEY_UOK
CH_NEW: CLRF SG_S1
CLRF SG_S2
NOP
CALL LED_HL ;显示新频道
NOP
NOP
CALL CXA ;设定新频道
NOP
NOP
MOVF CH_X,W
MOVWF VALU
MOVLW 01H
MOVWF ADDR
NOP
CALL EEPROM_W ;保存新频道
NOP
NOP
GOTO MAIN
KEY_INC: MOVF CH_X,W
MOVWF WW
MOVLW 0CH ;
SUBWF WW,W
BTFSC STATUS,Z
GOTO CH21 ;CH_X = CH12 加 1 转 CH_21
MOVLW 45H ;
SUBWF WW,W
BTFSC STATUS,Z
GOTO CH21 ;CH5 ;CH_X = CH69 加 1 转 CH_5
INCF CH_X,F ;其它正常加 1
GOTO INC_RET
CH21: MOVLW 15H
MOVWF CH_X
GOTO INC_RET
CH5: MOVLW 05H
MOVWF CH_X
NOP
INC_RET: NOP
CALL LED_HL
BCF BIT_SG,KEY_U
RETURN
KEY_DEC: NOP
MOVF CH_X,W ;确认有 DOWN 键按下
MOVWF WW
MOVLW 05H
SUBWF WW,W
BTFSC STATUS,Z
GOTO CH69 ;CH_X = CH5 减 1 转 CH_68
MOVLW 15H
SUBWF WW,W
BTFSC STATUS,Z
GOTO CH69 ;CH12 ;CH_X = CH21 减 1 转 CH_12
DECF CH_X,F ;其它正常减 1
GOTO DEC_RET
CH69: MOVLW 45H ;CH_69
MOVWF CH_X
GOTO DEC_RET
CH12: MOVLW 0CH ;CH_12
MOVWF CH_X
NOP
DEC_RET: CALL LED_HL
BCF BIT_SG,KEY_D
NOP
RETURN
;////////////////////////////////////////////////////////////////////////
T0_INT:
MOVWF W_TEMP
SWAPF STATUS,W
MOVWF STATUS_TEMP
MOVF WW,W
MOVWF WW_TEMP
BCF STATUS,RP0
BCF PIR1,TMR1IF
MOVLW 0D8H ;TIM1 中断周期 10 ms
MOVWF TMR1H ;
MOVLW 0EFH
MOVWF TMR1L
CLRWDT
MOVF TIM_CUNT1,W ;计数器TIM_CUNT1
BTFSC STATUS,Z
GOTO INT00
DECF TIM_CUNT1,F
INT00: NOP
NOP
MOVF TIM_CUNT2,W ;计数器TIM_CUNT2
BTFSC STATUS,Z
GOTO INT01
DECF TIM_CUNT2,F
INT01: NOP
NOP
CALL DISPLAY ;显示LED
NOP
NOP
CALL KEYBOARD ;检测键盘
NOP
NOP
NOP
NOP ;
MOVF WW_TEMP,W
MOVWF WW
SWAPF STATUS_TEMP,W
MOVWF STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W
RETFIE
;////////////////////////////////////////////////////////////////////////
KEYBOARD:
BCF STATUS,RP0
BCF STATUS,RP1 ;BANK0
BTFSS PORTA,S1
GOTO DOWN
NOP
BTFSS PORTA,S2
GOTO UP
GOTO KEY_SCH
;去抖动
DOWN: BTFSS SG_S1,0
GOTO DOWN1 ;第一次有 DOWN 键按下
BTFSC SG_S1,1
GOTO DOWN2 ;长按键
BSF SG_S1,1 ;确认有 DOWN 键按下
GOTO KEY_RET
DOWN1: BSF SG_S1,0 ;第一次有 DOWN 键按下标志
GOTO KEY_RET
NOP
DOWN2: BTFSC SG_S1,2
GOTO DOWN3
MOVLW 14H ;确认有长键延时 200 ms
MOVWF TIM_CUNT1
BSF SG_S1,2
GOTO KEY_RET
DOWN3: MOVF TIM_CUNT1,W
BTFSS STATUS,Z
GOTO KEY_RET
BSF BIT_SG,KEY_D ;
MOVLW 14H ;长按键周期200 ms
MOVWF TIM_CUNT1
GOTO KEY_RET
UP: BTFSS SG_S2,0
GOTO UP1 ;第一次有 UP 键按下
BTFSC SG_S2,1
GOTO UP2 ;长按键
BSF SG_S2,1 ;确认有 UP 键按下
GOTO KEY_RET
UP1: BSF SG_S2,0 ;第一次有 UP 键按下标志
GOTO KEY_RET
NOP
UP2: BTFSC SG_S2,2
GOTO UP3
MOVLW 14H ;确认有长键延时 200 ms
MOVWF TIM_CUNT2
BSF SG_S2,2
GOTO KEY_RET
UP3: MOVF TIM_CUNT2,W
BTFSS STATUS,Z
GOTO KEY_RET
BSF BIT_SG,KEY_U ;
MOVLW 14H ;长按键周期200 ms
MOVWF TIM_CUNT2
GOTO KEY_RET
;
KEY_SCH: BTFSS SG_S1,1
GOTO KEY_SCH1
BSF BIT_SG,KEY_DOK ;确认有 DOWN 键按下并放开
GOTO KEY_RET
KEY_SCH1: BTFSS SG_S2,1
GOTO NOKEY
BSF BIT_SG,KEY_UOK ;确认有 UP 键按下并放开
GOTO KEY_RET
NOKEY: CLRF SG_S1 ;排除干扰
CLRF SG_S2
KEY_RET: NOP
NOP
RETURN
;//////////////// ;LED显示 /////////////////////////////////////////////////////////
DISPLAY: NOP
BTFSC SG_DIS,0
GOTO DIS_H
DIS_L: BCF PORTB,DSH ;显示低位
MOVF LED_L,W
MOVWF PORTB
BSF PORTA,DSL
BSF SG_DIS,0
GOTO DIS_RET
DIS_H: BCF PORTA,DSL ;显示高位
MOVF LED_H,W
MOVWF PORTB
BSF PORTB,DSH
BCF SG_DIS,0
DIS_RET: NOP
RETURN
;//////////////// LED显示值获取 /////////////////////////////////////////////////////////
LED_HL: CLRF LED_NH
CLRF LED_NL
MOVF CH_X,W
MOVWF WW
LED0: MOVLW 0AH
SUBWF WW,W
BTFSS STATUS,C ;SKPC
GOTO LED_OK ;WW小于10
MOVWF WW
INCF LED_NH ;高位加一
GOTO LED0
LED_OK: MOVF WW,W
MOVWF LED_NL ;余数做低位
MOVLW LED_TAB ;取表LED_TAB
MOVWF WW
MOVF LED_NL,W
ADDWF WW,W ;
CALL LED_VALU
MOVWF LED_L
MOVLW LED_TAB ;取表LED_TAB
MOVWF WW
MOVF LED_NH,W
ADDWF WW,W ;
CALL LED_VALU
MOVWF LED_H
RETURN
;//////////////////////////////////////////////////////////////////////////////////
;///////////////频道设定///////////////////////////////////////////////////////////
CXA: BCF STATUS,RP0
BCF STATUS,RP1 ;BANK0
CLRWDT
MOVF CH_X,W ;VHF/UHF 判断
MOVWF UVHF
SUBLW 0DH ;CH_X 是否小于13?
BTFSC STATUS,C ;SKPC
GOTO VHF_GET ;小于则转VHF_GET
MOVLW 15H ; 21
SUBWF UVHF,F ;频道值入UVHF
UHF_GET: MOVLW CXA_TAB2 ;取表CXA_TAB2
MOVWF WW
BCF STATUS,C ;CLRC
RLF UVHF,F
MOVF UVHF,W
ADDWF WW,W ;
CALL CXA_VALU2
MOVWF DATA2
INCF UVHF
MOVF UVHF,W
ADDWF WW,W ;
CALL CXA_VALU2
MOVWF DATA3
GOTO I2C_SEND
DECF UVHF ;DATA1,DATA4
MOVLW CXA_TAB3 ;取表CXA_TAB3
MOVWF WW
;BCF STATUS,C ;CLRC
;RLF UVHF,F
MOVF UVHF,W
ADDWF WW,W ;
CALL CXA_VALU3
MOVWF DATA1
INCF UVHF
MOVF UVHF,W
ADDWF WW,W ;
CALL CXA_VALU3
MOVWF DATA4
GOTO I2C_SEND
;////////////////////////////////////////////////////////////
VHF_GET: MOVLW CXA_TAB1 ;取表CXA_TAB1
MOVWF WW
BCF STATUS,C ;CLRC
RLF UVHF,F
MOVF UVHF,W
ADDWF WW,W ;
CALL CXA_VALU1
MOVWF DATA2
INCF UVHF
MOVF UVHF,W
ADDWF WW,W ;
CALL CXA_VALU1
MOVWF DATA3
GOTO I2C_SEND
DECF UVHF ;DATA1,DATA4
MOVLW CXA_TAB3 ;取表CXA_TAB4
MOVWF WW
;BCF STATUS,C ;CLRC
;RLF UVHF,F
MOVF UVHF,W
ADDWF WW,W ;
CALL CXA_VALU3
MOVWF DATA1
INCF UVHF
MOVF UVHF,W
ADDWF WW,W ;
CALL CXA_VALU3
MOVWF DATA4
GOTO I2C_SEND
;/////////////////////////////////////////////////////////////////////////////
I2C_SEND: NOP
MOVLW B’11101100’
MOVWF DATA1
MOVLW 00H;B’01100010’
MOVWF DATA4
I2C_START: NOP
CLRWDT
BCF INTCON,GIE
MOVLW 04H ;发送4个字节
MOVWF CUNT2
CALL STA ;启动I2C总线
MOVLW MD_ADDR_W ;I2C地址
MOVWF WW
CALL WRBYT
CALL CACK
BTFSC BIT_SG,F0
GOTO I2C_START ;非应答位则重发
MOVLW DATA1 ;所发4字节数据的首地址
MOVWF FSR
WRDA: MOVF INDF,W
MOVWF WW
CALL WRBYT
CALL CACK
BTFSC BIT_SG,F0
GOTO I2C_SEND ;发送有误,重发
INCF FSR
DECFSZ CUNT2,F
GOTO WRDA
CALL STOP
BSF INTCON,GIE
RETURN
STA: BSF PORTA,SDA
BSF PORTA,SCL
NOP
NOP
NOP
NOP
BCF PORTA,SDA
NOP
NOP
NOP
NOP
BCF PORTA,SCL
RETURN
STOP: BCF PORTA,SDA
BSF PORTA,SCL
NOP
NOP
NOP
NOP
BSF PORTA,SDA
NOP
NOP
NOP
NOP
BCF PORTA,SDA
BCF PORTA,SCL
RETURN
CACK: BSF STATUS,RP0
BSF TRISA,SDA
BCF STATUS,RP0
BSF PORTA,SCL
NOP
NOP
NOP
NOP
BCF BIT_SG,F0
BTFSC PORTA,SDA
BSF BIT_SG,F0
CEND: BCF PORTA,SCL
BSF STATUS,RP0
BCF TRISA,SDA
BCF STATUS,RP0
RETURN
WRBYT: MOVLW 08H
MOVWF CUNT1
WLP: RLF WW,F
BTFSS STATUS,C ;SKPC
GOTO WR0
GOTO WR1
WLP1: DECFSZ CUNT1,F
GOTO WLP
RETURN
WR1: BSF PORTA,SDA
BSF PORTA,SCL
NOP
NOP
NOP
NOP
BCF PORTA,SCL
BCF PORTA,SDA
GOTO WLP1
WR0: BCF PORTA,SDA
BSF PORTA,SCL
NOP
NOP
NOP
NOP
BCF PORTA,SCL
GOTO WLP1
;//////////////////////////////////////////////////////////////////////////
;//////////////////////////////////////////////////////////////////////////
EEPROM_R: ;EEPROM 读子程序,把地址ADDR中内容读至DATA0
BCF STATUS,RP1 ;BANK0
BCF STATUS,RP0
MOVF ADDR,W
BSF STATUS,RP0 ;BANK1
MOVWF EEADR
BCF EECON1,WRERR
BSF EECON1,RD
MOVF EEDATA,W
BCF STATUS,RP0 ;BANK0
MOVWF DATA0
RETURN ;不带参数返回
;//////////////////////////////////////////////////////////////////////////
EEPROM_W: ;EEPROM 写子程序,把VALU中数值写入地址ADDR
CLRWDT
BCF STATUS,RP1 ;BANK1
BSF STATUS,RP0
BTFSC EECON1,WR ;等待写允许
GOTO $-1
BCF STATUS,RP0 ;BANK0
MOVF ADDR,W
BSF STATUS,RP0 ;BANK1
MOVWF EEADR
BCF STATUS,RP0 ;BANK0
MOVF VALU,W
BSF STATUS,RP0 ;BANK1
MOVWF EEDATA
BCF EECON1,WRERR
BSF EECON1,WREN
BCF INTCON,GIE
MOVLW 55H
MOVWF EECON2
MOVLW 0AAH
MOVWF EECON2
BSF EECON1,WR
BTFSC EECON1,WR
GOTO $-1
BSF INTCON,GIE ;写结束
BCF EECON1,WREN
BCF STATUS,RP0 ;BANK0
RETURN ;不带参数返回
;////////////////////////////////////////////////////////////////////////
;////////////////////////////////////////////////////////////////////////
DELAY: MOVLW 05H
MOVWF CUNT3
DELAY1: NOP ;2ms
CLRWDT
MOVLW 0FFH
MOVWF CUNT4
DELAY2: NOP
MOVF CUNT4,W
NOP
BTFSC STATUS,Z
GOTO DELAY3
NOP
DECF CUNT4,F
NOP
GOTO DELAY2
DELAY3: NOP
MOVF CUNT3,W
BTFSC STATUS,Z
GOTO DELAY_RET
NOP
DECF CUNT3,F
NOP
GOTO DELAY1
NOP
DELAY_RET: RETURN
;////////////////////////////////////////////////////////////////////////
;////////////////////////////////////////////////////////////////////////
FILL (GOTO $),NEXT_BLOCK-$
ORG 03FFH
NEXT_BLOCK:
END
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』