本文采用STM32的模拟I2C对 EEPROM(AT24C02)进行读写操作。
AT24C02的总容量是256个字节,也就是2K。
VCC和VSS是芯片的电源和地,电压的工作范围为:+1.8V~+6.0V;
A0、A1、A2是IC的地址选择脚;
SCL是I2C通讯时钟引脚;
SDA是I2C通讯数据引脚;
WP是写保护使能脚;当WP引脚接高电平的时,24C02只能进行读取操作,不能进行写操作;只有当WP引脚悬空或接低电平时,24C02才能进行写操作。
AT24C02的设备地址为如下:
前四位固定为1010,A2~A0由管脚电平决定,最后一位表示读/写操作。
因此:
AT24C02的读地址为0xA1;
AT24C02的写地址为0xA0;
AT24C02芯片片内地址寻址可对内部256个字节中的任一个进行读/写操作,其寻址范围为00~FF,共256个。
at24cxx.h,硬件以AT24C02为例;
#ifndef __AT24CXX_H__
#define __AT24CXX_H__
#include "stm32f10x.h"
#define EEPROM_TYPE AT24C02
#define AT24C01 127
#define AT24C02 255
#define AT24C04 511
#define AT24C08 1023
#define AT24C16 2047
#define AT24C32 4096
#define AT24C02_WRITEADDRESS 0XA0
#define AT24C02_READADDRESS 0XA1
void AT24CXX_WriteOneByte(u8 writeaddr,u8 writedat);
u8 AT24CXX_ReadOneByte(u16 readaddr);
u8 AT24CXX_Check(void);//检测器件是否正常
void AT24CXX_WriteLenByte(u16 writeaddr,u32 writedat,u8 Len);
u32 AT24CXX_ReadLenByte(u16 readaddr,u8 Len);
void AT24CXX_Read(u16 readaddr,u8 *p,u16 num);
void AT24CXX_Write(u16 writeaddr,u8 *p,u16 num);
#endif
at24cxx.c
#include "at24cxx.h"
#include "iic.h"
#include "delay.h"
void AT24CXX_WriteOneByte(u8 writeaddr,u8 writedat)
{
IIC_Start();
if(EEPROM_TYPE>AT24C16)
{
IIC_WriteByte(AT24C02_WRITEADDRESS);//发送写命令
IIC_Wait_Ack();
IIC_WriteByte(writeaddr>>8);//发送高地址
}
else
{
IIC_WriteByte(AT24C02_WRITEADDRESS+((writeaddr/256)<<1)); //发送器件地址,写
}
IIC_Wait_Ack();
IIC_WriteByte(writeaddr%256);//发送低地址
IIC_Wait_Ack();
IIC_WriteByte(writedat);//发送要写入的数据
IIC_Wait_Ack();
IIC_Stop(); //产生一个停止条件
delay_ms(10);
}
u8 AT24CXX_ReadOneByte(u16 readaddr)
{
u8 temp=0;
IIC_Start();
if(EEPROM_TYPE>AT24C16)
{
IIC_WriteByte(AT24C02_WRITEADDRESS);//发送写命令
IIC_Wait_Ack();
IIC_WriteByte(readaddr>>8);//发送高地址
}
else
{
IIC_WriteByte(AT24C02_WRITEADDRESS+((readaddr/256)<<1)); //发送器件地址,写
}
IIC_Wait_Ack();
IIC_WriteByte(readaddr%256);//发送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_WriteByte(AT24C02_READADDRESS); //进入接收模式
IIC_Wait_Ack();
temp=IIC_ReadByte();//接收数据
IIC_Stop();//产生一个停止条件
return temp;
}
//检查AT24CXX是否正常
//这里用了24CXX的最后一个地址(255)来存储标志字.
//如果用其他24C系列,这个地址要修改
//返回1:检测失败
//返回0:检测成功
u8 AT24CXX_Check(void)
{
u8 temp;
temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX
if(temp==0X55)
{
return 0;
}
else//排除第一次初始化的情况
{
AT24CXX_WriteOneByte(255,0X55);
temp=AT24CXX_ReadOneByte(255);
if(temp==0X55)return 0;
}
return 1;
}
//在AT24CXX里面的指定地址开始写入长度为Len的数据
//该函数用于写入16bit或者32bit的数据.
//writeaddr :开始写入的地址
//writedat :数据数组首地址
//Len :要写入数据的长度2,4
void AT24CXX_WriteLenByte(u16 writeaddr,u32 writedat,u8 Len)
{
u8 t;
for(t=0;t<Len;t++)
{
AT24CXX_WriteOneByte(writeaddr+t,(writedat>>(8*t))&0xff);
}
}
//在AT24CXX里面的指定地址开始读出长度为Len的数据
//该函数用于读出16bit或者32bit的数据.
//readaddr :开始读出的地址
//返回值 :数据
//Len :要读出数据的长度2,4
u32 AT24CXX_ReadLenByte(u16 readaddr,u8 Len)
{
u8 t;
u32 temp=0;
for(t=0;t<Len;t++)
{
temp<<=8;
temp+=AT24CXX_ReadOneByte(readaddr+Len-t-1);
}
return temp;
}
//在AT24CXX里面的指定地址开始读出指定个数的数据
//readaddr :开始读出的地址 对24c02为0~255
//p :数据数组首地址
//num :要写入数据的个数
void AT24CXX_Read(u16 readaddr,u8 *p,u16 num)
{
while(num)
{
*p++=AT24CXX_ReadOneByte(readaddr++);
num--;
}
}
//在AT24CXX里面的指定地址开始写入指定个数的数据
//writeaddr :开始写入的地址 对24c02为0~255
//p :数据数组首地址
//num :要写入数据的个数
void AT24CXX_Write(u16 writeaddr,u8 *p,u16 num)
{
while(num--)
{
AT24CXX_WriteOneByte(writeaddr,*p);
writeaddr++;
p++;
}
}
此工程硬件基于野火指南者开发板,板载EEPROM芯片24C02,采用I2C接口读写,LED灯指示工作状态,KEY按键进行读写操作,USART串口显示信息,工程包含文件如下图所示:
给出主程序main.c
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usartx.h"
#include "iic.h"
#include "at24cxx.h"
//要写入到24c02的字符串数组
const u8 TEXT_Buffer[]={" STM32F103VET6 IIC-24C02 TEST OK! "};
#define SIZE sizeof(TEXT_Buffer)
int main(void)
{
u8 i=0;
u8 datatemp[SIZE];
delay_init();
LED_GPIO_Config();
KEY_GPIO_Config();
IIC_GPIO_Config();
Usart_Config(115200);
printf("IIC-AT24C02 TEST \r\n");
while(AT24CXX_Check())//检测不到AT24c02
{
printf("AT24C02 Check Failed! \r\n");
delay_ms(500);
printf("Please Check! \r\n");
delay_ms(500);
LEDR_TOGGLE;
}
while(1)
{
if(KEY_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_DOWN)
{
LED_BLUE;
AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
USART_SendString(USARTx,"Start Write 24C02.... \r\n");
USART_SendString(USARTx,"24C02 Write Finished! \r\n");
}
if(KEY_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_DOWN)
{
LED_GREEN;
USART_SendString(USARTx,"Start Read 24C02.... \r\n");
AT24CXX_Read(0,datatemp,SIZE);
USART_SendString(USARTx,"24C02 Read Finished! \r\n");
USART_SendString(USARTx,"The Data Readed Is: ");
USART_SendString(USARTx,datatemp);
USART_SendString(USARTx,"\r\n");
}
i++;
delay_ms(10);
if(i==10)
{
LEDG_TOGGLE;//提示系统正在运行
//printf("AT24C02 Run OK! \r\n");
i=0;
}
}
}
STM32+I2C+AT24C02