1.浅释E2Write函数
宋老师的例程lesson14_3和lesson14_4里的“E2Write(unsigned char *buf, unsigned char addr, unsigned char len)”书写内容是不一样的,lesson14_4的E2Write函数比lesson14_3的E2Write函数运行高效,lesson14_3的E2Write函数是每写入一个字节就要经历起始信号,停止信号,写入下一个字节又要把这些步骤经历一遍。而lesson14_4的E2Write函数支持EEPROM页写入(参考《手把手教你学51单片机》文档14.3.3节),所以在建立起文件时我们选用lesson14_4的E2Write函数。
大家新建两个文件“iic.c”和“iic.h”,我们把IIC的相关函数和EEPROM的相关函数都合成在“iic.c”这个单独文件里。
2.iic.c的代码
#include #include #include #define I2CDelay() {_nop_();_nop_();_nop_();_nop_();} /* 产生总线起始信号 */ void I2CStart() { I2C_SDA = 1; //首先确保SDA、SCL都是高电平 I2C_SCL = 1; I2CDelay(); I2C_SDA = 0; //先拉低SDA I2CDelay(); I2C_SCL = 0; //再拉低SCL } /* 产生总线停止信号 */ void I2CStop() { I2C_SCL = 0; //首先确保SDA、SCL都是低电平 I2C_SDA = 0; I2CDelay(); I2C_SCL = 1; //先拉高SCL I2CDelay(); I2C_SDA = 1; //再拉高SDA I2CDelay(); } /* I2C总线写操作,dat-待写入字节,返回值-从机应答位的值 */ unsigned char I2CWrite(unsigned char dat) { unsigned char ack; //用于暂存应答位的值 unsigned char mask; //用于探测字节内某一位值的掩码变量 for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行 { if ((mask&dat) == 0) //该位的值输出到SDA上 I2C_SDA = 0; else I2C_SDA = 1; I2CDelay(); I2C_SCL = 1; //拉高SCL I2CDelay(); I2C_SCL = 0; //再拉低SCL,完成一个位周期 } I2C_SDA = 1; //8位数据发送完后,主机释放SDA,以检测从机应答 I2CDelay(); I2C_SCL = 1; //拉高SCL ack = I2C_SDA; //读取此时的SDA值,即为从机的应答值 I2CDelay(); I2C_SCL = 0; //再拉低SCL完成应答位,并保持住总线 return (!ack); //应答值取反以符合通常的逻辑: //0=不存在或忙或写入失败,1=存在且空闲或写入成功 } /* I2C总线读操作,并发送应答或者非应答信号,返回值-读到的字节 */ unsigned char I2CReadNAK_OR_ACK(unsigned char nak_or_ack) { unsigned char mask; unsigned char dat; I2C_SDA = 1; //首先确保主机释放SDA for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行 { I2CDelay(); I2C_SCL = 1; //拉高SCL if(I2C_SDA == 0) //读取SDA的值 dat &= ~mask; //为0时,dat中对应位清零 else dat |= mask; //为1时,dat中对应位置1 I2CDelay(); I2C_SCL = 0; //再拉低SCL,以使从机发送出下一位 } I2C_SDA = nak_or_ack; //8位数据发送完后,传入的参数NAK_OR_ACK决定是否应答,为1不应答,为0应答 I2CDelay(); I2C_SCL = 1; //拉高SCL I2CDelay(); I2C_SCL = 0; //再拉低SCL完成非应答位,并保持住总线 return dat; } /* E2读取函数,buf-数据接收指针,addr-E2中的起始地址,len-读取长度 */ void E2Read(unsigned char *buf, unsigned char addr, unsigned char len) { do { //用寻址操作查询当前是否可进行读写操作 I2CStart(); if (I2CWrite(0x50<<1)) //应答则跳出循环,非应答则进行下一次查询 { break; } I2CStop(); } while(1); I2CWrite(addr); //写入起始地址 I2CStart(); //发送重复启动信号 I2CWrite((0x50<<1)|0x01); //寻址器件,后续为读操作 while (len > 1) //连续读取len-1个字节 { *buf++ = I2CReadNAK_OR_ACK(0); //最后字节之前为读取操作+应答 len--; } *buf = I2CReadNAK_OR_ACK(1); //最后一个字节为读取操作+非应答 I2CStop(); } /* E2写入函数,buf-源数据指针,addr-E2中的起始地址,len-写入长度 */ void E2Write(unsigned char *buf, unsigned char addr, unsigned char len) { while (len > 0) { //等待上次写入操作完成 do { //用寻址操作查询当前是否可进行读写操作 I2CStart(); if (I2CWrite(0x50<<1)) //应答则跳出循环,非应答则进行下一次查询 { break; } I2CStop(); } while(1); //按页写模式连续写入字节 I2CWrite(addr); //写入起始地址 while (len > 0) { I2CWrite(*buf++); //写入一个字节数据 len--; //待写入长度计数递减 addr++; //E2地址递增 if ((addr&0x07) == 0) //检查地址是否到达页边界,24C02每页8字节, { //所以检测低3位是否为零即可 break; //到达页边界时,跳出循环,结束本次写操作 } } I2CStop(); } } 3.iic.h的代码 #ifndef __IIC_H__ #define __IIC_H__ sbit I2C_SCL = P3^7; sbit I2C_SDA = P3^6; void I2CStart();//产生总线起始信号 void I2CStop(); //产生总线停止信号 unsigned char I2CWrite(unsigned char dat);//I2C总线写操作,dat-待写入字节,返回值-从机应答位的值 unsigned char I2CReadNAK_OR_ACK(unsigned char nak_or_ack);//I2C总线读操作,并发送应答或者非应答信号,返回值-读到的字节 void E2Read(unsigned char *buf, unsigned char addr, unsigned char len); //E2读取函数,buf-数据接收指针,addr-E2中的起始地址,len-读取长度 void E2Write(unsigned char *buf, unsigned char addr, unsigned char len);//E2写入函数,buf-源数据指针,addr-E2中的起始地址,len-写入长度 #endif 4.部分代码的修改 “unsigned char I2CReadACK()”和“unsigned char I2CReadNAK()”这里我们合成了一个函数为 “unsigned char I2CReadNAK_OR_ACK(unsigned char nak_or_ack)”,利用参数的传递决定是否产生应答。 那么在main.c中,几乎也是只需要出现EEPROM的写函数“E2Write()”和读函数“E2Read()”而已了。 记得把“iic”添加到工程文件中 5.main.c测试代码 #include #include #include #include void main() { unsigned char buf[]={"We can learn SCM well!"};//我们可以学好单片机 unsigned char str[sizeof(buf)]; //数组长度与buf的一样 InitLcd1602(); //初始化液晶 E2Write(buf,0x8E,sizeof(buf));//把buf数组里面的内容在EEPROM中从地址0x8E开始写,直到把数组里的内容全部写完进去,在EEPROM中保存起来 delay_ms(1000); //过1秒之后再读出里面的内容显示在液晶屏上 E2Read(str,0x8E,sizeof(buf)); //用另一个数组存取从EEPROM中读出的内容 LcdShowStr_len(0, 0,str, 16); LcdShowStr(0, 1, str+16+1); while(1); }
上一篇:51单片机-EEPROM简单使用
下一篇:51单片机-红外遥控
推荐阅读
史海拾趣
Displaytech公司成立于1989年,作为一家LCD模块供应商在香港崭露头角。当时,液晶显示技术正逐渐崭露头角,Displaytech凭借其敏锐的市场洞察力和技术实力,迅速在市场中占据了一席之地。公司初期专注于小型到中型LCD的制造,为工业、消费和医疗行业的客户提供高质量的产品和技术支持。
- 创业初期:
- 描述Clulite公司的创始人或核心团队如何识别电子行业中的某个市场机遇。
- 讲述他们是如何筹集初始资金,设立公司,并开发出第一款产品或解决方案的。
- 可以提及公司在初创阶段面临的挑战,如技术难题、市场竞争等。
- 技术创新:
- 讲述Clulite如何通过研发创新,推出了一款颠覆性的产品或技术,从而获得了市场认可。
- 详细描述这一创新过程,包括研发团队的努力、关键技术的突破等。
- 提及这一创新如何帮助公司在市场上取得了竞争优势。
- 市场拓展:
- 描述Clulite如何逐步扩大市场份额,从地区市场走向全国乃至国际市场。
- 可以讲述公司如何建立销售网络、与合作伙伴建立合作关系,以及参与行业展会等活动来推广品牌和产品。
- 提及公司在市场拓展过程中遇到的挑战和应对策略。
- 品质管理:
- 讲述Clulite如何注重产品质量和客户体验,通过严格的质量控制流程来提升产品可靠性。
- 描述公司如何建立完善的售后服务体系,为客户提供及时、专业的支持。
- 提及这些举措如何帮助公司赢得了客户的信任和口碑。
- 可持续发展:
- 讲述Clulite如何关注环境保护和社会责任,推动公司的可持续发展。
- 描述公司如何采取环保措施,减少生产过程中的污染排放。
- 提及公司如何参与社会公益事业,回馈社会。
请注意,这些故事需要根据Clulite公司的实际情况进行调整和补充。如果你需要更具体的内容,建议查阅Clulite公司的官方网站、新闻报道或行业分析报告,以获取更详细的信息和数据。
随着国内市场的逐渐饱和,Cogent_Computer_Systems公司开始将目光投向海外市场。公司制定了一系列国际化战略,包括参加国际电子展会、建立海外销售网络、拓展国际合作伙伴等。这些举措使得公司的产品和服务逐渐走向全球,赢得了更多国际客户的认可。国际化战略的实施不仅拓宽了公司的市场版图,也提升了公司的品牌影响力和国际竞争力。
随着全球环保意识的提高,Cressall积极响应绿色生产的号召。公司投入资金研发环保型功率电阻器,采用环保材料和生产工艺,减少了对环境的污染。同时,公司还加强了对废弃物的处理和回收利用,实现了资源的循环利用。这些环保措施不仅提升了公司的社会形象,还为公司带来了更多的商机。
由于有更多的功能和更小的体积,当今的手机PCB比以前的手机越来越复杂,内部有越来越多的”噪音”.在许多情况下,扬声器很靠近天线,而音频放大器很接近RF功率放大器(PA)部分,这就会引起”嗡嗡”声的噪音.本文描述了如何提供更好的RF噪音. … 查看全部问答∨ |
|
作者 PowerAnt 现在,能源之星5.0,以及能源之星4.0的第二级(Tier 2)正在制定当中, 相关的讨论的信息可以在这里查到: http://www.energystar.gov/index.cfm?c=revisions.computer_spec 对电源效率的要求已经大致有些眉目。 可以预见的是,能 ...… 查看全部问答∨ |
1.exe has exited with code -1159943394 (0xBADCAB1E),我的设备和应用程序通过Activesync软件相连接,设备那边和我DEBUG调试的程序断了连接,并且在DEBUG窗口出现了上述错误现象,请帮忙指点指点,找不到错误发生在哪里?… 查看全部问答∨ |
我做gprs时,遇到这样的问题,在建立lcp,pap,ipcp时都没问题,得到了移动的内部IP地址,可我发UDP包时怎么服务器都收不到数据为什么? 1.lcp 发送数据hex:7E FF 03 C0 21 01 01 00 16 01 04 05 DC 02 06 00 00 00 00 07 02 08 02 03 04 C0 23 26 ...… 查看全部问答∨ |
|
wince/ARM 硬件驱动/应用程序QQ交流群39063007 ---一个人瞎看学得太慢了,晚上eeworld访问超慢,特别建立此群,请wince 驱动的,应用程序的都进来光顾一下,一起消磨晚上的时光… 查看全部问答∨ |
我装了quartus web10.1版,modelsim 6.5。。但是在调用modelsim6.5的时候不启动啊,win7系统,环境变量,路径什么的都设置了,同样的设置XP下就启动了。。。在点了eda rtl simulation 后下边也不提示错误,下边提示两条: 1:Info: Successfully l ...… 查看全部问答∨ |
48V及以下电压的锂电池单元在微混动汽车和工业储能中的应用率很高。系统由13至15个锂电池单体构成。由于锂电池固有特性,需要对该数量的电池单体进行精确监测,以保障系统安全性并提高电池效率和寿命。 本 ...… 查看全部问答∨ |