24c02读写程序.docx

上传人:b****6 文档编号:6285892 上传时间:2023-01-05 格式:DOCX 页数:23 大小:100.18KB
下载 相关 举报
24c02读写程序.docx_第1页
第1页 / 共23页
24c02读写程序.docx_第2页
第2页 / 共23页
24c02读写程序.docx_第3页
第3页 / 共23页
24c02读写程序.docx_第4页
第4页 / 共23页
24c02读写程序.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

24c02读写程序.docx

《24c02读写程序.docx》由会员分享,可在线阅读,更多相关《24c02读写程序.docx(23页珍藏版)》请在冰豆网上搜索。

24c02读写程序.docx

24c02读写程序

E2PROM芯片24C02的读写程序

 

 

一、实验目的:

   给24C02的内部RAM写入一组数据,数据从24C02内部RAM的01h开始存放。

然后再把这组数据读出来,检验写入和读出是否正确。

   在这里我们给24C02中写入0、1、2的段码,然后把它读出来,送到数码管显示。

二、理论知识准备:

上面两个实验主要学习的是利用单片机的串口进行通讯,本实验要介绍的是基于I2C总线的串行通讯方法,下面我们先介绍一下I2C总线的相关理论知识。

 

(一)、I2C总线概念

I2C总线是一种双向二线制总线,它的结构简单,可靠性和抗干扰性能好。

目前很多公司都推出了基于I2C总线的外围器件,例如我们学习板上的24C02芯片,就是一个带有I2C总线接口的E2PROM存储器,具有掉电记忆的功能,方便进行数据的长期保存。

 

(二)、I2C总线结构

I2C总线结构很简单,只有两条线,包括一条数据线(SDA)和一条串行时钟线(SCL)。

具有I2C接口的器件可以通过这两根线接到总线上,进行相互之间的信息传递。

连接到总线的器件具有不同的地址,CPU根据不同的地址进行识别,从而实现对硬件系统简单灵活的控制。

一个典型的I2C总线应用系统的组成结构如下图所示(假设图中的微控制器、LCD驱动、E2PROM、ADC各器件都是具有I2C总线接口的器件):

我们知道单片机串行通讯的发送和接收一般都各用一条线TXD和RXD,而I2C总线的数据线既可以发送也可以接受,工作方式可以通过软件设置。

所以,I2C总线结构的硬件结构非常简洁。

当某器件向总线上发送信息时,它就是发送器,而当其从总线上接收信息时,又成为接收器。

 (三)、I2C总线上的数据传送

下面我们看看I2C总线是如何进行数据传送的。

我们知道,在一根数据线上传送数据时必须一位一位的进行,所以我们首先研究位传送。

1、位传输

I2C总线每传送一位数据必须有一个时钟脉冲。

被传送的数据在时钟SCL的高电平期间保持稳定,只有在SCL低电平期间才能够改变,示意图如下图所示,在标准模式下,高低电平宽度必须不小于4.7us。

那么是不是所有I2C总线中的信号都必须符合上述的有效性呢?

只有两个例外,就是开始和停止信号。

开始信号:

当SCL为高电平时,SDA发生从高到低的跳变,就定义为开始信号。

停止信号:

当SCL为高电平时,SDA发生从低到高的跳变,就定义为结束信号。

 开始和结束信号的时序图如下图所示:

2、数据传输的字节格式

SDA传送数据是以字节为单位进行的。

每个字节必须是8位,但是传输的字节数量不受限制,首先传送的是数据的最高位。

每次传送一个字节完毕,必须接收到从机发出的一个应答位,才能开始下一个字节的传输。

如果没有接受到应答位,主机则产生一个停止条件结束本次的传送。

那么从机应该发出什么信号算是产生了应答呢?

这个过程是这样的。

当主器件传送一个字节后,在第9个SCL时钟内置高SDA线,而从器件的响应信号将SDA拉低,从而给出一个应答位。

好啦,了解了I2C传输数据的格式,现在来研究双方传送的协议问题。

 3、I2C数据传输协议

I2C总线的数据传输协议如下:

