AT24C02寄存助手
选用模块
这个组件叫 AT24C02寄存器
直接上库
先看提供了哪些函数:
实现代码(其实直接塞进去就ok)
库
AT24C02.c
#include <REGX52.H>
#include "I2C.h"
#define AT24C02_ADDRESS 0xA0
/**
* @brief AT24C02写入一个字节
* @param WordAddress 要写入字节的地址
* @param Data 要写入的数据
* @retval 无
*/
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();
}
/**
* @brief AT24C02读取一个字节
* @param WordAddress 要读出字节的地址
* @retval 读出的数据
*/
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;
}
AT24C02.h
#ifndef __AT24C02_H__
#define __AT24C02_H__
void AT24C02_WriteByte(unsigned char WordAddress,Data);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);
#endif
这个库提供了哪些函数?
1. AT24C02_WriteByte
void AT24C02_WriteByte(unsigned char WordAddress, Data);
- 功能:向AT24C02 EEPROM的指定地址写入一个字节。
- 参数:
WordAddress:目标存储单元的地址(范围为0x00到0xFF,具体取决于芯片容量)。Data:需要存储的数据(一个字节,范围为0x00到0xFF)。
- 返回值:无(
void类型)。 - 具体用途:
- 在EEPROM中保存配置信息、状态值等,断电后数据依然保存。
2. AT24C02_ReadByte
unsigned char AT24C02_ReadByte(unsigned char WordAddress);
- 功能:从AT24C02 EEPROM的指定地址读取一个字节。
- 参数:
WordAddress:需要读取的存储单元地址。
- 返回值:从指定地址读取到的数据(一个字节)。
- 具体用途:
- 从EEPROM中提取配置数据、记录等。
江协科技速览
1. 如何新建工程并添加所需模块?
操作步骤
- 打开KO软件,点击“新建工程”,选择保存位置(如12 - 1文件夹),设定工程名称。
- 在工程设置中,选择合适的单片机型号(如AT89CY)。
- 添加main函数,确保勾选“HEX”选项,以便生成可执行文件。
- 点击“头文件”按钮,添加所需的头文件(如 REGX52.H 等)。
- 从软件界面找到并选中所需模块(如LCD、按键、AT24C02等相关模块),使用“复制”(Ctrl + C)和“粘贴”(Ctrl + V)操作将其添加到工程中。
注意事项
- 确保所选单片机型号与实际使用的硬件一致,否则可能导致程序无法正常运行。
- 添加头文件时,要注意文件路径的正确性,避免找不到头文件的错误。
2. I2C协议中起始条件和停止条件是如何实现的?
起始条件实现原理
- 在I2C的起始条件中,默认SCL(时钟线)和SDA(数据线)为高电平,这是空闲状态。
- 为确保起始条件的正确拼接,首先执行
I2C_SDA = 1;,将SDA线置为高电平。这一步是为了保证在起始条件之前,SDA处于一个确定的高电平状态,避免因之前状态不确定而导致起始条 件错误。 - 接着
I2C_SCL = 1;,拉高SCL时钟线,此时SCL和SDA均为高电平。然后I2C_SDA = 0;,在SCL为高电平时,将SDA线拉低,这是起始条件的关键操作,根据I2C协议,SCL高电平期间,SDA从高电平切换到低电平表示起始条件。最后I2C_SCL = 0;,拉低SCL线,完成起始条件的设置。
停止条件实现原理
- 停止条件的实现同样基于SCL和SDA的电平操作。在停止之前,SDA可能处于0或1的不确定状态,所以先执行
I2C_SDA = 0;,将SDA线拉低。 - 然后
I2C_SCL = 1;,拉高SCL时钟线。此时,SCL为高电平,SDA为低电平。最后I2C_SDA = 1;,将SDA线拉高,使SDA和SCL均为高电平,恢复到空闲状态,符合I2C协议中停止条件的规定,即SCL高电平期间,SDA从低电平切换到高电平表示停止条件。
代码示例
代码示例
// 起始条件函数
void I2C_Start(void)
{
I2C_SDA = 1;
I2C_SCL = 1;
I2C_SDA = 0;
I2C_SCL = 0;
}
// 停止条件函数
void I2C_Stop(void)
{
I2C_SDA = 0;
I2C_SCL = 1;
I2C_SDA = 1;
}
3. 如何实现I2C协议中发送一个字节和接收一个字节的功能?
发送一个字节的实现
- 发送一个字节的函数(如
I2C_SendByte)有一个参数Byte,用于指定要发送的字节数据。 - 通过一个
for循环8次,实现从字节的高位到低 位依次发送。每次循环中,先将Byte与0x80进行与运算,取出最高位的值赋给SDA(即I2C_SDA = Byte & 0x80;),然后将SCL拉高(I2C_SCL = 1;),再拉低(I2C_SCL = 0;)。在拉高SCL期间,从机可以读取SDA上的数据,完成一位数据的发送。发送完一位后,Byte右移一位(Byte >>= 1;),准备发送下一位,循环8次后完成一个字节的发送。
接收一个字节的实现
- 接收一个字节的函数(如
I2C_ReceiveByte)首先执行I2C_SDA = 1;,释放SDA总线,准备接收数据。 - 然后通过一个
for循环8次,每次循环先将SCL拉高(I2C_SCL = 1;),在SCL高电平期间读取SDA的数据。使用if判断读取的值,如果SDA为1,则将返回变量Byte的相应位置1(即Byte |= 0x80 >> i;),否则不处理。读取完一位后,将SCL拉低(I2C_SCL = 0;),准备接收下一位数据。循环8次后,完成一个字节的接收,最后返回接收的字节Byte。
代码示例
代码示例
// 发送一个字节函数
void I2C_SendByte(unsigned char Byte)
{
unsigned char i;
for (i = 0; i < 8; i++)
{
I2C_SDA = Byte & 0x80;
I2C_SCL = 1;
I2C_SCL = 0;
Byte >>= 1;
}
}
// 接收一个字节函数
unsigned char I2C_ReceiveByte(void)
{
unsigned char Byte = 0x00, i;
I2C_SDA = 1;
for (i = 0; i < 8; i++)
{
I2C_SCL = 1;
if (I2C_SDA)
{
Byte |= 0x80 >> i;
}
I2C_SCL = 0;
}
return Byte;
}
4. 发送应答和接收应答在I2C协议中是如何操作的?
发送应答的操作
- 发送应答的函数(如
I2C_SendAck)有一个参数AckBit,用于指定应答位的值(0表示应答,1表示非应答)。 - 函数内部直接将
SDA设置为应答位的值(即I2C_SDA = AckBit;),然后将SCL拉高(I2C_SCL = 1;),再拉低(I2C_SCL = 0;),完成发送应答操作。这一系列操作按照I2C协议规定,在接收完一 个字节后,主机在下一个时钟发送一位数据作为应答信号。
接收应答的操作
- 接收应答的函数(如
I2C_ReceiveAck)首先执行I2C_SDA = 1;,释放SDA总线,准备接收应答信号。 - 然后将
SCL拉高(I2C_SCL = 1;),在SCL高电平期间读取SDA的值赋给应答位变量AckBit(即AckBit = I2C_SDA;),接着将SCL拉低(I2C_SCL = 0;),最后返回应答位AckBit。根据I2C协议,返回值为0代表有应答,返回值为1代表无应答。主机在接收之前需要释放SDA,然后在SCL高电平期间读取从机发送的应答信号。
代码示例
代码示例
// 发送应答函数
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;
}
5. 在AT24C02中如何实现字节写入和读取操作?
字节写入操作
- 字节写入操作通过调用一系列I2C函数来实现。首先调用
I2C_Start函数,启动I2C总线,发送起始条件。 - 接着发送AT24C02的地址(0XA0),通过
I2C_SendByte函数发送,发送后调用I2C_ReceiveAck函数接收应答,检查从机是否正确响应。 - 然后发送要写入的字节地址,再次接收应答。之后发送要写入的数据,同样接收应答。
- 最后调用
I2C_Stop函数,发送停止条件,完成字节写入操作。在写入操作后,需要延时5毫秒,因为AT24C02的写周期最长为5毫秒,这是芯片的特性要求,以确保数据正确写入。可以使用Delay函数来实现延时,例如Delay(5);。
字节读取操作
- 字节读取操作也遵循I2C协议的流程。先调用
I2C_Start函数启动总线,发送起始条件。 - 发送地址(0XA0 | 0X01表示读操作),通过
I2C_SendByte函数发送,然后接收应答。 - 接着调用
I2C_ReceiveByte函数获取数据,读取一个字节后,发送非应答位(1),表示读取结束,最后调用I2C_Stop函数发送停止条件。读取操作不需要延时,但写入操作后必须延时,否则会出错,这是因为写入操作涉及到芯片内部的存储过程,需要一定时间来完成数据的写入和存储。
代码示例
代码示例
// 在AT24C02中写入一个字节的函数
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();
Delay(5); // 写入后延时5毫秒
}
// 从AT24C02中读取一个字节的函数
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
unsigned char Data;
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS | 0x01);
I2C_ReceiveAck();
Data = I2C_ReceiveByte();
I2C_SendAck(1);
I2C_Stop();
return Data;
}