51单片机-IIC&EEPROM合成文件

发布者:纸扇轻摇最新更新时间:2021-08-27 来源: 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单片机-红外遥控

推荐阅读最新更新时间:2024-11-17 23:05

51单片机C语言学习 3
第三课 生成HEX文件和最小化系统   在开始C语言的主要内容时,我们先来看看如何用KEIL uVISION2来编译生成用于烧写芯片的HEX文件。HEX文件格式是Intel公司提出的按地址排列的数据信息,数据宽度为字节,所有数据使用16进制数字表示, 常用来保存单片机或其他处理器的目标程序代码。它保存物理程序存储区中的目标代码映象。一般的编程器都支持这种格式。我们先来打开第一课做的第一项目,打开它的所在目录,找到test.Uv2的文件就可以打开先前的项目了。然后右击图3-1中的1项目文件夹,弹出项目功能菜单,选Options for Target'Target1',弹出项目选项设置
[单片机]
基于51单片机16X32LED点阵显示屏程序设计
51单片机16X32LED点阵显示屏由单片机最小系统、行驱动电路74HC154、列驱运电路74HC595组成,实现汉字、数字的显示。电路简单。程序中以20个汉字作为显示示例。资料含51单片机C语言源程序、PROTEUS7.8仿真源文件。附送取模软件及取模说明文档,方便你自己更换显示内容。显示移动速度可在程序中进行设置。 #include REG51.H #define FOSC 12 //定义晶振频率 #define INIT_TH0 0x3C //定时器T0初始值 #define INIT_TL0 0xB0 #define TMOD_T00 0x
[单片机]
基于<font color='red'>51</font><font color='red'>单片机</font>16X32LED点阵显示屏程序设计
80C51单片机与8051单片机的主要差别在哪里
80C51单片机是在8051的基础上发展起来的,也就是说在单片机的发展过程中是先有8051,然后才有80C51的。 8051单片机与80C51单片机从外形看是完全一样的,其指令系统、引脚信号、总线等完全一致(完全兼容),也就是说在8051下开发的软件完全可以在80C51上应用,反过来,在89C51下开发的软件也可以在8051上应用。这两种单片机是完全可移植的。 既然这两种单片机外形及内部结构都一样,那它们之间的主要差别在哪里呢? 8051与80C51单片机的主要差别就在于芯片的制造工艺上。80C51的制造工艺是在8051基础上进行了改进。 8051系列单片机采用的是HMOS工艺:高速度、高密度; 80C51系列单片
[单片机]
89C51单片机+X25045构成的看门狗电路
采用89C51单片机和X25045组成的 看门狗电路 ,X25045硬件连接图如图1所示。X25045芯片内包含有一个看门狗定时器,可通过软件预置系统的监控时间。在看门狗定时器预置的时间内若没有总线活动,则X25045将从RESET输出一个高电平信号,经过微分电路C2、R3输出一个正脉冲,使CPU复位。图1电路中,CPU的复位信号共有3个:上电复位(C1、R2),人工复位(S、R1、R2)和Watchdog复位(C2、R3),通过或门综合后加到RESET端。C2、R3的时间常数不必太大,有数百微秒即可,因为这时CPU的振荡器已经在工作。   
[电源管理]
89C<font color='red'>51</font><font color='red'>单片机</font>+X25045构成的看门狗电路
基于51单片机设计N字节十六进制除法——以6字节除以3字节为例
1、思路 借用十进制除法竖式计算的思路,作十六进制的除法竖式计算。 将除数3字节与被除数高3字节对齐,除完后保存当前字节的商和余数,将被除数往低顺延一个字节,再执行新一轮的除法。被除数有6字节,除数有3字节,故除法需执行4轮。这是最外层的循环。 每一轮的除法可转换为多次减法,需要注意的是,对被除数来说减法需要一直执行到最高字节,以保证借位执行无误。这是中间层的循环。 每一轮的减法由单个字节的减法循环组成,减的过程中考虑借位。由于除数只有3个字节,执行完此3次减法后,除数再往上的字节内容为00H,减法就变成了XXH-CY-00H,即纯粹的借位。 为了判断中间层循环什么时候结束,需要额外写一个子程序来比较减数与被减数的
[单片机]
基于<font color='red'>51</font><font color='red'>单片机</font>设计N字节十六进制除法——以6字节除以3字节为例
51单片机内部定时器/计数器实验
一、实验内容 使用MCS-51内部定时/计数器,定时1秒钟,CPU运用定时中断方式,实现每1秒钟输出状态发生一次反转,即发光管每隔1秒钟亮一次(P1.7接LED)。 根据实验内容编写一个程序,并在实验仪器上调试和验证。 二、仿真图 三、代码 C语言实现: # include reg52.h # include intrins.h # define uint unsigned int # define uchar unsigned char sbit LED=P1^0; uchar t,temp; void init(); void main() { t=0; init(); whil
[单片机]
<font color='red'>51</font><font color='red'>单片机</font>内部定时器/计数器实验
基于51单片机的LED显示屏控制电路设计
LED显示屏广泛应用于工矿企业、学校、商场、店铺、公共场所等进行图文显示,广告宣传,信息发布。本文设计一种由4个16×16点阵LED模块组成的显示屏,由单片机作控制器,平滑移动显示任意多个文字或图形符号,本电路可级联扩展实现由任意多个16×16点阵LED模块组成的显示屏。 1 电路设计 控制电路由AT89C51单片机作控制器,显示屏由4个16×16点阵LED模块组成,每个16×16点阵LED模块由4个8×8点阵LED模块组成,用户可根据需要扩展增加任意多个16×16点阵LED模块。8×8点阵LED模块结构如图1所示,共8行8列,每个发光二极管放置在行线和列线的交叉点上,共64个发光二极管。当某一列为高电平,某一行为低电平时,
[单片机]
基于<font color='red'>51</font><font color='red'>单片机</font>的LED显示屏控制电路设计
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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