简单说一下AT24C02芯片:AT24C02芯片为EEPROM,可以实现数据保存,且掉电不丢失。
AT24C02的总容量是 256个字节,该芯片通过 IIC 总线与外部连接
电路如下(原子的):
芯片的1、2、3、4脚接地;
5脚:作为数据线,也就是IIC通信的SDA;
6脚:作为时钟线,也就是IIC通信的SCL;
7脚:接GND(地)
8脚:接VCC(电源)
电源和地之间接个电容,以滤波等
讲实现之前,简单介绍一下IIC:
IIC用于连接微控制器及其外围设备,由数据线 SDA 和时钟 SCL 构成的串行总线,可发送和接收数据。在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。I2C 总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,表示已收到数据。CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。
IIC 总线时序图
代码实现:
稍微讲一下代码以及使用 :
AT24C02写数据:
//在AT24CXX指定地址写入一个数据
//WriteAddr :写入数据的目的地址
//DataToWrite:要写入的数据
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0); //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr>>8);//发送高地址
}else IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); //发送器件地址0XA0,写数据
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite); //发送字节
IIC_Wait_Ack();
IIC_Stop(); //产生一个停止条件
delay_ms(10); //对于EEPROM器件,每写一次要等待一段时间,否则写失败!
}
AT24C02 读数据
//在AT24CXX指定地址读出一个数据
//ReadAddr:开始读数的地址
//返回值 :读到的数据
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0); //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);//发送高地址
}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //发送器件地址0XA0,写数据
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0XA1); //进入接收模式
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();//产生一个停止条件
return temp;
}
初始化代码之后,可以往AT24cXX(EEPROM),写入字符、字符串、数字等,
断电之后,数据还保存在AT24C02里面,只要使用读函数,就可以将数据读出来
示例:
const u8 TEXT_Buffer[]={6,9,12,56,88}; //要写入到24c02的数组
//TEXT_Buffer[]={"dafeacaeceawa"}; 可以是字符串
#define SIZE sizeof(TEXT_Buffer) //计算数组的大小
AT24CXX_Write(0, (u8*)TEXT_Buffer, SIZE); //向AT24C02写入数据
// 0:开始写数据地址,这个地址的范围看自己用什么型号的EEPROM,这里是02,因此地址范围为0~255
//(u8*)TEXT_Buffer, 数组的首地址,也就是我们需要写入的数据的地址
// SIZE:是写入的数据的大小,也就是我们需要存入多少数据,以字节为单位,这里计算的是数组的大小
AT24CXX_Read(0, datatemp, SIZE);
// 0:开始读数据地址,这个地址的范围看自己用什么型号的EEPROM,这里是02,因此地址范围为0~255
//datatemp, 数组的首地址,读出的数据保存在数组里面
// SIZE:是读出的数据的大小,也就是我们需要读多少数据,以字节为单位,这里计算的是数组的大小
开始写入的数据为TEXT_Buffer[]={6,9,12,56,88};
因此读出时,datatemp []={6,9,12,56,88}; 先要什么数据直接对数组操作就行
接下来这部分的代码主要是IIC的初始化以及一些驱动,就粘贴出来,不作详细的介绍了
//初始化IIC
void IIC_Init(void)
{
RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟
GPIOC->CRH&=0XFFF00FFF;//PC11/12 推挽输出
GPIOC->CRH|=0X00033000;
GPIOC->ODR|=3<<11; //PC11,12 输出高
}
//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;
delay_us(4);
IIC_SCL=1;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SDA=1;//发送I2C总线结束信号
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA设置为输入
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输出0
return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//不产生ACK应答
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;
txd<<=1;
delay_us(2); //对TEA5767这三个延时都是必须的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
总结:
1、STM32 与 AT24C02 通信方式为IIC通信;
2、AT24C02 为EEPROM芯片,可以实现数据的掉电保存
3、往AT24C02 写入和读出数据只需要对AT24C02的地址写入和读出就行
4、读出的数据,可以保存在数组里面,操作只需要对数组进行操作