;=======================================
;PIC16C74B单片机与AT24C64通讯
;该程序实现的功能是:
;将I2C_A,I2C_B.....I2C_K内容写入EEPROM中
;同时在EEPROM中读出数据从新写入各个寄存器
;=======================================
LIST P=16C74B
#include
ERRORLEVEL -302
I2C_A EQU 0X20
I2C_B EQU 0X21
I2C_C EQU 0X22
I2C_D EQU 0X23
I2C_E EQU 0X24
I2C_F EQU 0X25
I2C_G EQU 0X26
REG1 EQU 0X2B
REG2 EQU 0X2C
COUNT EQU 0X71 ;I2C
BCOUNT EQU 0X72 ;I2C
TXBUF EQU 0X73 ;I2C
RXBUF EQU 0X74 ;I2C
BUSCON EQU 0X75 ;I2C
BUSSTA EQU 0X76 ;I2C
I2CBUF EQU 0X77 ;I2C
SLAVEADDR EQU 0XA0 ;I2C
DATAADDRH EQU 0X01 ;I2C
DATAADDRL EQU 0X00 ;I2C
;---------------------------------------
;BUSCON
;---------------------------------------
SLAVE_RW EQU 7
LAST_BYTE_RX EQU 6
SLAVE_ACTIVE EQU 5
TIME_OUT EQU 4
;---------------------------------------
;BUSSTA
;---------------------------------------
BUS_BUSY EQU 7
TX_PROGRESS EQU 6
RX_PROGRESS EQU 5
TX_SUCCESS EQU 4
RX_SUCCESS EQU 3
FATAL_ERROR EQU 2 ;SLAVE EEPROM
ABORT EQU 1
ACK_ERROR EQU 0
;---------------------------------------
R_NOT_W EQU 0
TRUE EQU 1
FALSE EQU 0
SDA EQU 0X04 ;I2C
SCL EQU 0X03 ;I2C
;=======================================
ORG 0X00
GOTO START
ORG 0X20
START BCF STATUS,RP1
BCF STATUS,RP0
CLRF RA
CLRF RB
CLRF RC
CLRF RD
CLRF RE
BSF STATUS,RP0
CLRF TRISA
CLRF TRISB
CLRF TRISC
CLRF TRISD
CLRF TRISE
MOVLW 0X02
MOVWF I2C_A
MOVLW 0X04
MOVWF I2C_B
MOVLW 0X03
MOVWF I2C_C
MOVLW 0X03
MOVWF I2C_D
MOVLW 0X05
MOVWF I2C_E
MOVLW 0X06
MOVWF I2C_F
MOVLW 0X04
MOVWF I2C_G
;=======================================
START1
CALL I2CBUS_INIT
CALL REGTOI2CBUF
CALL I2CWRITE
CALL CLRI2CBUF
CALL D10
CALL I2CREAD
CALL I2CBUFTOREG
GOTO START1
;=======================================
;CLRI2CBUF
;---------------------------------------
CLRI2CBUF
BCF STATUS,RP0
MOVLW I2CBUF
MOVWF FSR
MOVLW 0X08
MOVWF COUNT
CLRLOOP CLRF INDF
INCF FSR,F
DECFSZ COUNT,F
GOTO CLRLOOP
RETURN
;---------------------------------------
;将各个REGSTER数据写入 I2CBUF 缓冲区
;---------------------------------------
REGTOI2CBUF
BCF STATUS,RP0
MOVLW I2CBUF
MOVWF FSR
MOVF I2C_A,W
MOVWF INDF
INCF FSR,F
MOVF I2C_B,W
MOVWF INDF
INCF FSR,F
MOVF I2C_C,W
MOVWF INDF
INCF FSR,F
MOVF I2C_D,W
MOVWF INDF
INCF FSR,F
MOVF I2C_E,W
MOVWF INDF
INCF FSR,F
MOVF I2C_F,W
MOVWF INDF
INCF FSR,F
MOVF I2C_G,W
MOVWF INDF
RETURN
;---------------------------------------
;将 I2CBUF 缓冲区数据写入各个REGSTER
;---------------------------------------
I2CBUFTOREG
BCF STATUS,RP0
MOVLW I2CBUF
MOVWF FSR
MOVF INDF,W
MOVWF I2C_A
INCF FSR,F
MOVF INDF,W
MOVWF I2C_B
INCF FSR,F
MOVF INDF,W
MOVWF I2C_C
INCF FSR,F
MOVF INDF,W
MOVWF I2C_D
INCF FSR,F
MOVF INDF,W
MOVWF I2C_E
INCF FSR,F
MOVF INDF,W
MOVWF I2C_F
INCF FSR,F
MOVF INDF,W
MOVWF I2C_G
RETURN
;=======================================
;将I2CBUF缓冲区内的数据写入EEPROM
;=======================================
I2CWRITE
CALL I2CSTART
BTFSS BUSSTA,BUS_BUSY
GOTO TX_FAIL
BCF BUSCON,SLAVE_RW
CALL TX_SLAVE_ADDR
BTFSS BUSSTA,TX_SUCCESS ;SUCESSFULL?
GOTO TX_FAIL
CALL TX_DATA_ADDR
BTFSS BUSSTA,TX_SUCCESS
GOTO TX_FAIL
MOVLW I2CBUF
MOVWF FSR
MOVLW 07
MOVWF COUNT
T_BYTE_LOOP
MOVF INDF,W
MOVWF TXBUF
CALL I2CTXB
BTFSS BUSSTA,TX_SUCCESS
GOTO TX_FAIL
INCF FSR,F
DECFSZ COUNT,F
GOTO T_BYTE_LOOP
GOTO TX_PASS
TX_FAIL CALL I2CSTOP
BCF BUSSTA,TX_PROGRESS
BCF BUSSTA,TX_SUCCESS
RETLW FALSE
TX_PASS
CALL I2CSTOP
BCF BUSSTA,TX_PROGRESS
RETLW TRUE
;---------------------------------------
;从 EEPROM 中读出数据到 I2CBUF 寄存器
;---------------------------------------
I2CREAD BCF STATUS,RP0
BCF BUSSTA,RX_SUCCESS
CALL I2CSTART
BTFSS BUSSTA,BUS_BUSY
GOTO RX_FAIL
BCF BUSCON,SLAVE_RW
CALL TX_SLAVE_ADDR
BTFSS BUSSTA,TX_SUCCESS
GOTO RX_FAIL
CALL TX_DATA_ADDR
BTFSS BUSSTA,TX_SUCCESS
GOTO RX_FAIL
CALL I2CSTART
BSF BUSCON,SLAVE_RW
CALL TX_SLAVE_ADDR
BTFSS BUSSTA,TX_SUCCESS
GOTO RX_FAIL
BCF BUSSTA,LAST_BYTE_RX
MOVLW I2CBUF
MOVWF FSR
MOVLW 07
MOVWF COUNT
R_BYTE_LOOP
MOVLW 0X01
XORWF COUNT,W
BTFSC STATUS,Z
BSF BUSSTA,LAST_BYTE_RX
CALL I2CRXB
BTFSS BUSSTA,RX_SUCCESS
GOTO RX_FAIL
MOVF RXBUF,W
MOVWF INDF
INCF FSR,F
DECFSZ COUNT,F
GOTO R_BYTE_LOOP
GOTO RX_PASS
RX_FAIL CALL I2CSTOP
BCF BUSSTA,RX_PROGRESS
BCF BUSSTA,RX_SUCCESS
RETLW FALSE
RX_PASS CALL I2CSTOP
BCF STATUS,RP0
BCF BUSSTA,TX_PROGRESS
BCF BUSSTA,RX_PROGRESS
BSF BUSSTA,RX_SUCCESS
RETLW TRUE
;=======================================
; I2C 初始化
;=======================================
I2CBUS_INIT
BCF STATUS,RP0
MOVF RC,W
ANDLW 0X18
MOVWF RC
CLRF BUSSTA
CLRF BUSCON
RETURN
;=======================================
; 传送设备地址
;入口: BUSCON
;出口: BUSSTA
;=======================================
TX_SLAVE_ADDR
BCF STATUS,RP0
BCF BUSSTA,ACK_ERROR
MOVLW SLAVEADDR
MOVWF TXBUF
BTFSC BUSCON,SLAVE_RW
BSF TXBUF,R_NOT_W
CALL I2CTXB
BTFSC BUSSTA,TX_SUCCESS
GOTO TXADDR_SUCCESS
CLRWDT
BTFSS BUSSTA,ACK_ERROR
CALL I2CSTOP
GOTO TXADDR_END
TXADDR_SUCCESS
CLRWDT
TXADDR_END
RETURN
;=======================================
;TX_DATA_ADDR 发送写/读的地址
;=======================================
TX_DATA_ADDR
BCF STATUS,RP0
MOVLW DATAADDRH
MOVWF TXBUF
CALL I2CTXB
BCF STATUS,RP0
BTFSS BUSSTA,TX_SUCCESS
GOTO TX_DATA_ADDR_ERROR
MOVLW DATAADDRL
MOVWF TXBUF
CALL I2CTXB
BCF STATUS,RP0
BTFSS BUSSTA,TX_SUCCESS
GOTO TX_DATA_ADDR_ERROR
GOTO TX_DATA_END
TX_DATA_ADDR_ERROR
BCF BUSSTA,TX_PROGRESS
BCF BUSSTA,TX_SUCCESS
BSF BUSSTA,ACK_ERROR
TX_DATA_END
RETURN
;=======================================
;向 EEPROM 输出一个8位数据,并检测EEPROM的ACK信号
;入口: TXBUF 寄存器
; BUSSTA 寄存器
;出口: EEPROM 存储器
; BUSSTA 寄存器
;======================================
I2CTXB BCF STATUS,RP0
BSF BUSSTA,TX_PROGRESS
BCF BUSSTA,TX_SUCCESS
MOVLW 0X08
MOVWF BCOUNT
TXLOOP CLRWDT
BSF STATUS,RP0
BCF TRISC,SCL
NOP
BCF TRISC,SDA
BCF STATUS,RP0
RLF TXBUF,F
BSF STATUS,RP0
BTFSC STATUS,C
BSF TRISC,SDA
NOP
BSF TRISC,SCL
NOP
NOP
BCF STATUS,RP0
DECFSZ BCOUNT,F
GOTO TXLOOP
;---------------------------------------
;检测是EEPROM否有ACK信号产生,产生为正常
;检测方法:
; 1. 将RC口的SCL.SDA分别设置为输出和输入状态
; 2. 延时2个指令周期,将SCL设置为高电平
; 3. 延时2个指令周期,检测RC口SDA的状态
; 4. 如果为高电平,设置错误状态,返回
; 5. 如果为低电平,延时2个指令周期后,将RC口SCL设置为低电平,继续执行
;---------------------------------------
BSF STATUS,RP0
BCF TRISC,SCL
BSF TRISC,SDA
NOP
NOP
BSF TRISC,SCL
NOP
BCF STATUS,RP0
BTFSC RC,SDA
GOTO TX_ERR
BSF STATUS,RP0
BCF TRISC,SCL
BCF STATUS,RP0
BCF BUSSTA,TX_PROGRESS
BSF BUSSTA,TX_SUCCESS
BCF BUSSTA,ACK_ERROR
GOTO TX_END
TX_ERR BCF BUSSTA,TX_PROGRESS
BCF BUSSTA,TX_SUCCESS
BSF BUSSTA,ACK_ERROR
TX_END RETURN
;=======================================
;从EEPROM中读出 8 位的数据,并发送发送ACK信号
;入口: EEPROM 存储器
; BUSCON 寄存器
;出口: RXBUF 寄存器
; BUSSTA 寄存器
;=======================================
I2CRXB BCF STATUS,RP0
BSF BUSSTA,RX_PROGRESS
BCF BUSSTA,RX_SUCCESS
MOVLW 0X08
MOVWF BCOUNT
RXLOOP CLRWDT
BSF STATUS,RP0
BCF TRISC,SCL ;定义TRISC为输出
BSF TRISC,SDA ;定义TRISC为输入
NOP
NOP
BSF TRISC,SCL ;TRISC输出高电平
NOP
BCF STATUS,RP0
BCF STATUS,C
BTFSC RC,SDA ;原指令为BTFSC TRISC,SDA
BSF STATUS,C
RLF RXBUF,F
DECFSZ BCOUNT,F
GOTO RXLOOP
;---------------------------------------
;发送ACK信号到EEPROM
;判断接收的是否为最后一个字节
;LAST_BYTE_RX为1,是 SDA发送一个高电平,结束
;LAST_BYTE_RX为0,不是 SDA发送一个低电平ACK,继续接收
;---------------------------------------
BSF STATUS,RP0
BCF TRISC,SCL
BCF TRISC,SDA
BTFSC BUSCON,LAST_BYTE_RX ;检测是否是最后一个字节
BSF TRISC,SDA ;是最后一个字节
NOP ;发送ACK信号
BSF TRISC,SCL
NOP
NOP
NOP
NOP
BCF TRISC,SCL
BCF STATUS,RP0
BCF BUSSTA,RX_PROGRESS
BSF BUSSTA,RX_SUCCESS
RETURN
;=======================================
;I2C 开始信号
;输入: 无
;输出: BUFSSTA
;=======================================
I2CSTART
BSF STATUS,RP0
BSF TRISC,SDA ;1US
NOP ;1US
BSF TRISC,SCL ;1US
NOP
NOP
BCF TRISC,SDA
NOP
NOP
BCF STATUS,RP0
BSF BUSSTA,BUS_BUSY
RETURN
;=======================================
;I2C 结束信号
;输入: 无
;输出: BUSSTA
;=======================================
I2CSTOP
BSF STATUS,RP0
BCF TRISC,SCL
BCF TRISC,SDA
BSF TRISC,SCL
NOP
NOP
BSF TRISC,SDA
NOP
BCF STATUS,RP0
BCF BUSSTA,BUS_BUSY
RETURN
;=======================================
; D10 @
; clock in 4Mhz
; delay 10ms
;=======================================
D10 MOVLW 0X0D
MOVWF REG1
LOOP2 MOVLW 0XFF
MOVWF REG2
LOOP1 DECFSZ REG2,f
GOTO LOOP1
DECFSZ REG1,f
GOTO LOOP2
RETURN
;=======================================
I2CERR CLRWDT
NOP
NOP
NOP
RETURN
END
SSP控制寄存器SSPCON
WCOL SSPOV SSPEN CKP SSPM3 SSPM2 SSPM1 SSPM0 地址:14h上电值:00h
│ │ │ │ │ │
│ │ │ │ ├────────────┘
│ │ │ │ │
│ │ │ │ └── 同步串行口(SSP)模式选择
│ │ │ │ 0000= SPI主控模式,时针=OSC/4
│ │ │ │ 0001= SPI主控模式,时针=OSC/16
│ │ │ │ 0010= SPI主控模式,时针=OSC/64
│ │ │ │ 0011= SPI主控模式,时钟=TMR2输出/2
│ │ │ │ 0100= SPI从属模式,时钟=SCK脚输入,SS脚使能
│ │ │ │ 0101= SPI从属模式,时钟=SCK脚输入,SS脚关闭
│ │ │ │ 0110=I2C从属模式,7位地址
│ │ │ │ 0111=I2C从属模式,10位地址
│ │ │ │ 1011=I2C主控模式(从属模式关闭)
│ │ │ │ 1110=I2C从属模式,7位地址,并支持主控模式
│ │ │ │ 1111=I2C从属模式,10位地址,并支持主控模式
│ │ │ └───── 时钟极性选择
│ │ │ ·SPI模式
│ │ │ 1=下降沿发送,上升沿接收
│ │ │ 0=上升沿发送,下降沿接收
│ │ │ ·I2C模式
│ │ │ 1=时钟使能(时钟线释放)
│ │ │ 0=时钟线锁定为低电平,以保证数据建立时间
│ │ └────── 同步串行口(SSP)使能位
│ │ ·SPI模式
│ │ 1=使能SPI模块,并定义SCK,SDO和SDI为传输线
│ │ 0=关闭SPI模块,释放SCK,SDO和SDI为一般I/O线
│ │ ·I2C模式:
│ │ 1=使能I2C模块,并定义SDA和SCL为传输线
│ │ 0=关闭I2C模块,释放SDA和SCL为一般I/O线
│ │ 注:当使能SPP时,这些传输线应由用户定义为正确的
│ │ 输入/输出方向,详见各相应章节。
│ └────────── 接收溢出位。
│ 1=发生接收溢出,详见具体章节介绍。
│ 0=未发生接收溢出。
└─────────────── 写操作冲突标志位
1=在传送过程中又有数据试图写入SSPBUF寄存器。
该位需由软件清零。
0=未发生写操作冲突。
SSP状态寄存器SSPSTAT
R R R R R R
─ ─ D/A P S R/W UA BF 地址:94h上电值:00h
│ │ │ │ │ │ │ │
└┬┘ │ │ │ │ │ └──── 缓冲区满
│ │ │ │ │ │ ·接收(SPI和I2C模式)
│ │ │ │ │ │ 1=接收完成,SSPBUF满
│ │ │ │ │ │ 0=接收未完成,SSPBUF空
│ │ │ │ │ │ ·发送(I2C模式)
│ │ │ │ │ │ 1=发送正在进行,SSPBUF满
│ │ │ │ │ │ 0=发送已经完成,SSPBUF空
│ │ │ │ │ └────── 地址更新(10位I2C从属模式)
│ │ │ │ │ 1=通知用户更新SSPADD中的地址
│ │ │ │ │ 0=地址尚不需更新
│ │ │ │ └───────── 读/写信息位(I2C模式),该位记录I2C
│ │ │ │ 的读/写状态。用户需用这个位来判
│ │ │ │ 断发送和接收状态。
│ │ │ │ 1=读
│ │ │ │ 0=写
│ │ │ └────────────── 起始位(I2C模式)
│ │ │ 1=I2C线上检测到起始位
│ │ │ 0=I2C线上未检测到起始位
│ │ └───────────────── 停止位(I2C模式)
│ │ 1=I2C线上检测到停止位
│ │ 0=I2C线上未检测到停止位
│ └──────────────────── 数据/地址位(I2C模式)
│ 1=最后收到的字节是数据
│ 0=最后收到的字节是地址
└──────────────────────── 未用