1.导入Delay、key、LCD1602相关文件
2.控制逻辑
以I2C去写入,用AT24C02包装好,main调用即可
3.编写I2C代码
看着这六个状态编
图1 开和关
图2 发送一个字节
图3 接收一个字节
图4 接收和发送应答
#include <REGX52.H>
sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;
/**
* @brief I2C开始
* @param 无
* @retval 无
*/
void I2C_Start(void)
{
//空闲状态默认SCL和SDA是高电平的
I2C_SDA=1; //SDA可能是0
I2C_SCL=1; //SCL在I2C复合的时候有可能为低电平
I2C_SDA=0; //SDA要换为低电平
I2C_SCL=0; //SCL要换为低电平
}
/**
* @brief I2C发送一个字节
* @param Data 要发送的字节
* @retval 无
*/
void I2C_Send(unsigned char Data)
{
//默认I2C_SCL=0;
unsigned char i;
for(i=0;i<8;i++)
{
I2C_SDA=Data&(0x80>>i);
I2C_SCL=1;
I2C_SCL=0; //写了立马就读没超过最大时钟
}
}
/**
* @brief I2C接收一个字节
* @param 无
* @retval 接收到的一个字节数据
*/
unsigned char I2C_Receive(void) //这里不需要参数Data
{
unsigned char Receive_Data=0x00,i;
I2C_SDA=1; //释放SDA
for(i=0;i<8;i++)
{
I2C_SCL=1; //低电平不允许读取,所以要为1
if(I2C_SDA)Receive_Data|=(0x80>>i);
I2C_SCL=0;
}
return Receive_Data;
}
/**
* @brief I2C发送应答
* @param ACK_select 应答位,0为应答,1为非应答
* @retval 无
*/
void I2C_Send_ACK(unsigned char ACK_select)
{
//返回需要通过时序变化,不能直接返回参数值
I2C_SDA=ACK_select; //SDA就是应答位
//发送应答过程
I2C_SCL=1;
I2C_SCL=0;
}
/**
* @brief I2C接收应答位
* @param 无
* @retval 接收到的应答位,0为应答,1为非应答
*/
unsigned char I2C_Receive_ACK(void)
{
unsigned char ACK_bit;
//返回需要通过时序变化,不能直接返回参数值
I2C_SDA=1; //SDA释放
//发送应答过程
I2C_SCL=1;
ACK_bit=I2C_SDA;
I2C_SCL=0;
return ACK_bit;
}
/**
* @brief I2C停止
* @param 无
* @retval 无
*/
void I2C_Stop(void)
{ //归为0上拉才有意义
I2C_SDA=0; //在终止之前,SDA有可能是0,有可能是1
I2C_SCL=1;
I2C_SDA=1;
}
4.看此图编写AT24C02代码
#include <REGX52.H>
#include "I2C.h"
#define AT24C02_ADDRESS 0xA0 //默认地址
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
I2C_Start();
I2C_Send(AT24C02_ADDRESS);
I2C_Send_ACK(0);
I2C_Send(WordAddress);
I2C_Send_ACK(0);
I2C_Send(Data); //第一个字节数据
I2C_Send_ACK(0);
I2C_Stop();
}
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
unsigned char num;
I2C_Start();
I2C_Send(AT24C02_ADDRESS);
I2C_Receive_ACK();
I2C_Send(WordAddress);
I2C_Receive_ACK();
I2C_Start();
I2C_Send(AT24C02_ADDRESS|0x01); //这表示为读
I2C_Receive_ACK();
num=I2C_Receive();
I2C_Send_ACK(1);
I2C_Stop();
return num;
}
5.编写main代码
#include <REGX52.H>
#include "LCD1602.h"
#include "key.h"
#include "AT24C02.h"
#include "Delay.h"
unsigned char keynum;
unsigned int figure=0;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"Hello! ");
while(1)
{
keynum=Key();
//K1按键,Num自增
if(keynum==1)
{
figure++;
LCD_ShowNum(2,1,figure,5);
}
//K2按键,Num自减
if(keynum==2)
{
figure--;
LCD_ShowNum(2,1,figure,5);
}
//K3按键,向AT24C02写入数据
if(keynum==3)
{
AT24C02_WriteByte(0,figure%256);
Delay(5);
AT24C02_WriteByte(1,figure/256);
Delay(5);
Delay(1000);
LCD_ShowString(2,1,"Write ok");
Delay(500);
}
//K4按键,从AT24C02读取数据
if(keynum==4)
{
static int temp=0;
temp=AT24C02_ReadByte(0);
temp|=AT24C02_ReadByte(1)<<8; //这一步为叠加数据
LCD_ShowString(2,1,"Read ok");
Delay(500);
LCD_ShowString(2,1," ");
LCD_ShowNum(2,1,temp,5);
Delay(1000);
}
}
}
6.试验结果展示
AT24C02存储