历史上的今天

今天是:2024年08月27日(星期二)

正在发生

2021年08月27日 | 51单片机-IIC&EEPROM合成文件

发布者:纸扇轻摇 来源: eefocus关键字:51单片机  IIC  EEPROM 手机看文章 扫描二维码
随时随地手机看文章

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”添加到工程文件中

12.7.png

5.main.c测试代码


#include

#include //详见第六章第8讲

#include      //详见第十一章第3讲

#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单片机  IIC  EEPROM 引用地址:51单片机-IIC&EEPROM合成文件

上一篇:51单片机-EEPROM简单使用
下一篇:51单片机-红外遥控

推荐阅读

近日,在2018世界机器人大会上,欧洲机器人协会副主席,库卡机器人有限公司德国总部研发负责人莱纳·比绍夫 (Rainer Bischoff)受邀发表了《欧洲机器人学的发展与未来创新》的主题演讲,向行业和用户分享了欧洲机器人的发展现状和未来创新方向。库卡机器人作为全球领先的工业机器人及自动化生产设备和解决方案的供应商之一,在自动化机器人领域占有举...
经过近两年的实践,“硬科技”概念得到了许多城市的认可和实践。北京已成立“硬科技基金”;杭州将硬科技写入政府文件;成都要通过硬科技引领,加快向“新经济2.0版”发起冲击。 作为“硬科技”概念的首倡城市,我市的硬科技产业目前发展得如何呢?8月22日,记者采访了市科技局相关负责人,据介绍,我市硬科技产业发展良好,九大硬科技产业中,光电芯片(...
近年来,在一系列产业政策的支持下,我国集成电路和软件产业实现快速发展,为经济社会信息化数字化水平的提升提供了有力支撑。园区作为我国产业发展的集聚区,也是国民经济和地区经济发展的重要载体。各大产业园区也为吸引集成电路企业落户、打造产业生态系统、完善人才、服务配套系统等方面出台了很多具体实施细则。各地园区、政府更是呈“攀比”状态,吸...
据路透社报道,消息人士称,日本东芝公司正在和全球至少四家大型私募股权投资公司(其中包括 KKR 和黑石集团)进行沟通,征求他们对东芝新发展战略的意见建议。需要注意的是,这并不意味着东芝正式为整个公司或其部分资产征求收购要约,目前也尚不清楚与收购公司的合作是否会在未来产生正式要约。但上述举动表明东芝正在与潜在收购方进行接触。此前,东...

史海拾趣

问答坊 | AI 解惑

消除GSM手机的”嗡嗡”声

由于有更多的功能和更小的体积,当今的手机PCB比以前的手机越来越复杂,内部有越来越多的”噪音”.在许多情况下,扬声器很靠近天线,而音频放大器很接近RF功率放大器(PA)部分,这就会引起”嗡嗡”声的噪音.本文描述了如何提供更好的RF噪音. …

查看全部问答∨

清华大学教材《嵌入式系统的构建》

本帖最后由 paulhyde 于 2014-9-15 08:59 编辑 清华大学教材《嵌入式系统的构建》  …

查看全部问答∨

能源之星5.0浮出水面

作者 PowerAnt 现在,能源之星5.0,以及能源之星4.0的第二级(Tier 2)正在制定当中, 相关的讨论的信息可以在这里查到: http://www.energystar.gov/index.cfm?c=revisions.computer_spec 对电源效率的要求已经大致有些眉目。 可以预见的是,能 ...…

查看全部问答∨

evc调试遇到的问题,请帮忙分析一下

1.exe has exited with code -1159943394 (0xBADCAB1E),我的设备和应用程序通过Activesync软件相连接,设备那边和我DEBUG调试的程序断了连接,并且在DEBUG窗口出现了上述错误现象,请帮忙指点指点,找不到错误发生在哪里?…

查看全部问答∨

底层驱动的疑问?

我们头让我和他一起做xc2365的底层驱动,我连底层驱动具体搞什么都不清楚,哪位大哥可以指点一下,然后该看看什么方面的书籍?谢谢!!!…

查看全部问答∨

关于PPP通讯的问题??????

我做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 QQ交流群

wince/ARM 硬件驱动/应用程序QQ交流群39063007 ---一个人瞎看学得太慢了,晚上eeworld访问超慢,特别建立此群,请wince 驱动的,应用程序的都进来光顾一下,一起消磨晚上的时光…

查看全部问答∨

为什么调用不了modelsim?

我装了quartus web10.1版,modelsim 6.5。。但是在调用modelsim6.5的时候不启动啊,win7系统,环境变量,路径什么的都设置了,同样的设置XP下就启动了。。。在点了eda rtl simulation 后下边也不提示错误,下边提示两条: 1:Info: Successfully l ...…

查看全部问答∨

哪里有STM32的实验板?

                                 我是给学生用的,实验稍微简单一点,要有实验程序。…

查看全部问答∨

15通道锂电池管理模块

48V及以下电压的锂电池单元在微混动汽车和工业储能中的应用率很高。系统由13至15个锂电池单体构成。由于锂电池固有特性,需要对该数量的电池单体进行精确监测,以保障系统安全性并提高电池效率和寿命。         本 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved