寻求以通俗的言语让小白能够更容易上手学单片机,在此同时稳固常识(很多图片来自江科大和普中,作者也是学这个来的,仅仅通过自己的言语想把它复述出来)。

本节将以AT24C02实现数据存储事例来驱动对AT24C02,IIC等的学习。

事例:接LCD1602显示屏、设置独立按键,当按下第一个按键为+1,第2个按键为-1,数据范围是0~655350-1->65535,65535+1->0);第三个按键按下会保存数据;第四个按键按下会跳到已保存的数据(不管值是多少,断过电否)。
重点:存储数据,取出数据
用到的模块有LCD1602,Delay(延时函数),Key(独立按键),IIC(数据传输)

ATC24C02的硬件原理

芯片介绍

51单片机第10篇章-AT24C02实现数据存储
如图,这儿的重点是–掉电不丢掉(永久保存)、通讯接口I2C总线,也就是咱们接下来会使用这两个点去实现数据存储。

存储器

由上面咱们可知道,AT24C02是一个存储器,那存储器又有什么常识点(重点)吗? 这儿简略给了个分类图(如下),不具体打开。后边有时间我会再具体讲一下。 能够知道,咱们用的AT24C02属于非易失性存储器(ROM)-即能够实现掉电不丢掉数据(能够实现永久保存数据,掉电后也能够有所设置的数据)。

51单片机第10篇章-AT24C02实现数据存储

引脚图(这个才是对于驱动程序来说,实际一点的东西)

51单片机第10篇章-AT24C02实现数据存储

  1. SDA、SCL为IIC接口,数据的传输(从单片机主机到存储器从机)必须用到这个。
  2. A0,A1,A2为三位的AT24C02存储器地址,能够将数据放在其中的某个地址,然后访问改地址。
  3. WP:AT24C02有一个写保护引脚,供给硬件数据保护。当连接到地(GND)时,写保护引脚允许正常读/写操作。当引脚连接到Vcc时,就会启用Write protection特性,不允许读写。

IIC的地址

51单片机第10篇章-AT24C02实现数据存储
如图,在IIC的模块中,咱们要连接AT24C02,要写入其地址,写为0xA0,读为0xA1.

怎么使得数据传输

51单片机第10篇章-AT24C02实现数据存储
全体思路(手写,字丑勿喷~)

  • 为什么读数据有两个start?这是规则了的,恪守就行,做项目的时分查文档跟着来就能够。

  • 为什么发送了两个地址?第一个地址为SLAVE ADDRESS(器件(芯片)地址,一般固定),第二个地址为 WORD ADDRESS(从机地址,一般可写什么0,1,2不过注意,每个地址只能存放256个字节,即比方65535,就得用/256部分存一个从机地址,%256存一个地址)

    51单片机第10篇章-AT24C02实现数据存储
    写很容易了解,但是读很容易混淆 照着来就行了

代码解读

到了严重又激动的时刻了,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文件作为导入 欢迎交流!!