📄 24c02.asm
字号:
INCLUDE <P16F5X.INC>
STATUS EQU 3H
PORTB EQU 6H
PORTC EQU 7H
EEPROM EQU 08H
ADDR EQU 09H
BUFIN EQU 0AH
BUFOUT EQU 0BH
SLAVE EQU 0CH
TXBUF EQU 0DH
BIT EQU 0EH
DLY1 EQU 0FH
DLY2 EQU 10H
DI EQU 7
DO EQU 6
SDA EQU 7
SCL EQU 6
ACKF EQU 0
;**********************
ORG 7FFH
GOTO MAIN
ORG 000H
;********以下是读写子程序********
;********起始位子程序*************
;产生一个起始位,当时钟为高电平时数据线变为低电平
BSTART
BSF PORTB,SDA ;设置数据线为高电平
BSF PORTB,SCL ;设置时钟线为高电平
MOVLW B'00111111'
TRIS PORTB ;设置数据和时钟线为输出状态
NOP
NOP
NOP
NOP
NOP
NOP
BCF PORTB,SDA ;在时钟为高电平期间数据为低电平作为起始位
NOP
NOP
NOP
NOP
NOP
BCF PORTB,SCL;定时时间调整,启动时钟序列
NOP
NOP
RETLW 0
;************停止位子程序**********
;当时钟为高电平时数据线变为高电平
BSTOP
BCF PORTB,SDA ;确认数据线上为低电平
MOVLW B'00111111'
TRIS PORTB ;设置数据/时钟线为输出
BCF PORTB,SDA ;确认数据线上为低电平
NOP
NOP
NOP
BSF PORTB,SCL ;设置时钟线为高电平
NOP
NOP
NOP
BSF PORTB,SDA ;当时钟为高电平数据线变为高电平作为停止位
NOP
NOP
BCF PORTB,SCL ;重新设置时钟为低电平
NOP
NOP
RETLW 0
;********发送子程序**************
;该程序把放在BUFOUT寄存器中数据字把其发送到串行
;EEPROM器件,然后应答位再发送1个以上的时钟到EEPROM
TX
MOVLW D'8'
MOVWF BIT ;把位数设置成8位
TXLP BCF EEPROM,DO ;假设为输出是0
BTFSC TXBUF,7 ;判位输出是否确是0
BSF EEPROM,DO ;不为0,设其为1
CALL BITOUT ;若为0,把该位送串行EEPROM
RLF TXBUF ;对TXBUF循环左移
DECFSZ BIT ;8位完成否?
GOTO TXLP ;未完成,继续
CALL BITIN ;完成,读应答位
BTFSC EEPROM,DI ;检查应答位
BSF PORTC,ACKF ;若器件未把数据拉成低电平,
;接通应答失失败LED发光
RETLW 0
;****接收数据子程度*****************
;该程度从器件中读取1个字节的数据送到BUFIN寄存器
;然后送一个高电平答应,以指示不再有数据被读出.
RX
CLRF BUFIN ;清输入缓冲器
MOVLW D'8'
MOVWF BIT ;把数据数设8位
BCF STATUS,0 ;确认进位位是0
RXLP RLF BUFIN ;对BUFIN左移一位
BCF BUFIN,0 ;
CALL BITIN ;读1位
BTFSC EEPROM,DI
BSF BUFIN,0 ;若有必要,把D0置1
DECFSZ BIT ;8位完成否
GOTO RXLP ;未完成,继续
BSF EEPROM,DO ;完成,置应答位1
CALL BITOUT ;去完成发送
RETLW 0
;*该程序读取D0中的数据位,并把其发到串行该程序******
BITOUT
MOVLW B'00111111' ;设置数据/时钟线为输出
tris PORTB
BTFSS EEPROM,DO ;检查发送数据位的状态
GOTO BITLOW ;为0,转设置数据线为低电平
BSF PORTB,SDA ;为1,设置数据线为高电平
GOTO CLKOUT ;反转时钟线电平
BITLOW BCF PORTB,SDA ;输出低电平
CLKOUT BSF PORTB,SCL ;设置时钟线为高电平
NOP
NOP
NOP
NOP
BCF PORTB,SCL ;回到时钟线为低电平
RETLW 0
;**该程序从串行EEPROM器件中读出一位据,并存放在DI中********************
BITIN
BSF EEPROM,DI ;假设输入为是1
MOVLW B'10111111' ;使数据线为输入线
TRIS PORTB
BSF PORTB,SCL ;设时钟线为高电平
NOP ;保持一些时间
NOP
NOP
NOP
NOP
BTFSS PORTB,SDA ;读数据位
BCF EEPROM,DI ;输入为是0,设置相应的DI
BCF PORTB,SCL ;设置时钟线为低电平
RETLW 0
;***********************
MAIN
MOVLW B'00000000'
TRIS PORTC
CLRF PORTC
WRITE
CLRF PORTC
MOVLW B'10100000' ;设置从器件地址位和写操作模式
MOVWF SLAVE ;写入发送缓冲器
MOVLW B'01010101' ;向数据输出寄存器写入55H
MOVWF BUFOUT
CLRF ADDR ;设置起始地址为00
LOOP0 CALL BSTART ;产生一个起始位
MOVF SLAVE,0 ;读入从地址
MOVWF TXBUF ;写入发送缓冲器
CALL TX ;发送从地址
MOVF ADDR,0 ;读入字节地址
MOVWF TXBUF ;写入发送缓冲器
CALL TX ;发送字节地址
MOVF BUFOUT,0 ;读入数据字节
MOVWF TXBUF ;写入发送缓冲器
CALL TX ;发送数据字节
CALL BSTOP ;产生停止位
;**********延时子程序*********
DELAY10MS
MOVLW D'13'
MOVLW DLY1
MOVLW 0FFH
MOVWF DLY2
LP0 DECFSZ DLY2
GOTO $-1
DECFSZ DLY1
GOTO $-5
;****字节读操作程序**************
;用随机读操作读出串行EEPROM中8个地址的数据
;串行EEPROM起始地址为00
;用这种模式读操作之前为每个字节设置地址指针
;在写操作模式下通过送控制字节和需要读出单元的地址实现
READ
CLRF PORTC
MOVLW B'10100000' ;设置从地址和写操作
MOVWF SLAVE ;写入发送缓冲器
CLRF ADDR ;设置起始地址为00
LOOP1 CALL BSTART ;产生一个起始位
MOVF SLAVE,0 ;读入字地址
MOVWF TXBUF ;写入发送缓冲器
CALL TX ;发送
MOVF ADDR,0 ;读入字地址
MOVWF TXBUF ;写入发送缓冲器
CALL TX ;发送
CALL BSTART ;产生一个起始位
MOVLW B'10100001' ;设置从地址和读操作
MOVWF TXBUF ;写入发送缓冲器
CALL TX ;发送
CALL RX ;从器件读一个字节数据
CALL BSTOP ;产生停止位
NOP
NOP
NOP
NOP
NOP
NOP
MOVF BUFIN,0
MOVWF PORTC
LOOP2 NOP
GOTO $-1
;************************
END
24C02在PIC单片机系统中的应用
作者:本站 来源:本站整理 发布时间:2006-10-19 下午 09:51:34 发布人:sanplug
减小字体 增大字体
24C02在PIC单片机系统中的应用
MICROCHIP公司的PIC16系列单片机以其精简的指令和较强的端口驱动能力在各个领域得到广泛的应用。在需要储存较大数量数据的控制领域,24C02可以解决PIC16C8×系列单片机片内EEPROM不足的问题,用以保存诸如用户设置参数、采集到的数据等。
由于部分PIC单片机不具备I2C总线接口,在应用时必须用软件法加以解决。
在软件编制时应当严格遵循I2C总线规则,并注意24C02的片内读写周期时间,调整好程序流程,以避免写不进、读不出的问题。
下面将笔者在实际工作中遇到的问题和解决的方法进行简单的介绍,希望可以给同行一些帮助。
首先约定,数据由微处理器发送到24C02称“写”、“发”,反之称“读”、“收”。24C02支持顺序读写和随机读写,文中以随机读写方式为例进行介绍。
一、硬件电路(如图1所示)。
使用微处理的任意两个通用I/O端口(图中用RA2、RA3)作为与24C02的连接,其中一个作为时钟SCL线,另外一个作为数据SAD线。两个端口均接22kΩ上拉电阻。
二、软件设计
首先简要介绍一下用EEPROM的I2C总线的规则。
初始状态时,SCL、SDA两线都为高。
当SCL为高电平时,如果SDA线跌落,认为是“起始位”。
当SCL为高电平时,如果SDA线上升,认为是“停止位”。
除此之外,在发送数据的过程中当SCL为高电平时,SDA应保持稳定。
ACK应答位指在此时钟周期内由从器件(EEPROM)把SDA拉低,表示回应。这时主器件(PIC16微处理器)的SDA口的属性应该变为输入以便检测。
1.在写数据周期应该依次执行以下过程:
1)发“起始位”。2)发“写入代码”(8bit),1010(A1A2A3)0,其中的A1、A2、A3三位是片地址,由24C02的硬件决定,文中采用000。3)收“ACK”应答(1bit)。4)发EEPROM片内地址(即要写入EEPROM的什么位置)(8bit)。从00到FF中的任意一个,对应EEPROM中的相应位。5)收“ACK”应答(1bit)。6)发要发送的数据(8bit),即要存储到EEPROM中的数据。7)发“停止位”。
接下来,如图2所示,进入轮询程序以便检验24C02片内写周期是否完成。如果已经完成则进入下一个字节的写操作过程。如果没有完成则继续等待,直到完成。
2.在读数据周期,依次执行以下过程:
1)发“起始位”。2)发“写入代码”(8bit),1010(A1A2A3)0,其中A1、A2、A3三位是片地址,由24C02的硬件决定,文中采用000。3)收“ACK”应答(1bit)。4)发“EEPROM”片内地址(即要读出EEPROM的位置)(8bit)。从00到FF中的任意一个,对应EEPROM中的相应位。5)收“ACK”应答(1bit)。6)发“起始位”(1bit)。7)发“读出代码”(8bit),1010(A1A2A3)1,其中A1、A2、A3三位是片地址,由24C02的硬件接线决定,文中采用000。8)接收。9)发ACK应答。10)发“停止位”。
要特别注意的两个问题是:1)24C02有一个约10ms的片内写周期。在这个周期内,24C02是不对外界的操作作出反应的。2)在发送数据的过程中,要确保当SCL为高电平时,SDA保持稳定。
解决第一个问题的常见方法有两个,其一为采用延时等待,确保在写过程中,在一个字节完成发送了停止位之后,微处理器等待足够的时间,通常应该超过10ms,再送下一个字节,这段时间用来等待EEPROM完成片内写周期。另一个是采用轮询的方式,判断EEPROM是否完成了片内写周期。这种方式的主导思想是,当向EEPROM发送写标志后,正常情况下,EEPROM应该有ACK应答。但是当EEPROM在进行片内写周期的时候,则不会产生这样的应答。程序据此判断,EEPROM是否完成了片内的写周期程序。如果完成,则可以继续写入下一个要写的内容,否则继续等待。
第一种方法编程较为简单,但是会浪费大量的机器时间,并且程序的延时时间不好确定。第二种方法的优点在于,虽然编程较为复杂,但是较为快速,对其余的程序模块影响较少,便于完成程序的模块化设计。
对于在发送数据的过程中,要确保当SCK为高电平时,SDA必须保持稳定,应该在程序中利用软件给予保证。
如果可以很好的解决以上两个问题,数据的写入和读出是方便快捷和可靠的。
;24c02的开机计数器,系统复位一次数码管加1
;***************************************************************************
;* (程序转载请著明出处 ,未声明可适应本站腾龙/isp开发套件/倚天版开发套件 *
;* E-mail:sxj1974@163.com (51c51 test web) 51单片机学习网,自学单片机的网站 *
;* Create by :石学军
www.51c51.com
www.8951.com 更多例程请登陆网站 *
;***************************************************************************
SDA24 EQU P2.7
SCLK24 EQU P3.6
ORG 0000H
AJMP MAIN
ORG 0030H
MAIN:
CLR P3.7 ;打开写保护
MOV DPTR,#TAB
MOV A,#00H ;读地址
LCALL RD24
CJNE A,#10,TT
TT: JNC TT1
AJMP TT2
TT1: MOV A,#00
TT2: MOV 30H,A
MOVC A,@A+DPTR
CLR P2.6 ;开数码管
MOV P0,A ;送显示
MOV A,30H
INC A
MOV B,A
MOV A,#00H
LCALL WT24
AJMP $
TAB: DB 28H,7EH,0A2H,62H,74H,61H,21H,7AH,20H,60H
RD24: PUSH ACC ;读24C02子程序。
SETB SDA24
CLR SCLK24
CALL START24
MOV A,#0A0H
CALL SHIFT8
CALL ACK
POP ACC
CALL SHIFT8
CALL ACK
CALL START24
MOV A,#0A1H
CALL SHIFT8
CALL ACK
SETB SDA24
MOV R7,#8
CLR A
SETB SDA24
RD000: RL A
SETB SCLK24
MOV C,SDA24
MOV ACC.0,C
CLR SCLK24
DJNZ R7,RD000
RET
;-------------------------------
;写入24C02程序:
WT24: PUSH ACC
SETB SDA24
CLR SCLK24
CALL START24
MOV A,#0A0H
CALL SHIFT8
CALL ACK
POP ACC
CALL SHIFT8
CALL ACK
MOV A,B
CALL SHIFT8
CALL ACK
CALL STOP
CALL DELAY2
RET
; -------------------------------
;开始条件
START24:CLR SDA24
SETB SDA24
SETB SCLK24
CLR SDA24
CLR SCLK24
RET
;停止条件
STOP: CLR SDA24
SETB SCLK24
SETB SDA24
RET
;应答信号
ACK: SETB SCLK24
CLR SCLK24
RET
;读、写数据
SHIFT8: MOV R7,#8
SH01: RLC A
MOV SDA24,C
SETB SCLK24
CLR SCLK24
DJNZ R7,SH01
RET
DELAY2:
NOP
NOP
NOP
NOP
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -