基于STM32的I2C通信 2(读写AT24C02)

本文采用STM32的模拟I2C对 EEPROM(AT24C02)进行读写操作。

1.EEPROM(24C02):I2C接口

1.1-24C02器件介绍:

AT24C02的总容量是256个字节,也就是2K。
VCC和VSS是芯片的电源和地,电压的工作范围为:+1.8V~+6.0V;
A0、A1、A2是IC的地址选择脚;
SCL是I2C通讯时钟引脚;
SDA是I2C通讯数据引脚;
WP是写保护使能脚;当WP引脚接高电平的时,24C02只能进行读取操作,不能进行写操作;只有当WP引脚悬空或接低电平时,24C02才能进行写操作。
基于STM32的I2C通信 2(读写AT24C02)_第1张图片

1.2-24C02的读写

AT24C02的设备地址为如下:
前四位固定为1010,A2~A0由管脚电平决定,最后一位表示读/写操作。
因此:
AT24C02的读地址为0xA1
AT24C02的写地址为0xA0
AT24C02芯片片内地址寻址可对内部256个字节中的任一个进行读/写操作,其寻址范围为00~FF,共256个。

1.2.1-24C02字节写时序

基于STM32的I2C通信 2(读写AT24C02)_第2张图片

1.2.2-24C02字节读时序

基于STM32的I2C通信 2(读写AT24C02)_第3张图片

1.2.3-程序代码

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++;
	}
}

2.工程结构

此工程硬件基于野火指南者开发板,板载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;
		}	
	}
}

3.功能测试

基于STM32的I2C通信 2(读写AT24C02)_第4张图片

4.资料分享

STM32+I2C+AT24C02

你可能感兴趣的:(STM32,单片机,嵌入式硬件)