返回主页 单片机教程XL2000开发板 单片机学习 自制编程器 单片机资料 软件下载 电子技术产品介绍如何购买 进入论坛

作品1:征文-我是怎样开始学习电子的 山西省大同市作品6:多功能自行车测速仪  北京大学      崔健
作品2:数字温度计的设计  杭州电子科技大学     陈智杰作品7:带闹钟智能电子钟 深圳市天安数码城      谢玉平 
作品3:如何使自制的单片机电子钟走时精准      舒新生作品8:电话回拨服务告知装置 武汉市桥口区     詹显德
作品4:宽带数控放大器 陕西省西安通信学院     韩宏伟作品9:单片机应用之摩斯密码电子锁广东省顺德      吴志光
作品5:一些事,一些情  韶关市     冯敬锋作品10:基于aduc842瞬态波形存储器 华中师范大学物理学院     杨程泽
作品11:基于AT89S52单片机的毫欧表电路设计中南林业科技大学涉外学院    郭海

作品1:字符型液晶显示模块       邓杰   作品6:基于89C51的智能转速计   淮安信息学院     宋炎
作品2:8X8LED点阵屏循环显示作品7:用虚拟IIC总线实现24C02的应用  南阳理工学院     张全领
作品3:虚拟仿真仪器UMPS的应用      牛余朋作品8:语音编程、远程控制试验板    社区乞丐
作品4:万年历数字钟及可调时钟系统作品9:定时开关控制器的制作     魏军丞
作品5:点矩阵显示器的应用 会员lfgbody    林发根作品10:AD080951单片机中的应用    /黄海

用虚拟IIC总线实现串行EEPROM  24C02 在单片机中的应用

                  南阳理工学院电子系张全领

1、引言

本文是介绍串行E2 PROM 24C02 与单片机的连接, 给出了接口电路及具体应用程序,含有有键盘程序、动态显示程序。

2串行E2 PROM 24C02的硬件连接 如图1 所示,24C02 与单片机AT89S52的连接采用的是I2C 总线( Inter IC Bus) I2C 总线是串行数据线SDA 与时钟线SCL 构成, 所有的控制命令和数据均通过这两条线传输。单片机AT89S52 作为主器件,它在I2C 总线上产生时钟脉冲、寻址信号、起停信号; 24C02 作为从器件,它通过串行数据线SDA 与时钟线SCL 与单片机AT89S52的引脚P3.6 P3.7 相连。24C02 提供2k 位串行E2 PROM , 内部组态为256 ×8 位。A0A1A2 为芯片的地址线,在使用中把这三条线接地。WP 为低电平时,允许写操作。AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器,与工业80C51产品指令各引脚完全兼容。

            图1

2. 1   总线的操作时序如图2 所示, SCL SDA 两总线平时通过上拉电阻为高电平, SDA 为数据线,SCL为时钟线。

2

 

摘要: 本文介绍的是串行E2 PROM 与单片机AT89S52 的硬件连接, 阐述了AT89S52 24C02 的读写操作时序、操作方法,最后给出了一个完整的应用程序。

 

关键词: I2C 总线    串行E2 PROM

 

SCL 低电平时间周期内可能改变。SCL 高电平周期期间数据改变表示“开始”或“停止”两种状态: SCL 处于高电平时,DSA 由高电平转向低电平表示“开始”, 由低电平转向高电平表示“停止”状态。其中“开始”状态必须在其它操作之前执行, 而“停止”状态则终止所有操作。除以上两个状态,24C02 与外界的通讯还需另一个状态, 即确认状态ACK , 该确认是在每个字节之后第九个时钟周期发生,在后面的读、写过程将予以介绍。

2.2 24C02 数据写操作

写操作时序如图3 所示。在写操作中,主器件发送完写控制字节10100000 , 等接收到24C02 通过SDA 发出确认信号ACK , 主器件接着随时钟输入8 位地址码(00 -0FFH) , 收到24C02 再次发出确认信号ACK ,才发送待写入的数据。最后,主设备必须用停止状态来终止写操作。在写控制字节中高四位被指定为1010 , 芯片地址为A2A1A0 000 ,R/ W =0

2. 3 24C02 数据读操作读操作时序如图4 所示。若是读当前地址内容,主器件发送完读控制字节10100001 ,并收到ACK信号后, 即可一位位地读出该单元内容; 若要读随意地址内容, 由主器件先发送写控制字节10100000 , 然后发送待读的E2 PROM 单元地址(00 - 0FFH) , 收到ACK信号后由主器件再次产生起始条件,接着发送读控制字节, 收到ACK信号后, 即可读出该单元内容。最后,数据的读取不通过确认应答,而是通过产生一个停止状态来应答。

 

