单片机模拟IIC时序读写24C02

2019-04-15 12:42发布

一、什么是IIC总线
IIC即集成电路总线,也是一种非常常用的总线是由飞利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路(ICS) ,IIC是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实时数据传输的控制源。
注意:IIC芯片在工业上的应用也是非常重要的,与串口、SPI、CAN等总线齐名。
二、IIC总线协议简介
IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。同时为了保证数据可靠地传送,任一时刻总线只能由某一台主机控制。
在I2C总线传输过程中,将两种特定的情况定义为开始和停止条件:当SCL保持"高"时,SDA由"高"变为"低"为开始条件;当SCL保持"高"且SDA由"低"变为"高"时为停止条件。开始和停止条件均由主控制器产生。使用硬件接口可以很容易地检测到开始和停止条件,没有这种接口的微机必须以每时钟周期至少两次对SDA取样,以检测这种变化。且SDA线上的数据在时钟"高"期间必须是稳定的,只有当SCL线上的时钟信号为低时,数据线上的"高"或"低"状态才可以改变。输出到SDA线上的每个字节必须是8位,每次传输的字节不受限制,但每个字节必须要有一个应答ACK。如果一接收器件在完成其他功能(如一内部中断)前不能接收另一数据的完整字节时,它可以保持时钟线SCL为低,以促使发送器进入等待状态;当接收器准备好接受数据的其它字节并释放时钟SCL后,数据传输继续进行。

IIC数据传输格式如下:


三、24C02芯片介绍
24C02串行E2PROM是基于IIC总线的存储器件,遵循二线制协议,由于其具有接口方便,体积小,数据掉电不丢失等特点,在仪器仪表及工业自动化控制中得到大量的应用。24C02在电路的作用主要是在掉电的情况下保存数据,具体参数不进行详细论述。详细资料请参考24C02的datasheet。
相关控制需要的时序参数如下:









四、协议时序详解
void start(void)
{
 sda=1;
 delay();
 scl=1;
 delay();
 sda=0;
 delay();
}


void stop(void)
{
 sda=0;
 delay();
 scl=1;
 delay();
 sda=1;
 delay(); 
}


void ack(void)
{
 uchar i;
 scl=1;
 delay();
 while((sda==1)&&(i<200))i++;
 scl=0;
 delay();
}


void noack(void)
{
 sda=1;
 delay();
 scl=1;
 delay();
 scl=0;
 delay();
}

void write_byte(uchar add,uchar dat)
{
 init();
 start();
 iicwr_byte(0xa0);
 ack();
 iicwr_byte(add);
 ack();
 iicwr_byte(dat);
 ack();
 stop(); 
}


uchar read_byte(uchar add)
{
 uchar a;
 init();
 start();
 iicwr_byte(0xa0);
 ack();
 iicwr_byte(add);
 ack();
 start();
 iicwr_byte(0xa1);
 ack();
 a=iicre_byte();
 noack();
 stop();
 return a; 
}
五、硬件电路设计


六、软件程序设计
设计程序,系统每开关机一次,记录一次并用数码管显示 #include #include #define uchar unsigned char #define uint unsigned int sbit sda=P1^1; sbit scl=P1^0; unsigned char code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; void iic_init(void); void start(void); void stop(void); void ack(void); void noack(void); void iicwr_byte(uchar dat); uchar iicre_byte(void); void delay (void); void init(void); void delay1(void); void write_byte(uchar add,uchar dat); uchar read_byte(uchar add); /////////////////////////////////// void delay1(void) { uint a=30000; while(a--); } void delay (void) { _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); } void start(void) { sda=1; delay(); scl=1; delay(); sda=0; delay(); } void stop(void) { sda=0; delay(); scl=1; delay(); sda=1; delay(); } void ack(void) { uchar i; scl=1; delay(); while((sda==1)&&(i<200))i++; scl=0; delay(); } void noack(void) { sda=1; delay(); scl=1; delay(); scl=0; delay(); } void iic_init(void) { sda=1; scl=1; } void iicwr_byte(uchar dat) { uchar i; scl=0; for(i=0;i<8;i++) { if(dat&0x80) { sda=1; } else { sda=0; } dat=dat<<1; delay(); scl=1; delay(); scl=0; delay(); } sda=1; delay(); } uchar iicre_byte(void) { uchar i; uchar dat; scl=0; delay(); sda=1; delay(); for(i=0;i<8;i++) { scl=1; delay(); dat=dat<<1; if(sda) { dat++;// } scl=0; delay(); } return dat; } void main() { uchar k; iic_init(); k=read_byte(0x11); k=k%10; P1=smg_du[k]; //测试用,静态显示几个算啦 k++; write_byte(0x11,k); while(1); } void write_byte(uchar add,uchar dat) { iic_init(); start(); iicwr_byte(0xa0); ack(); iicwr_byte(add); ack(); iicwr_byte(dat); ack(); stop(); } uchar read_byte(uchar add) { uchar a; iic_init(); start(); iicwr_byte(0xa0); ack(); iicwr_byte(add); ack(); start(); iicwr_byte(0xa1); ack(); a=iicre_byte(); noack(); stop(); return a; }
注意:并不是所有的24系列的存储芯片都适用本程序的读写流程,有些芯片有部分不同,如24C64就分高低地址,要根据实际应用的芯片参考相关的芯片数据手册,查看访问流程。