历史上的今天
返回首页

历史上的今天

今天是:2025年01月14日(星期二)

正在发生

2019年01月14日 | 51通过IO口模拟IIC实现AT24C02的读写

2019-01-14 来源:eefocus

1.硬件连接


这里写图片描述


AT24C02是一个2K位串行CMOS E2PROM, 内部含有256个8位字节,CATALYST公司的先进CMOS技术实质上减少了器件的功耗。AT24C02有一个8字节页写缓冲器。该器件通过IIC总线接口进行操作,有一个专门的写保护功能。在单片机上的应用广泛, 可以实现掉电数据不丢失功能。


2.AT24C02读写时序说明:


(1)写数据描述:


通过IIC几种信号的组合,可以向AT24C02指定单元地址写一字节的数据。


这里写图片描述


可以看出,写顺序为:起始,写器件地址,应答,写单元地址,应答,写数据,应答,终止。


(2)读数据描述


这里写图片描述


从AT24C02任意单元地址读取数据,可以看出读写顺序为:起始,写器件地址(下一个字节为写),应答,写单元地址,应答,起始,写器件地址(下一个字节为读取),读取数据,终止。


3.例程实现


(1)延时

delay.h:


#ifndef _DELAY_H

#define _DELAY_H


#include "stc51.h"


void delay_us(uchar t);

void delay_ms(uint t);



#endif


#include "delay.h"

#include "stc51.h"

//Function:延时1us

//Input:延时的微秒数

//Output:无

//Return:无

//Others:无

void delay_us(uchar t)

{

    while(t--);

}


//Function:延时1us

//Input:延时的毫秒数

//Output:无

//Return:无

//Others:无

void delay_ms(uint t)

{

    uint x,y;

    for(x=t;x>0;x--)

        for(y=110;y>0;y--);

}



(2)IIC模拟

iic.h:


#ifndef _IIC_H

#define _IIC_H


#include "stc51.h"


/*IIC管脚定义*/

sbit IIC_SDA = P3^0;

sbit IIC_SCL = P3^1;


void IO_Init();

void IIC_Start();

void IIC_Stop();

void IIC_Ack();

void IIC_NAck();

void IIC_Write_Byte(uchar txd);

uchar IIC_Read_Byte();


#endif


iic.c:


#include "delay.h"

#include "iic.h"

#include "stc51.h"


//Function:初始化IO口

//Description:GPIO初始化为高,通知器件总线空闲

//Input:无

//Output:无

//Return:无

//Others:无

void IO_Init()

{

    IIC_SCL = 1;

    delay_us(5);

    IIC_SDA = 1;

    delay_us(5);

}


//Function:启动IIC传输

//Description:IIC_SCL为高时,IIC_SDA由高到低

//Input:无

//Output:无

//Return:无

//Others:无

void IIC_Start()

{

    IIC_SDA = 1;

    IIC_SCL = 1;

    delay_us(5);

    IIC_SDA = 0;

    delay_us(5);

    IIC_SCL = 0;

}


//Function:停止IIC传输

//Description:IIC_SCL为高时,IIC_SDA由低到高

//Input:无

//Output:无

//Return:无

//Others:无

void IIC_Stop()

{

    IIC_SCL = 0;

    IIC_SDA = 0;

    delay_us(5);

    IIC_SCL = 1;

    IIC_SDA = 1;

    delay_us(5);

}


//Function:产生应答信号

//Description:IIC_SCL为高时,IIC_SDA被拉低并保持一定时间的低电平

//Input:无

//Output:无

//Return:无

//Others:无

void IIC_Ack()

{

    uchar i;


    IIC_SCL = 1;//在scl为高电平期间等待应答

    delay_ms(2);

    while((IIC_SDA == 1) && i < 250)//若为应答0即退出,从机向主机发送应答信号

        i++;//通过i自增等待一段时间   

    IIC_SCL = 0;//得到应答,拉低时钟

    delay_ms(2);

}


//Function:产生非应答信号

//Description:IIC_SCL为高时,IIC_SDA为高

//Input:无

//Output:无

//Return:无

//Others:无

void IIC_NAck()

{

    IIC_SCL = 1;

    delay_ms(2);

    IIC_SDA = 1;

    IIC_SCL = 0;

    delay_ms(2);

}


//Function:I2C写一个字节数据,返回ACK或者NACK

//Description:从高位开始依次传输

//Input:写的字节

//Output:无

