追求以通俗的语言让小白可以更容易上手学单片机,在此同时巩固知识(很多图片来自江科大和普中,作者也是学这个来的,只是通过自己的语言想把它复述出来)。
本节将以AT24C02实现数据存储案例来驱动对AT24C02,IIC等的学习。
案例:接LCD1602显示屏、设置独立按键,当按下第一个按键为+1,第2个按键为-1,数据范围是0~65535(0-1->65535,65535+1->0);第三个按键按下会保存数据;第四个按键按下会跳到已保存的数据(无论值是多少,断过电否)。
重点:存储数据,取出数据
用到的模块有LCD1602,Delay(延时函数),Key(独立按键),IIC(数据传输)
ATC24C02的硬件原理
芯片介绍
如图,这里的重点是–掉电不丢失(永久保存)、通讯接口I2C总线,也就是我们接下来会利用这两个点去实现数据存储。
存储器
由上面我们可知道,AT24C02是一个存储器,那存储器又有什么知识点(重点)吗? 这里简单给了个分类图(如下),不详细展开。后面有时间我会再详细讲一下。 可以知道,我们用的AT24C02属于非易失性存储器(ROM)-即能够实现掉电不丢失数据(可以实现永久保存数据,掉电后也可以有所设置的数据)。
引脚图(这个才是对于驱动程序来说,实际一点的东西)
- SDA、SCL为IIC接口,数据的传输(从单片机主机到存储器从机)必须用到这个。
- A0,A1,A2为三位的AT24C02存储器地址,可以将数据放在其中的某个地址,然后访问改地址。
- WP:AT24C02有一个写保护引脚,提供硬件数据保护。当连接到地(GND)时,写保护引脚允许正常读/写操作。当引脚连接到Vcc时,就会启用Write protection特性,不允许读写。
IIC的地址
如图,在IIC的模块中,我们要连接AT24C02,要写入其地址,写为0xA0,读为0xA1.
怎么使得数据传输
整体思路(手写,字丑勿喷~)
-
为什么读数据有两个start?这是规定了的,遵守就行,做项目的时候查文档跟着来就可以。
-
为什么发送了两个地址?第一个地址为SLAVE ADDRESS(器件(芯片)地址,一般固定),第二个地址为 WORD ADDRESS(从机地址,一般可写什么0,1,2···不过注意,每个地址只能存放256个字节,即比如65535,就得用/256部分存一个从机地址,%256存一个地址) 写很容易理解,但是读很容易混淆 照着来就行了
代码解读
到了紧张又激动的时刻了,3、2、1上代码!
主函数
#include <REGX52.H>
#include "LCD1602.h"//引入显示屏,独立按键,AT24C02,延时函数
#include "Key.h"
#include "AT24C02.h"
#include "Delay.h"
unsigned char KeyNum;
unsigned int Num;
void main()
{
LCD_Init();
LCD_ShowNum(1,1,Num,5);
while(1)
{
KeyNum=Key();
if(KeyNum==1) //当等于1时,就++
{
Num++;
LCD_ShowNum(1,1,Num,5);
}
if(KeyNum==2) //当等于2时,就--
{
Num--;
LCD_ShowNum(1,1,Num,5);
}
if(KeyNum==3) //当等于3时,就保存
{
AT24C02_WriteByte(0,Num%256);//因为一个从机地址只能存8位,所以必须将十进制数分/256和%256部分
Delay(5);//最好写完延迟函数,保证数据能录入
AT24C02_WriteByte(1,Num/256);
Delay(5);
LCD_ShowString(2,1,"Write OK");
Delay(1000);
LCD_ShowString(2,1," ");
}
if(KeyNum==4) //读取存储的数据
{
Num=AT24C02_ReadByte(0);
Num|=AT24C02_ReadByte(1)<<8;//要将前面的部分左移并入NUM-
LCD_ShowNum(1,1,Num,5);//此时16位二进制数会转为十进制数
LCD_ShowString(2,1,"Read OK ");
Delay(1000);
LCD_ShowString(2,1," ");
}
}
}
LCD1602 显示屏
这里是封装好的,以后可以用,不过由于篇幅,这里不展示,可以去看我写的LCD1602文章,里面有封装
Key 独立按键
#include <REGX52.H>
#include "Delay.h"
unsigned char Key()
{
unsigned char KeyNumber=0;
if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
return KeyNumber;
}
IIC
#include <REGX52.H>
sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;
void I2C_Start(void)//开始
{
I2C_SDA=1;
I2C_SCL=1;//一定要在SCL置1时才时SDA下降沿
I2C_SDA=0;
I2C_SCL=0;
}
void I2C_Stop(void)
{
I2C_SDA=0;
I2C_SCL=1;
I2C_SDA=1;
}
void I2C_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
I2C_SDA=Byte&(0x80>>i);//要先置SDA,再给上升沿,再下降
I2C_SCL=1;
I2C_SCL=0;
}
}
unsigned char I2C_ReceiveByte(void)
{
unsigned char i,Byte=0x00;
I2C_SDA=1;
for(i=0;i<8;i++)
{
I2C_SCL=1;
if(I2C_SDA){Byte|=(0x80>>i);}//在SCL置1 时获取,然后置0
I2C_SCL=0;
}
return Byte;
}
void I2C_SendAck(unsigned char AckBit)
{
I2C_SDA=AckBit;
I2C_SCL=1;
I2C_SCL=0;
}
unsigned char I2C_ReceiveAck(void)
{
unsigned char AckBit;
I2C_SDA=1;
I2C_SCL=1;
AckBit=I2C_SDA;
I2C_SCL=0;
return AckBit;
}
AT24C02
#include <REGX52.H>
#include "I2C.h"
#define AT24C02_ADDRESS 0xA0
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_SendByte(Data);
I2C_ReceiveAck();
I2C_Stop();
}
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
unsigned char Data;
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS|0x01);
I2C_ReceiveAck();
Data=I2C_ReceiveByte();
I2C_SendAck(1);
I2C_Stop();
return Data;
}
这就是数据存储的代码,每个模块要有一个XXX.h文件作为导入 欢迎交流!!
今天的文章51单片机第10篇章-AT24C02实现数据存储分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/16213.html