(1)、主器件发出开始信号

(2)、主器件发出第一个字节,用来选通相应的从器件。

其中前7位为地址码,第8位为方向位(R/W)。

方向位为“0”表示发送,方向位为“1”表示接受。

(3)、从机产生应答信号,进入下一个传送周期,如果从器件没有给出应答信号,此时主器件产生一个结束信号使得传送结束,传送数据无效。

(4)、接下来主、从器件正式进行数据的传送,这时在I2C总线上每次传送的数据字节数不限,但每一个字节必须为8位(传送的时候先送高位,再送低位)。

当一个字节传送完毕时,再发送一个应答位(第9位),如上一条所述,这样每次传送一个字节都需要9个时钟脉冲。

数据的传送过程如下图所示:

(四)、24C02芯片相关介绍

AT24C02是带有I2C总线接口的E2PROM存储器,具有掉电记忆的功能,并且可以象普通RAM一样用程序改写。

它的容量是256个字节(00h~0ffh),有A2、A1、A0三位地址,可见I2C总线上可以连接8片AT24C02,它的寻址字节是1010A2A1A0R/W。

板上面24C02的电路连接如图所示:

我们对引脚的功能作一个简单的解释:

       VCC,GND:

电源、地引脚

        A2A1A0:

地址引脚

        SCLK、SDA:

通信引脚

        WP:

写保护引脚

从上面的电路连接知:

A2A1A0=000,可见如果要对24C02进行写操作,寻址字节是10100000;如果对24C02进行读操作,寻址字节是10100001。

用单片机的P1.6脚作为串行时钟线,用P1.7脚作串行数据线。

(五)、程序分析

        写过程:

(1)、主机首先发出开始信号

(2)、发出写24C02的寻址字节10100000,即0A0H

(3)、发数据写入24C02的地址,本例中为01H

(4)、往24C02中写入数据,这里是3个字节,分别为48h,0ebh,52h。

(5)、写完毕发出停止信号

         读过程:

(1)、主机发出start信号

(2)、发写24C02的寻址字节10100000