//Return:无

//Others:无

void IIC_Write_Byte(uchar txd)

{

    uchar len;


    for (len=0;len<8;len++)

    {

        IIC_SCL = 0;//只有在IIC_SCL为低电平时,才允许IIC_SDA上的数据变化

        delay_us(5); 

        if(txd & 0x80)

            IIC_SDA = 1;

        else

            IIC_SDA = 0;  

        delay_us(5);   

        IIC_SCL = 1;//在IIC_SCL为高电平时,不允许IIC_SDA上的数据变化,使数据稳定

        txd <<= 1;

        delay_us(10); 

        IIC_SCL = 0;    

        delay_us(5);

    }

    IIC_SDA = 1;//释放总线

    IIC_SCL = 1;

    delay_us(5);

}


//Function:I2C读一个字节数据,返回ACK或者NACK

//Description:从高到低,依次接收

//Input:是否应答

//Output:无

//Return:接收的数据

//Others:无

uchar IIC_Read_Byte(/*uchar ack*/)

{

    uchar len,dat = 0;


    IIC_SDA = 1;//准备读取数据

    for(len=0;len<8;len++) 

    {


        IIC_SCL = 0; 

        delay_us(5);

        IIC_SCL = 1;//不允许IIC_SDA变化

        delay_us(5); 

        dat <<= 1;

        dat |= IIC_SDA; //读数据 

        delay_us(5); 

        IIC_SCL = 0;//允许IIC_SDA变化等待下一位数据的到来

        delay_us(5); 

    }   


    return dat;

}


(3)AT24C02实现:


at24c02.h:


#ifndef _AT24C02_H

#define _AT24C02_H


#include "stc51.h"


#define IIC_WADDR   0XA0

#define IIC_RADDR   0XA1


void AT24C02_Init(void);


void At24c02_Write_Byte(uchar addr,uchar dat);

uchar At24c02_Read_Byte(uchar addr);


void At24c02_Serial_Write(uchar Writeaddr,uchar *Str,uchar Len);

void At24c02_Serial_Read(uchar Readaddr,uchar *Str,uchar Len);


#endif


at24c02.c:


#include "iic.h" 

#include "delay.h"

#include "at24c02.h"

#include "stc51.h"



//Function:初始化AT24C02

//Description:IO口属于空闲,准备开始通信

//Input:无

//Output:无

//Return:无

//Others:无

void AT24C02_Init(void)

{

    IO_Init();

}


//Function:写一个字节

//Description:向AT24C02的任意地址写入一个字节数据

//Input:写入的地址和数据

//Output:无

//Return:无

//Others:无

void At24c02_Write_Byte(uchar addr,uchar dat)

{

    IIC_Start();    //启动

    IIC_Write_Byte(IIC_WADDR);  //发送从设备地址

    IIC_Ack();  //等待从设备的响应

    IIC_Write_Byte(addr);   //发出芯片内地址

    IIC_Ack();  //等待从设备的响应

    IIC_Write_Byte(dat);    //发送数据

    IIC_Ack();  //等待从设备的响应

    IIC_Stop(); //停止

    delay_ms(10);    // 写入周期

}


//Function:指定地址读一个字节

//Description:向AT24C02的指定地址读出一个字节数据

//Input:读地址

//Output:无

//Return:读到的数据

//Others:无

uchar At24c02_Read_Byte(uchar addr)

{

    uchar dat;


    IIC_Start();

    IIC_Write_Byte(IIC_WADDR);//发送发送从设备地址 写操作

    IIC_Ack();

    IIC_Write_Byte(addr);//发送芯片内地址

    IIC_Ack();

    IIC_Start();

    IIC_Write_Byte(IIC_RADDR);//发送发送从设备地址 读操作

    IIC_Ack();

    dat = IIC_Read_Byte();//获取数据

    IIC_Stop();


    return dat;

}


//Function:任意地址写入一串数据

//Description:向AT24C02写入一串数据

//Input:写地址,写数据,数据长度

//Output:无

//Return:无

//Others:无

void At24c02_Serial_Write(uchar Writeaddr,uchar *Str,uchar Len)

{

    while(Len--)

    {

        At24c02_Write_Byte(Writeaddr,*Str);

        Writeaddr++;

        Str++;

    }

}


//Function:指定地址读出一串数据

//Description:向AT24C02读出一串数据

//Input:读地址,读数据,数据长度

//Output:无

//Return:无