3、说明

   我正在学习单片机,在学习过程中认为键盘、显示、数据存储等,这些基本模块非常重要。我也写过键盘程序、动态显示程序、还有串行E2 PROM 24C02的一些相关程序。本次只是把三个模块稍加综合。在初始状态下,实现8位数码管全部为0,按键是4*4键盘,其中含有存储、取出显示、清除三个功能键,( 其它键本来是表示0-C ,但是由于我的实验板是74LS48做译码 ,无法正常显示字母,我在程序中把它们全改成了0——9的数字。)由低位到高位移动显示,即按下第一次键显示的数,到第二次有键按下时,会被挤到第二位显示,依次类推,如果第九次按键,就会把第一次键值挤出,因为只能显示八位。串行E2 PROM 24C02的程序,我在学习中感觉比键盘、显示子程序有点难度,所以基本上都带有详细的注释及说明。

以下,说一下图5(仿真图),其实它与原理图没有太大区别,就是省去了晶振、复位及一些驱动放大电路,我想这对每个单片机爱好者来说,没有太大问题。如果哪位读者对原理图感兴趣的话,可以给我留言,我可以用Protel作图再发过去。由于本人也是穷学生一个。根本没有数码相机这样高消费的东西,没有办法把实物照片发过,希望石大哥见谅!

另外,我也是一名单片机初学者,因此能力有限。希望与大家共同学习提高。虽然本人呕心沥血(夸张一点)使程序可以实现应有功能。不过,也是无法满足大侠的需要,里面一定会有很多不足之处,希望读者批评指正。

 

参考文献:《单片机外围器件手册——存储器分册》

 

5

 

 

 

附源程序:

/*********************************************************************

 *     本程序是练习键盘、显示及串行IIC的程序                         *

 *     以12M晶振为例                                                 *

 *     谨适合初学者                                                  *

 *     作者:张全领                                                  *

 ********************************************************************/

SDA    EQU    P3.7

SCL    EQU    P3.6

SLAW   EQU    0A0H       ;WRITE的外围地址  

SLAR   EQU    0A1H       ;READ的外围地址

NUMBYT EQU    8          ;字节个数

       ORG    0000H

       LJMP   MAIN

       ORG    000BH      ;采用定时器0中断 

       SJMP   ITIME0

       ORG    0040H

ITIME0:MOV   TH0,#LOW(65536-40000)      ;重赋初值

       MOV   TL0,#HIGH(65536-40000)

       MOV   P0,40H

       ORL   P0,#70H                    ;使第一位显示

       CALL  T1MS                       ;延时

       MOV   P0,41H

       ORL   P0,#60H

       CALL  T1MS

       MOV   P0,42H

       ORL   P0,#50H

       CALL  T1MS 

       MOV   P0,43H

       ORL   P0,#40H

       CALL  T1MS  

       MOV   P0,44H

       ORL   P0,#30H

       CALL  T1MS

       MOV   P0,45H

       ORL   P0,#20H

       CALL  T1MS

       MOV   P0,46H

       ORL   P0,#10H

       CALL  T1MS

       MOV   P0,47H

       ORL   P0,#00H

       CALL  T1MS

       RETI 

T1MS:  MOV  R5,0FFH             ;延时程序

       DJNZ R5,$

       RET      

MAIN:

    MOV   SP,#60H

    MOV   P2,#0FFH

    MOV   R0,#40H

    MOV   R2,#08H

CLEAR:                          ;清除显示区内容

    MOV   @R0,#00H

    INC   R0

    DJNZ  R2,CLEAR

    MOV   TMOD,#01H             ;定时器0,工作方1

    MOV   TH0,#HIGH(65536-40000);赋初值

    MOV   TL0,#LOW(65536-40000)

    SETB  EA

    SETB  ET0

    SETB  TR0

LOOP:                           ;调用键盘程序

    CALL  KEY

    SJMP  LOOP

KEY:

    ACALL KS1                   ;判断键是否按下

    JNZ   LK1                   ;有键按下(A不等于0)转到LK1,消抖动延时

    AJMP  KEY                   ;无键按下返回

LK1:ACALL T12MS                 ;调用12MS延时

    ACALL KS1                   ;有无键按下,若有则为确实有键盘按下                 

    JNZ   LK2                   ;键按下转列扫描

    AJMP  KEY                   ;不是键按下返回

LK2:MOV  R2,#0EFH               ;全扫描字11101111放入R2

    MOV  R4,#00H                ;首列号

