C51—模拟IIC总线实现EEPROM存取数据

本文介绍了如何使用51单片机模拟IIC总线与EEPROM(以AT24C02为例)进行数据的存取。讲解了IIC总线的原理,包括通信格式、启始和停止信号、寻址信号以及应答信号。此外,还详细阐述了EEPROM的工作原理和在单片机中的应用,以及实现IIC通信的关键函数和模块化设计。

- 什么是IIC总线

IIC总线是同步通信的一种特殊形式,具有接线口少、控制简单、器件封装形式小、通信速率高等特点。在主从通信中,可以有多个IIC总线器件同时连接到IIC总线上,所有与IIC兼容的器件都具有标准的接口,通过地址来识别通信对象,使他们可以经由IIC总线互相直接通信。
IIC总线由SDA数据线和SCL时钟线俩条线构成通信线路,既可发送数据也可以接收数据。在CPU和IC之间、IC与IC间都可以双向传播,每个器件都有唯一的地址,这样就可以使信息进行准确的传输。CPU发出的信号分为地址码和数据码俩部分,地址码用来选址,数据码是通信的内容。
总而言之,IIC总线就是器件之间的通信线路,主器件可以通过IIC总线向从器件发送数据,也可以从从器件接收数据。51单片机不具备IIC总线接口,但我们可以通过软件模拟IIC总线的工作时序,只需要正确调用各个函数就能够方便的拓展IIC总线接口器件。

-什么是EEPROM

EEPROM就是一种存储介质,就像ROM、PROM、FLASH储存器等,下面我粗略地介绍一下EEPROM的由来
ROM:只读存储器,其中的内容在工厂中就烧录好了,内容只能读,不能改,所以用户只能读取其中数据,一旦数据出错,ROM就相当于废掉了。
PROM:可编程的ROM,相比于原来的ROM,用户可以将自己所需要的数据写入,但也只有一次机会,数据一旦写入之后就无法修改。
EPROM:可擦除可编程ROM,相比较PROM,此芯片可以重复擦除和写入,虽然它解决了PROM只能写入一次的弊端,但EPROM数据的擦除是通过紫外线的照射来完成的,所以使用此芯片时对紫外线的防护是很重要的。
EEPROM电可擦除可编程ROM,鉴于EPROM擦除数据的不容易,EEPROM应运而生,它是以电子信号来修改其内容的,而且是以byte为最小修改单位的,不需要将数据全部清除来写入,可以实现定向修改数据。而且因为其数据保存具有掉电不丢失的特性备受追捧。
在下的程序就是通过51单片机模拟IIC总线对AT24C02(EEPROM的型号)进行数据的存取和修改。
AT24C02的储存容量为256B一般通过片内子地址寻址对内部256B中任意一个进行读\写操作,其寻址范围为00~FF。

-IIC总线的通信格式

就像串口通讯和红外遥控一样,IIC总线也有一套通信方式。
硬件结构
先来认识一下IIC总线的硬件结构,SDA是数据线,SCL是时钟线,总线上个器件均采用漏极开路结构与总线相连,因此SDA和SCL都需要上拉电阻,总线在空闲状态保持高电平,一旦某一器件输出低电平,都将使总线的信号变低,所以说各器件的SDA和SCL都是线“与”关系。
在这里插入图片描述
数据位有效性
IIC中数据的传输是通过SDA和SCL

