C51 10.AT24C02
前言
AT24C存储介质为02E2PROM,通讯接口为I2C总线的存储器
祝愉快
1.原理图
A0、A1、A2为I2C地址
SCL、SDA为I2C接口
2.I2C总线结构
两根通信线SCL(Serial Clock)和SDA(Serial Data)。
- 所有I2C设备的SCL连在一起,SDA连在一起
- 设备的SCL和SDA均应配置开漏输出模式
- SCL和SDA每增加一个上拉电阻,电阻值一般为4.7K欧
- 泄漏输出和上拉电阻的共同作用实现了线与的功能,主要是解决多机通信相互干扰的问题
3.I2C时序结构
4.I2C数据帧
我们将上述时序结构结合起来
发送的第一步是发送发送地址和读写标志字(写)字。
收到响应后,一个BIT接一个BIT发送。
接收的第一步是发送接收地址和读写标志字(读)字
收到响应后,一个BIT接一个BIT接收。
组合上面的数据帧,以完成向谁收指定的数据的任务
以复合格式改写AT24C02数据帧格式
5.C代码
用代码实现I2C数据帧
#include <REGX52.H> sbit I2C_SCL=P2^1; sbit I2C_SDA=P2^0; /** * @brief I2C开始 * @param 无 * @retval 无 */ void I2C_Start(void) {
I2C_SDA=1; I2C_SCL=1; I2C_SDA=0; I2C_SCL=0; } /** * @brief I2C停止 * @param 无 * @retval 无 */ void I2C_Stop(void) {
I2C_SDA=0; I2C_SCL=1; I2C_SDA=1; } /** * @brief I2C发送字节 * @param Byte 要发送的字节 * @retval 无 */ void I2C_SendByte(unsigned char Byte) {
unsigned char i; for(i=0;i<8;i ) {
I2C_SDA=Byte&(0x80>>i);=1;
I2C_SCL=0;
}
}
/** * @brief I2C接收一个字节 * @param 无 * @retval 接收到的一个字节数据 */
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);}
I2C_SCL=0;
}
return Byte;
}
/** * @brief I2C发送应答 * @param AckBit 应答位,0为应答,1为非应答 * @retval 无 */
void I2C_SendAck(unsigned char AckBit)
{
I2C_SDA=AckBit;
I2C_SCL=1;
I2C_SCL=0;
}
/** * @brief I2C接收应答位 * @param 无 * @retval 接收到的应答位,0为应答,1为非应答 */
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
/** * @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;
}
main
#include <REGX52.H>
#include "LCD1602.h"
#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) //K1按键,Num自增
{
Num++;
LCD_ShowNum(1,1,Num,5);
}
if(KeyNum==2) //K2按键,Num自减
{
Num--;
LCD_ShowNum(1,1,Num,5);
}
if(KeyNum==3) //K3按键,向AT24C02写入数据
{
AT24C02_WriteByte(0,Num%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) //K4按键,从AT24C02读取数据
{
Num=AT24C02_ReadByte(0);
Num|=AT24C02_ReadByte(1)<<8;
LCD_ShowNum(1,1,Num,5);
LCD_ShowString(2,1,"Read OK ");
Delay(1000);
LCD_ShowString(2,1," ");
}
}
}
总结
- 表示出I2C的每一种数据帧。
- 用I2C数据帧拼凑出AT24C02的数据帧