LK4:MOV  P2,R2                  ;全扫描字送P2口               

    MOV  A,P2

    JB   ACC.0,LONE             ;判断第0行无键按下,转第一行,ACC.0=0为有键按下

    MOV  A,#00H                 ;第0行首列号

    AJMP LKP                    ;转求键号

LONE:

    JB   ACC.1,LTWO

    MOV  A,#04H

    AJMP LKP

LTWO:

    JB   ACC.2,LTHR

    MOV  A,#08H

    AJMP LKP

LTHR:

    JB   ACC.3,NEXT

    MOV  A,#12

LKP:ADD  A,R4                   ;R4列号  键号=行号+列号

    PUSH ACC                    ;键号进堆栈保护

LK3:ACALL T12MS               

    ACALL KS1                   ;判断是否释放

    JNZ   LK3                   ;未释放等待

    POP  ACC                    ;释放,出栈键号入A

    MOV  DPTR ,#TABLE           ;首地址放入DPTR

    MOV  B,#3

    MUL  AB

    JMP  @A+DPTR                ;散转

TTR:RET

NEXT:

    INC  R4                     ;列号加1

    MOV  A,R2                  

    JNB ACC.7,KND               ;四列扫描完,返回

    RL   A                      ;未完,左移一位

    MOV  R2,A                   ;放入R2

    AJMP LK4                    ;重新进入逐行判断

KND:AJMP KEY                   ;重新调用键盘程序

KS1:MOV  P2,#0FH               ;判断键是否按下

    MOV  A, P2

    CPL  A

    ANL  A,#0FH

    RET         

TABLE:

    LJMP   KEY0

    LJMP   KEY1

    LJMP   KEY2

    LJMP   KEY3

    LJMP   KEY4

    LJMP   KEY5

    LJMP   KEY6

    LJMP   KEY7

    LJMP   KEY8

    LJMP   KEY9

    LJMP   KEYA

    LJMP   KEYB

    LJMP   KEYC

    LJMP   KEYD

    LJMP   KEYE

    LJMP   KEYF

 

KEY0:

      MOV  A,#00H

      SJMP LEDA   

KEY1: MOV  A,#01H

      SJMP LEDA

KEY2: MOV  A,#02H

      SJMP LEDA

KEY3: MOV  A,#03H

      SJMP LEDA

KEY4: MOV  A,#04H

      SJMP LEDA

KEY5: MOV  A,#05H

      SJMP LEDA         

KEY6: MOV  A,#06H

      SJMP LEDA

KEY7: MOV  A,#07H

      SJMP LEDA   

KEY8: MOV  A,#08H

      SJMP LEDA

KEY9: MOV  A,#09H

      SJMP LEDA

KEYA: MOV  A,#01H

      SJMP LEDA

KEYB: MOV  A,#02H

      SJMP LEDA       

KEYC: MOV  A,#03H

      SJMP LEDA

KEYD: ;MOV  A,#04H

      LJMP QING24

KEYE: ;MOV  A,#05H

      LJMP READ24

KEYF: ;MOV  A,#06H

      LJMP WRITE24

LEDA: CLR    ET0

      XCH    A,40H

      XCH    A,41H

      XCH    A,42H

      XCH    A,43H

      XCH    A,44H

      XCH    A,45H

      XCH    A,46H

      XCH    A,47H      

      SETB   ET0

      LJMP   TTR

T12MS:                   ;延时12MS子程序

    MOV  R7,#18H

TM: MOV  R6,#0FFH

TM6:DJNZ R6,$

    DJNZ R7,TM

    RET

;存储  写进24的程序

WRITE24:

      MOV    R5,#0

      MOV    R1,#40H

      CLR    ET0

      LCALL   SEND_NBYTE

      SETB   ET0

      LJMP   TTR

;取出  读24内容

READ24:

      MOV    R5,#0

      MOV    R1,#40H

      CLR    ET0

      LCALL   READ_NBYT

      SETB   ET0

      LJMP   TTR

;清24的内容

QING24:

      MOV    R5,#0

      MOV    50H,#00H

      MOV    R1,#50H

      CLR    ET0

      LCALL   SEND_CLR

      SETB   ET0

      LJMP   TTR

 

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

;发送n字节程序:SEND_NBYTE

;发送的字节个数放入R3中,24c02器件内地址在R5中;发送缓冲区首址在r1中

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

SEND_NBYTE:

       MOV  R3,#NUMBYT

       LCALL STA

       MOV   A,#SLAW  ;发送外围器件地址

       LCALL SEND

       LCALL CACK

       JB    F0, SEND_NBYTE

       MOV   A,R5     ;从器件内地址

       LCALL SEND

       LCALL CACK

       JB    F0,SEND_NBYTE

