单片机
返回首页

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显示写入和读出的数据,分别测试单字节和字符串

这里写图片描述

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 如何利用ESP8266制作一个简单的四轴飞行器

  • 离子检测器电路分析

  • 基于IC555的可变PWM振荡器电路

  • 分享一个电网倾角计电路

  • 电谐波图形均衡器示意图

  • 一种构建12V和230V双直流电源的简单方法

    相关电子头条文章