×
单片机 > 单片机程序设计 > 详情

24c08 I2C总线协议操作程序汇编和C语言2个版本详解

发布时间:2021-05-25 发布时间:
|


;24c08操作时序为:起始信号sclk拉高情况下sda由高变低,表示起始

; 结束信号sclk拉高情况下sda由低变高,表示结束

; 字节由高位向低位依次发送

; 第一个字节是地址和读写控制,第二个是存储地址,第三个是数据,每个数据结束器件都会发送 ack应答信号;

; I2C 总线协议

;I2C 总线协议定义如下

;1 只有在总线空闲时才允许启动数据传送

;2 在数据传送过程中当时钟线为高电平时数据线必须保持稳定状态不允许有跳变时钟线

;为高电平时数据线的任何电平变化将被看作总线的起始或停止信号

;起始信号

;时钟线保持高电平期间数据线电平从高到低的跳变作为I2C 总线的起始信号

;停止信号

;时钟线保持高电平期间数据线电平从低到高的跳变作为I2C 总线的停止信号

;

ORG 0000H

SCL EQU P2.6

SDA EQU P2.7

AJMP MAIN

ORG 00030H

MAIN:LCALL INIT ;主函数,

LCALL WRITE2408

LCALL DELAY1

LCALL READ2408

MOV P0,A

AJMP $


INIT: SETB SCL ;初始化

LCALL DELAY

SETB SDA

LCALL DELAY

RET


START:SETB SDA ;起始信号

LCALL DELAY

SETB SCL

LCALL DELAY

CLR SDA

LCALL DELAY

RET

STOP:CLR SDA ; 停止信号

LCALL DELAY

SETB SCL

LCALL DELAY

SETB SDA

RET

ACK:SETB SCL ;应答信号

LCALL DELAY

JB SDA,$

CLR SCL

LCALL DELAY

SETB SDA

LCALL DELAY

RET

WRITE: MOV R4,#08H ;写

LOOP: CLR SCL

LCALL DELAY

RLC A

MOV SDA,C

LCALL DELAY

SETB SCL

LCALL DELAY

DJNZ R4,LOOP

CLR SCL ;哎呀吃大亏了,我说怎么就是写一个A0算完了而且还有一个停止信号,娘了个逼我程序里不是这样的啊,奥今天我才看透,原来A0的最低位是0

LCALL DELAY ;这里以前是先把SDA释放,再拉低SCL ,相当于一个停止信号啊,所以U820受到后把总线禁止了,也难怪写不出了,哈哈哈又学一招

SETB SDA ;原来这么细微的变动都会是你的程序白搭,即使你其他的都是对的;

LCALL DELAY ;加油;2010年7月22日午与天津宿舍

RET ;EEPROM的成功读取时很有意义的,嘿嘿


READ:MOV R4,#08H ;读

SETB SDA

LCALL DELAY

LOP: CLR SCL

LCALL DELAY

SETB SCL

LCALL DELAY

MOV C,SDA

RLC A

DJNZ R4,LOP

CLR SCL

RET

DELAY: ;数据稳定

NOP

NOP

NOP

NOP

NOP

RET


WRITE2408:LCALL START

MOV A,#0A0H

LCALL WRITE

LCALL ACK ;向U820的00H单元写0x88;

MOV A,#00H

LCALL WRITE

LCALL ACK

MOV A,#88H

LCALL WRITE

LCALL ACK

LCALL STOP

RET

READ2408:LCALL START

MOV A,#0A0H

LCALL WRITE

LCALL ACK

MOV A,#00H ;从U820的00H单元读出数据

LCALL WRITE

LCALL ACK

LCALL START

MOV A,#0A1H

LCALL WRITE

LCALL ACK

LCALL READ

LCALL STOP

RET

DELAY1: ;延时1S,在应用中这个可以是主程序啊哈哈,真他妈了噶比的爽老子也做出来了;爽啊

MOV R7,#0A7H

DL1:

MOV R6,#0ABH

DL0:

MOV R5,#10H

DJNZ R5,$

DJNZ R6,DL0

DJNZ R7,DL1

NOP

RET

END



#include

#define uchar unsigned char

sbit sda=P2^7;

sbit scl=P2^6;


void delay1(uchar z)

{

uchar j,k;

for(k=0;k

{

for(j=0;j<100;j++) ; //此处j不得小于27否则读不出数据

}

}

void delay()

{


;;

}

void init()

{

sda=1;

delay();

scl=1;

delay();

}

void start()

{

sda=1;

delay();

scl=1;

delay();

sda=0;

delay();

}

void stop()

{

sda=0;

delay();

scl=1;

delay();

sda=1;

delay();


}

void ack()

{

scl=1;

delay();

if(sda==1)

{ delay1(1000);


}

scl=0;

delay();

sda=1;

delay();

}

void write_24c08(uchar add)

{

uchar a,i;

i=add;

scl=0;

delay();

for(a=0;a<8;a++)

{

i=i<<1;

sda=CY;

delay();

scl=1;

delay();

scl=0;

delay();

}

scl=0;

delay();

sda=1;

delay();

}

uchar read_24c08()

{

uchar a,readdate;

scl=0;

delay();

sda=1;

delay();

for(a=0;a<8;a++)

{


scl=1;

delay();

readdate=(readdate<<1)|sda; //这里注意啊,不要换成别的

scl=0;

delay();


}

return readdate;

}



void main()

{

init();

start();

write_24c08(0 );

ack();

write_24c08(0x21);

ack();

write_24c08(0xf0);

ack();

stop();


delay1(100);

start();

write_24c08(0 );

ack();

write_24c08(0x21);

ack();

start();

write_24c08(0xa1);

ack();

P0=read_24c08();

stop();

while(1);

}



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
AVR熔丝位操作时的要点和需要注意的相关事项