//Others:无

void At24c02_Serial_Read(uchar Readaddr,uchar *Str,uchar Len)

{

    while(Len)

    {

        *Str++ = At24c02_Read_Byte(Readaddr++);

        Len--;

    }

}



stc51.h:


#ifndef _STC51_H

#define _STC51_H


#include


typedef unsigned char   uchar;

typedef unsigned int    uint;


#endif


主函数main.c:


#include "iic.h"

#include "at24c02.h"

#include "stc51.h"

#include "Lcd_4line.h"

#include "key.h"

#include "delay.h"


//要写入到24c02的字符串数组

const uchar TEXT_Buffer[]={"STC51"};

uchar TEXT_Buffer1[]={"00000"};//数组一定初始化


#define SIZE sizeof(TEXT_Buffer)


void main()

{

    uchar dat = 8;

    uchar Text = 6 + '0';

    uchar val;


    Lcd_1602_init();

    AT24C02_Init();

    while(1)

    {

        lcd_onestring(0,0,Text);

        At24c02_Write_Byte(10,dat);

        val = At24c02_Read_Byte(10);

        val = val + '0';

        lcd_onestring(1,0,val);


    lcd_string(0,7,5,TEXT_Buffer);

    At24c02_Serial_Write(10,TEXT_Buffer,5);

    At24c02_Serial_Read(10,TEXT_Buffer1,5);

    lcd_string(1,7,5,TEXT_Buffer1);

    }

}


4.实验现象

通过LCD1602显示写入和读出的数据,分别测试单字节和字符串

这里写图片描述

推荐阅读

史海拾趣

Amphenol(安费诺)公司的发展小趣事

Amphenol Corporation,通常简称为Amphenol,是一家全球领先的连接技术公司,提供广泛的连接器解决方案,涵盖了航空航天、汽车、通信、工业、医疗和军事等多个领域。以下是关于Amphenol公司发展的五个相关故事:

  1. 创立与起步阶段:Amphenol公司成立于1932年,总部位于美国康涅狄格州沃拉姆。最初,公司致力于生产无线电连接器,并通过不断的创新和技术改进,逐步发展成为连接器行业的领导者之一。在第二次世界大战期间,Amphenol公司为美国军队提供了大量的军用连接器,为公司的发展奠定了坚实的基础。

  2. 技术创新与产品多样化:随着电子技术的不断进步和市场需求的不断变化,Amphenol公司不断进行技术创新,拓展产品线的多样性。除了传统的连接器产品,公司还开发了许多新型连接器,如光纤连接器、高速数据连接器、环境密封连接器等,以满足不同行业的需求。

  3. 全球化发展与市场拓展:Amphenol公司在全球范围内建立了广泛的销售网络和生产基地,实现了全球化布局和市场覆盖。公司在美国、欧洲、亚洲和其他地区设有多个生产工厂和研发中心,为客户提供当地化的服务和支持。通过不断扩大市场份额和提升产品质量,Amphenol公司成为了全球连接器市场的主要参与者之一。

  4. 客户合作与定制化解决方案:Amphenol公司与客户建立了紧密的合作关系,根据客户的需求和应用场景,提供定制化的连接器解决方案。公司的工程团队与客户共同设计和开发符合特定要求的产品,为客户提供专业化和个性化的服务。这种定制化解决方案能够满足客户多样化的需求,增强了公司在市场上的竞争优势。

  5. 质量管理与持续改进:Amphenol公司高度重视产品质量管理,严格遵循国际质量管理体系标准。公司的生产工艺和质量管理体系通过了ISO 9001质量管理体系认证,并持续进行质量改进和技术创新。此外,Amphenol公司的产品还通过了各种行业认证和标准,如航空航天领域的AS9100认证等,确保产品的可靠性和稳定性。

这些故事展示了Amphenol公司从创立初期到如今在技术创新、产品多样化、全球化发展、客户合作与定制化解决方案以及质量管理与持续改进等方面取得的重要进展。

Bomar公司的发展小趣事

随着电子行业的快速发展,Bomar公司逐渐意识到,仅仅依靠石英晶振产品已经无法满足市场的多样化需求。于是,在1988年,公司开始积极建立OEM客户群,将业务范围拓展至电信、计算机、医疗、安全、商业和工业等多个领域。通过与这些客户的紧密合作,Bomar公司不仅成功推出了时钟振荡器、VCXOs和TCXOs等新产品,还根据客户需求重新设计了制造流程,提升了产品性能和生产效率。