(大家可能要问:

我们是读数据,为什么要发写信号呢?

这是因为你首先要送出一个信号,说明从24C02中的哪个地址读取数据。

(3)、发要读取的数据在24C02中的地址,即01h

(4)、主机发start信号

(5)、发读24C02的寻址字节10100001

(5)、从24  C02中读取数据

(6)、读取完毕发出停止信号

在这个程序中,我们把开始信号,结束信号、写一个字节数据、读一个字节数据都编制成为通用的子程序,便于在程序中随时调用。

发送和接受应答位的过程放到子程序中,这样可以使得程序结构简化。

具体的程序如下所示,希望大家认真理解。

 三、实验程序

Org0000h

I2cdata  equ30h            ;发送数据缓冲区的首址

2402data equ01h            ;接受缓冲区首址

numdata equ03h           ;传送的字节数,传送3个字节

Sda bitp1.7

Scl  bitp1.6

Ajmpmain                      

Main:

  Lcallinit           ;初始化给30h,31h,32h中存入0,1,2的段码

Mainwr:

Lcallstart           ;启动

       Movr7,#0a0h

       Lcallsend            ;发送写24C02的寻址字节

       Movr7,#2402data

       Lcallsend          ;发送数据存入24C02的地址    

       Movr5,#Numdata    ;欲发送的字节数

      Movr0,#i2cdata     ;发送缓冲区的首址

wrloop:

Mova,@r0

       Movr7,a

       Incr0

       Lcallsend

       Djnzr5,wrloop      ;把3个字节的数据发送出去

       lcallstop            ;停止

       lcalld1s   

       movr5,#Numdata     ;要读取的字节数重新赋值

Mainre:

lcallstart            ;启动

       Movr7,#0a0h

       Lcallsend            ;发送写24C02的寻址字节

       Movr7,#2402data

       Lcallsend            ;发接受缓冲区首址

       Lcallstart            ;再次启动

       Movr7,#0a1h

       Lcallsend            ;发送读24C02的寻址字节

Reloop:

Lcallread            ;调用读取一个字节数据的子程序

       movp0,r7           ;把读进来的数送到p0口显示

       lcalld1s

       lcalld1s

       Djnzr5,reloop

       Lcallstop           ;3字节读取完毕发出停止信号

       Ajmp$

init:

    movp2,#0ffh         ;初始化,30h、31h、32h中存入0、1、2的段码

        mov30h,#48h        

       mov31h,#0ebh

       mov32h,#52h

       ret

start:

 setbsda            ;启动信号子程序,大家可以参考开始信号的时序图

       setbscl

       lcalld5u

       clrsda

       lcalld5u

       clrscl

       ret

stop:

 clrsda                ;停止信号子程序

       setbscl

lcalld5u

       setbsda

       lcalld5u

       clrsda

       clrscl

       ret       

;send是发送一个字节子程序

send:

movr6,#08h            

       mova,r7              ;要发送的数在r7中

sendlop1:

rlca                 ;左环移,把A的最高位移入cy

        movsda,c            ;把cy的值通过sda发送出去

        setbscl              ;在scl上产生一个时钟

        lcalld5u

        clrscl

        djnzr6,sendlop1       ;重复8次,发送一个字节

 ;cack是检查应答信号的子程序

cack:

 setbsda               ;主机首先拉高sda

       setbscl                ;发出一个时钟

       lcalld5u

sendlop2:

movc,sda              ;读入sda的状态,如果是0表示接受到了应答

   jcsendlop2         

    clrscl                ;接受到应答位,结束时钟

    ret      

read:

    movr6,#08h             ;读取一个字节子程序

readlop1:

 setbsda                ;置sda为输入方式

        setbscl                  ;发出一个时钟 

        lcalld5u

        movc,sda              ;读入sda状态

        rlca                   ;把该位的状态移入A中 

        clrscl                 ;结束时钟

        djnzr6,readlop1         ;重复8次,读入一个字节

        movr7,a                ;读进来的数放在r7中 

;sack是发送应答位子程序

sack:

  clrsda                 ;拉低sda线

        setbscl                ;发出时钟信号

        lcalld5u

        clrscl

        setbsda

        ret

d5u:

    nop                 ;延时5us子程序

        nop

        nop

        nop

        nop

        ret

d1s:

    movr1,#100        ;延时1s子程序

del1:

   movr4,#20

del2:

   movr3,#0ffh  

del3:

   djnzr3,del3

        djnzr4,del2

        djnzr1,del1

        ret

        end

 

大家把这个程序下载到测试板上面,发现数码管依次显示数字0、1、2

 

;简洁的24C02读写汇编程序 

;--------------------------------------------

   I2C_SDA         EQUP1.6  ;PIN5

   I2C_SCL         EQUP1.7  ;PIN6

 

;=============================================

I2C_WRITE:

 ; WRITE8BYTESTOEEROM;INPUT:

A-A*8=EEROMSTARTADDR 

           ;                                 R0-RANSTARTADDR

           ;                           USE:

C,A,R0,R6,R7

 

     ACALLI2C_START

     ACALLOUT

     MOVR6,#8

WR_LP:

MOVA,@R0

     ACALLOUT

     INCR0

     DJNZR6,WR_LP

     AJMPI2C_STOP  

 

;==========================================

I2C_READ:

  ; READ8BYTESFROMEEROM

;INPUT:

A-A*8=EEROMSTARTADDR 

           ;    R0-RANSTARTADDR

           ;      USE:

C,A,R0,R6,R7

      

     ACALLI2C_START

     ACALLOUT

     MOVR6,#8

     MOVA,#0A1H;#RDCMD

     ACALLOUTS

BRDLP:

         MOVR7,#8

         SETBI2C_SDA

INLP:

    CLR I2C_SCL

         ACALLDELAY6

         SETB I2C_SCL

         NOP

         MOVC,I2C_SDA

         RLCA

         DJNZR7,INLP

         CLR  I2C_SCL

         MOV@R0,A

         INCR0

  DJNZR6,ACKLP

;;;;----------------------------

I2C_STOP:

         CLRI2C_SDA

         ACALLDELAY5

         SETBI2C_SCL

         ACALLDELAY5

         SETBI2C_SDA

DELAY6:

         NOP

DELAY5:

         NOP

         RET

;;-----------------------------

I2C_START:

     SWAPA

     RRA

     MOVR6,A

     MOVA,#0A0H;#WTCMD

     ACALLOUTS

     MOVA,R6

     RET

;-------------------------------                  

ACKLP:

     CLRI2C_SDA 

     SETBI2C_SCL

     ACALLDELAY5

     CLRI2C_SCL

     AJMPBRDLP

;=======================

OUTS:

     SETBI2C_SDA  

     SETBI2C_SCL 

     ACALLDELAY5 

     CLRI2C_SDA  

     ACALLDELAY5 

     CLRI2C_SCL  

;========================

OUT:

     SETBC

     MOVR7,#9

OTLP:

RLCA

     NOP

     MOVI2C_SDA,C

     NOP

     NOP

     SETBI2C_SCL

     ACALLDELAY5

     CLR I2C_SCL

     DJNZR7,OTLP

     RET

;========================

END

 

;SDAEQUP1.6;(你可以根据你的情况变更引脚)

;SCLEQUP1.7

;D15US,D1MS子程序分别为15uS和1mS延时程序,请根据你的晶体自行编写。

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

;24C01写初始.(传递的数据在R7中).

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

sdabitp1.7

sclbitp1.6

org0000

ajmpstar

org00040

star:

movp3,#00H

mov30H,#01H

mov31h,#88h

nop

nop

nop

acallat2401w

nop

nop

nop

nop

nop

ajmp$

AT2401W:

MOVP1,#0FFH;置SDA/SCL=1

LCALLR2STAR;写开始状态字

MOVR7,#10100000B;SET2401=写

LCALLR2SEND;送

MOVACC,30H;30H指向2401数据的起始地址

MOVR7,ACC;将要写2401的起始地址送到R7

LCALLR2SEND

MOVACC,31H;取第一个号

MOVR7,ACC;数据传递到R7

LCALLR2SEND;写具体号码

LCALLR2STOP;停止

LCALLD1MS;等待一定时间使24C01内部写完成

RET

;------------------------------------------

;写到2401本程序开始及结束SDA&SCL均=0,发送数据在R7

;------------------------------------------

R2SEND:

PUSHACC;保存ACC

MOVACC,R7;将R7中的数发送出去

MOVR6,#08H;往2401发送数据

R2SLOP1:

RLCA;将ACC中的数据移到数据线上

MOVSDA,C;送出数据

LCALLD15US

SETBSCL;发送串行时钟进行写操作

LCALLD15US

CLRSCL

DJNZR6,R2SLOP1;串行发送8BIT

SETBSDA;准备接收ACK

LCALLD15US

SETBSCL;接收ACK的时钟

LCALLD15US

R2SLOP2:

MOVC,SDA;写完后等待确认信号ACK

JCR2SLOP2

CLRSCL;为下一步其它操作做准备

CLRSDA

POPACC;还原ACC

LCALLD1MS;等待内部写完

RET

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

;2401读初始.

;------------------------------------------------------------------

AT2401RC:

LCALLR2STAR;写状态字

MOVR7,#10100000B;SET2401=WRI

LCALLR2SEND;送出状态字

MOVA,30H;上程序传来的读取地址

MOVR7,A;地址数据送R7

LCALLR2SEND;送出数据

MOVP1,#11111111B;保证SDA/SCL起始=1

LCALLR2STAR

MOVR7,#10100001B;0A1H;读状态

LCALLR2SEND

LCALLR2READ;读所需的数

LCALLR2STOP

RET

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

;设置开始,初始SDA&SCL=1,结束SDA&SCL=0

;--------------------------------------------------------------

R2STAR:

LCALLD15US;对2401操作开始

CLRSDA;在SCL=1时,SDA由1变为0表示开始

LCALLD15US

CLRSCL

LCALL

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1