WRDA:  MOV   A,@R1    ;主发送缓冲区首址在R1中

       LCALL SEND

       LCALL CACK

       JB    F0,SEND_NBYTE

       INC   R1

       DJNZ  R3,WRDA

       LCALL  STP

       RET     

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

;接收n字节程序:READ_NBYTE

;发送的字节个数放入R3中,24c02器件内地址在R5中;接收缓冲区首址在r1中

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

READ_NBYT:

       MOV   R3,#NUMBYT

       LCALL STA    

       MOV   A,#SLAW   ;发送外围器件地址(w) 

       LCALL SEND

       LCALL CACK

       JB    F0,READ_NBYT

       MOV   A,R5       ;从器件内地址

       LCALL SEND

       LCALL CACK

       JB    F0,READ_NBYT

       LCALL STA       ;从新起始信号

       MOV   A,#SLAR   ;发送外围器件地址(r)  

       LCALL SEND

       LCALL CACK

       JB    F0,READ_NBYT

RDN1:  LCALL READ

       MOV   @R1,A    ;主接收缓冲区首址

       DJNZ  R3,ACK

       LCALL STP

       RET

ACK:   LCALL  MACK

       INC    R1

       SJMP   RDN1

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

;发送n字节清0程序:SEND_CLR

;发送的字节个数放入R3中,24c02器件内地址在R5中;发送缓冲区首址在r1中

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

SEND_CLR:

       MOV  R3,#NUMBYT

       LCALL STA

       MOV   A,#SLAW ;发送外围器件地址

       LCALL SEND

       LCALL CACK

       JB    F0, SEND_CLR

       MOV   A,R5     ;从器件内地址

       LCALL SEND

       LCALL CACK

       JB    F0,SEND_CLR

WRDA1:  MOV   A,@R1    ;主发送缓冲区首址在R1中

       LCALL SEND

       LCALL CACK

       JB    F0,SEND_CLR

       DJNZ  R3,WRDA1

       LCALL  STP

       RET     

      

;send one byte**R2*****************************************************

;发送的字节字长在R2中

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

SEND:

      MOV    R2,#08H      ;8BIT

SEND3:RLC    A

      JC     SEND1

      SJMP   SEND0

WLP1: DJNZ   R2,SEND3

      RET

SEND1:SETB   SDA         ;SEND"1"

      SETB   SCL

      NOP

      NOP

      NOP

      NOP

      CLR    SCL

      CLR    SDA

      SJMP   WLP1

SEND0:CLR    SDA      ;SEND"0"

      SETB   SCL

      NOP

      NOP

      NOP

      NOP

      CLR   SCL

      SETB   SDA

      SJMP  WLP1

;READ ONE  BYTE****R2,R4,C********************************************

;接收的字节字长在R2中,接受的字节放入R4

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

READ:

      MOV   R2,#08H

RLP:  SETB  SDA

      SETB  SCL

      MOV   C,SDA

      MOV   A,R4

      RLC   A

      MOV   R4,A

      CLR  SCL

      DJNZ R2,RLP

      RET 

;应答位检查CACK*******************************************************

CACK:

     SETB  SDA    ;置输入方式

     SETB  SCL    ;使SDA上数据有效

     CLR    F0

     MOV   C,SDA

     JNC   CEND

     SETB  F0     ;无应答

CEND:CLR  SCL

     RET

;***START*************************************************************

STA:

    SETB SDA       ;发送起始条件的数据信号

    SETB SCL          ;发送起始条件的时钟信号

    NOP

    NOP

    NOP

    NOP

    CLR  SDA

    NOP

    NOP

    NOP

    NOP

    CLR  SCL  ;钳住I2C总线准备发送或接受数据

    RET

;***STOP**************************************************************

STP:

    CLR  SDA      ;发送停止条件的数据信号 

    SETB SCL       ;发送停止条件的时钟信号

    NOP

    NOP

    NOP

    NOP

    SETB SDA     ;发送I2C总线停止信号

    NOP

    NOP

    NOP

    NOP

    CLR  SDA

    CLR  SCL

    RET

;***MACK***"0"*********************************************************

MACK:

    CLR  SDA

    SETB SCL

    NOP

    NOP

    NOP

    NOP

    CLR  SCL

    SETB SDA

    RET

;**NMACK*"1"***********************************************************   

NMACK: 

    SETB SDA

    SETB SCL

    NOP

    NOP

    NOP

    NOP

    CLR  SCL

    CLR  SDA

    RET

  

    END