宇阳科技(EYANG)公司的发展小趣事

随着公司业务的不断发展,宇阳科技在产能扩张和全球布局方面也取得了显著进展。公司在深圳、东莞、安徽等地建立了多个生产基地,引进了先进的生产线和检测设备,确保了产品的高品质和稳定供应。同时,宇阳科技还积极拓展海外市场,与全球多家知名企业建立了长期稳定的合作关系。

Fairchild Imaging公司的发展小趣事

Fairchild Imaging公司的历史可以追溯到1950年成立的Fairchild Camera & Instrument Company。这家公司自创立以来,就凭借其创新的技术和优质的产品,在许多重大的政府、国防项目中发挥了关键作用。随着公司业务的不断拓展,Fairchild Camera & Instrument Company逐渐将业务重心转向半导体和集成电路领域,并在此领域取得了显著成就。最终,Fairchild Imaging从Fairchild Camera & Instrument Company中独立出来,专注于高端成像技术的研发和应用。

ACEINNA公司的发展小趣事

Fairchild Imaging非常重视与行业领先企业的合作。通过与这些企业的紧密合作,Fairchild Imaging能够不断吸收先进的技术和管理经验,提升自身的研发和生产能力。同时,这种合作也有助于Fairchild Imaging将其技术成果更快地推向市场,满足客户的多样化需求。

E-San Electronic Co Ltd公司的发展小趣事

在市场竞争日益激烈的情况下,E-San Electronic Co Ltd积极寻求市场拓展的新策略。公司通过与国内外知名企业的合作,成功进入了国际市场。同时,公司还加大了对新兴市场的开拓力度,通过参加各种国际展会和商务活动,提升了品牌知名度和影响力。此外,公司还积极探索线上线下相结合的销售模式,通过电商平台和社交媒体等新兴渠道拓展销售渠道。

问答坊 | AI 解惑

步进电机的控制问题

在职硕士的毕业论文,步进电机的驱动电源设计 要求:1.将步进电机的控制电路、驱动电路以及其它相关电路融为一体,使之具备低功耗和高可靠性的特点;           2.具备较好的通用性,可以进行二相、三相、四相、五 ...…

查看全部问答>

FPGA应用举例.pdf

本帖最后由 paulhyde 于 2014-9-15 03:44 编辑 FPGA应用举例.pdf    …

查看全部问答>

求:基于单片机的点阵显示屏设计论文

本人求一份基于单片机的点阵显示屏设计论文,有意者联系QQ1210979462,待遇QQ聊!…

查看全部问答>

问一个wince5.0 用以太网实现kitl 的问题

以太网kitl通信通道的实现,用到虚拟的网络设备,我想问一下 kitl所用的虚拟的网络设备是由vbridge实现的,还是 由vbridge和vmini共同实现的,或者说vmini在kitl的实现过程中用到了吗? vmini都做些什么? 请高手指点!…

查看全部问答>

十万火急!请教USB端口写数据~

各位前辈大侠,     我现在用一个USB接口的打印机,连接在Wince的PDA上,想直接发送打印数据到打印机。我在网上找了好几天资料都说要找到打印机设备的路径或者是名称,用CreateFile创建句柄,但是我不知道怎么找到该设备。无法用CreateF ...…

查看全部问答>

脉冲宽度的测量的怪问题?

目的是测量连续的脉冲宽度 源码见附件 typedef struct times {   uchar second;       //秒级     uint m_second;     //毫秒级     uchar mm_second_1;  / ...…

查看全部问答>

高手帮帮忙

请问,我用的是MSP430F449单片机,其中很多模块都用不到,也有很多引脚用不上,这些多余的引脚怎么处理呢?肯定不能直接悬空吧?哪位大侠给指点一下呢,谢谢…

查看全部问答>

上、下拉电阻

为什么动不动就要上拉或下拉一个电阻?究竟有什么好处?更重要的是为什么会 有这样的好处?谢谢…

查看全部问答>

高手请指教,关于中断向量表的问题

请问用LF2407外部RAM调试程序时,中断向量表一定要先烧写到FLASH中吗? 现在用外扩的SRAM做程序调试仿真,把中断向量表也分配到了外部SRAM中,结果进不了中断;需要先把中断向量表先烧写到FLASH中吗?还需要加什么跳转指令吗? 更重要的是为 ...…

查看全部问答>