c51模拟IIC总线实现EEPROM存取数据//ÈÎÎñ17 ±£´æÉ趨Êý¾Ý #include <reg51.h> // #include <intrins.h> // #define DCOUNT 6 // ¶¨ÒåÊýÂë¹ÜµÄ¸öÊýΪ6¸ö #define portled_s P1 // ÊýÂë¹ÜµÄ¶ÎÑ¡¿ÚΪP1¿Ú #define portled_b P2 // ÊýÂë¹ÜµÄλѡ¿ÚΪP2¿Ú #define uchar unsigned char // sbit SDA=P3^0; // ´®ÐÐÊý¾ÝÏß sbit SCL=P3^1; // ´®ÐÐʱÖÓÏß uchar idata disdat[6]; // ÊýÂë¹ÜµÄÏÔʾÊý×é uchar data wcnt; // ÊýÂë¹ÜɨÃèλÖüÆÊýÆ÷ uchar code led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // uchar code ledctrl[]={0x0fe,0x0fd,0x0fb,0x0f7,0x0ef,0x0df}; // void display(void); // void Delay5000ms(); // void Delay5us(); // void start(void); // void stop(void); // void rdack(void); // void wrack(void); // void wrnoack(void); // void sdbyte(uchar); // uchar rcvbyte(void); // void rdnb(uchar,uchar,uchar idata *); // void wrnb(uchar,uchar,uchar idata *); // //-------------mainº¯Êý------------- void main(void) // { uchar idata rdwrdat[6]; // rdwrdat[6]£º±£´æAT24C02µÄ¶ÁдÊý¾Ý uchar i; // SP=0x5f; // wcnt=0; // for(i=0;i<6;i++)disdat[i]=i; // ÏÔʾÊý¾Ý¸³³õÖµ TMOD=0x10; // TL1=(65536-2764)%256; // T1¸³¼ÆÊý³õÖµ£º3ms TH1=(65536-2764)/256; // ET1=1; // EA=1; // TR1=1; // for(i=0;i<6;i++)rdwrdat[i]=disdat[i]+1; // ¸÷ÏÔʾÊý¾Ý¼Ó1 wrnb(0x00,0x06,rdwrdat); // rdwrdatÖеÄ6¸öÊý±£´æÔÚAT24C02µÄ0x00¡«0x05µ¥ÔªÖÐ Delay5000ms(); rdnb(0x00,0x06,disdat); // ½«AT24C02µÄ0x00--0x05µ¥ÔªÖеÄÊý¶ÁÖÁdisdatÊý×éÖÐ while(1) {PCON=PCON|0x01;} // } // //-------------¶¨Ê±ÖжÏT1·þÎñ³ÌÐò------------- void tim1() interrupt 3 using 1 // { TL1=(65536-2764)%256; // T1¸³¼ÆÊý³õÖµ£º3ms TH1=(65536-2764)/256; // display(); // } // //-------------дÈën¸ö×Ö½ÚÊý¾Ý------------- //subadd£ºAT24C02×ÓµØÖ· //n£ºÐ´Èë×Ö½ÚÊý //dp£ºidataÇø´ýдÈëÊý¾ÝµÄÊ×µØÖ· void wrnb(uchar subadd,uchar n,uchar idata *dp) // { uchar i; // ¶¨Òå¾Ö²¿±äÁ¿i(Ñ­»·¼ÆÊýÆ÷) start(); // ²úÉúÆô¶¯ÐźŠsdbyte(0x0a0); // ·¢ËÍдѰַ×Ö½Ú rdack(); // ¶ÁAT24C02µÄÓ¦´ðÐźŠsdbyte(subadd); // ·¢ËÍ×ÓµØÖ· rdack(); // ¶ÁAT24C02µÄÓ¦´ðÐźŠfor(i=0;i<n;i++) // Ñ­»·n´Î { sdbyte(*dp); // дһ¸ö×Ö½Ú rdack(); // ¶ÁAT24C02µÄÓ¦´ðÐźŠdp++; // ÒÆ¶¯Ö¸Õë } // Ñ­»·Ìå½áÊø stop(); // ²úÉúÍ£Ö¹ÐźŠ} // º¯Êý½áÊø //-------------¶ÁÈ¡n¸ö×Ö½Ú------------- //subadd£ºAT24C02µÄ×ÓµØÖ· //n£º¶Á³ö×Ö½ÚÊý //dp£ºidataÇøÊ×µØÖ· void rdnb(uchar subadd,uchar n,uchar idata *dp) // { uchar i; // ¶¨Òå¾Ö²¿±äÁ¿i(Ñ­»·¼ÆÊýÆ÷) start(); // ²úÉúÆô¶¯ÐźŠsdbyte(0x0a0); // ·¢ËÍдѰַ×Ö½Ú rdack(); // ¶ÁAT24C02µÄÓ¦´ð sdbyte(subadd); // ·¢ËÍ×ÓµØÖ· rdack(); // ¶ÁAT24C02µÄÓ¦´ð start(); // ²úÉúÆô¶¯ÐźŠsdbyte(0x0a1); // ·¢ËͶÁѰַ×Ö½Ú rdack(); // ¶ÁAT24C02µÄÓ¦´ð for(i=0;i<n;i++) // Ñ­»·n´Î { *dp=rcvbyte(); // ¶ÁÒ»¸ö×Ö½Ú£¬²¢´æÈëdpËùÖ¸Ïòµ¥Ôª dp++; // dpÖ¸ÏòÏÂÒ»½ÓÊÕµ¥Ôª if(i<n-1) wrack(); // Èô²»ÊǶÁ×îºóÒ»¸ö×Ö½Ú£¬Ôò²úÉúÓ¦´ðÐźŠelse wrnoack(); // ÊǶÁ×îºóÒ»¸ö×Ö½Ú£¬Ôò²úÉú·ÇÓ¦´ðÐźŠ} // Ñ­»·Ìå½áÊø stop(); // ²úÉúÍ£Ö¹ÐźŠ} // º¯Êý½áÊø //-------------·¢ËÍÆô¶¯ÐźÅ------------- void start(void) // { SDA=1; // Êý¾ÝÏßÖÃ¸ßµçÆ½ SCL=1; // ʱÖÓÊýÖÃ¸ßµçÆ½ SDA=0; // ²úÉúSDAϽµÑØ Delay5us(); // ÑÓʱ5?s SCL=0; // ²úÉúSCLϽµÑØ£¬×¼±¸´«ÊäÊý¾Ý } // º¯Êý½áÊø //-------------·¢ËÍÍ£Ö¹ÐźÅ------------- void stop() // { SDA=0; // Êý¾ÝÏßÇå0 SCL=1; // ²úÉúSCLÉÏÉýÑØ Delay5us(); // ÑÓʱ5?s SDA=1; // ²úÉúSDAÉÏÉýÑØ } // º¯Êý½áÊø //-------------¶ÁÓ¦´ðÐźÅ------------- void rdack(void) // { SDA=1; // Êý¾ÝÖÃ1£¬ÊÍ·ÅÊý¾ÝÏߣ¬×¼±¸¶ÁSDAÏß¡£ SCL=1; // ²úÉúSCLÉÏÉýÑØ Delay5us(); // ÑÓʱ5?s(¶ÔӦʱÖÓµÄ¸ßµçÆ½ÆÚ) SCL=0; // ²úÉúSCLϽµÑØ } // º¯Êý½áÊø //-------------дӦ´ðÐźÅ------------- void wrack(void) // { SDA=0; // ²úÉúSDAϽµÑØ SCL=1; // ²úÉúSCLÉÏÉýÑØ Delay5us(); // ÑÓʱ5?s(¶ÔӦʱÖÓµÄ¸ßµçÆ½ÆÚ) SCL=0; // ²úÉúSCLϽµÑØ } // º¯Êý½áÊø //-------------д·ÇÓ¦´ðÐźÅ------------- void wrnoack(void) // { SDA=1; // ²úÉúSDAÉÏÉýÑØ SCL=1; // ²úÉúSCLÉÏÉýÑØ Delay5us(); //112 ʱÖÓ¸ßµçÆ½ÆÚ5?s SCL=0; // ²úÉúSCLϽµÑØ } // º¯Êý½áÊø //-------------·¢ËÍÒ»¸ö×Ö½Ú------------- void sdbyte(uchar sdat) // { uchar i; // ¶¨Òå¾Ö²¿±äÁ¿i(Ñ­»·´ÎÊý) for(i=0;i<8;i++) // Ñ­»·8´Î { if(sdat&0x80) SDA=1; // Èô×î¸ßλΪ1£¬ÔòÏòSDAÏßд1 else SDA=0; // ×î¸ßλΪ0£¬ÔòÏòSDAÏßд0 SCL=1; // ²úÉúSCLÉÏÉýÑØ Delay5us(); // ÑÓʱ5?s(¶ÔӦʱÖÓµÄ¸ßµçÆ½ÆÚ) SCL=0; // ²úÉúSCLϽµÑØ Delay5us(); // ÑÓʱ5?s(¶ÔӦʱÖÓµÄµÍµçÆ½ÆÚ) sdat=sdat<<1; // ´ý·¢ËÍÊý¾Ý×óÒÆ1λ(´«ËÍ·½ÏòΪ¸ßλÔÚÏÈ) } // Ñ­»·Ìå½áÊø } // º¯Êý½áÊø //-------------½ÓÊÕÒ»¸ö×Ö½Ú------------- uchar rcvbyte(void) // { uchar i,m=0; // ¶¨Òå¾Ö²¿±äÁ¿i(Ñ­»·´ÎÊý)¡¢m(½ÓÊÕÊý¾Ý) for(i=0;i<8;i++) // Ñ­»·8´Î { SDA=1; // Êý¾ÝÏßÖÃ1£¬×¼±¸¶ÁÊý¾ÝÏß SCL=1; // ²úÉúSCLÉÏÉýÑØ m=m<<1; // Ô¤½ÓÊÕ0 if(SDA) m=m|1; // ÈôÊý¾ÝÏßÉÏΪ0£¬Ô¤½ÓÊÕλ¸ÄΪ1 Delay5us(); // ÑÓʱ5?s(¶ÔӦʱÖÓµÄ¸ßµçÆ½ÆÚ) SCL=0; // ²úÉúSCLϽµÑØ Delay5us(); // ÑÓʱ5?s(¶ÔӦʱÖÓµÄµÍµçÆ½ÆÚ) } // Ñ­»·Ìå½áÊø return m; // ·µ»Ø½ÓÊÕÖµ } // º¯Êý½áÊø //-------------ÏÔʾ×Ó³ÌÐò------------- void display(void) { portled_s=0; // ¶ÎÑ¡¿ÚÏûÒþÊä³ö portled_b=ledctrl[wcnt]; portled_s=led[disdat[wcnt]]; wcnt++; wcnt=wcnt%DCOUNT; } /************************************************ STC-ISP²úÉúµÄÑÓʱ³ÌÐò Ö¸Á:STC-Y1 ϵͳƵÂÊ:11.0592MHz ************************************************/ /************************************************ void Delay5us() ¹¦ÄÜ:5usÑÓʱ ************************************************/ void Delay5us() //@11.0592MHz { } /************************************************ void Delay5000ms() ¹¦ÄÜ:5sÑÓʱ ************************************************/ void Delay5000ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); i = 36; j = 5; k = 211; do { do { while (--k); } while (--j); } while (--i); } 解释代码
最新发布
09-27
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值