初学24CXX系列EEPROM使用详解&STM32库函数I2C总线

      24CXX系列芯片属于EEPROM(Electrically Erasable Programmable read only memory)即电可擦可编程只读存储器,是一种掉电后数据不丢失(不挥发)存储芯片。
      24CXX系列芯片数据说明:见下表(只做参考,只表明常用24CXX器件的常用数据,具体使用请查阅器件数据手册):
如24C02BN容量=2KB,但写缓冲区(页容量)=8K,而不是下表中给出的16K;

型号

存储容量

页数

写缓冲器容量(页容量)

A2引脚功能

A1引脚功能

A0引脚功能

存储数据地址位数

24C01

1K=128Byte*8

16

8

A2

A1

A0

8

24C02

2K=256Byte*8

16

16

A2

A1

A0

8

24C04

4K=512Byte*8

32

16

A2

A1

P8

8

24C08

8K=1024Byte*8

64

16

A2

P9

P8

8

24C16

16K=2048Byte*8

128

16

P10

P9

P8

8

24C32

32K=4096Byte*8

256

32

a2

a1

a0

16

24C64

64K=8192Byte*8

512

32

a2

a1

a0

16

24C128

128K=16384Byte*8

512

64

NC

NC

NC

16

1、    “型号”:24Cxx系列型号的标称C后面的参数代表其存储容量大小,单位为KB,这里的1KB=1024bit;
2、    “存储容量”:24Cxx系列存储数据为8位(bit)格式,根据其容量可以计算出各型号具体存储数据的字节(Byte)数;
3、    “页数”和“写缓冲器容量”:为减少器件的功耗,每个24CXX器件都有一个写缓冲器,器件收到总线发来的数据时,先写入缓冲器并进行应答,直到器件收到总线上发出的STOP信号后,器件将收到的数据写入其内部存储器中;
收到总线STOP信号后,器件将数据从写缓冲器写入存储器中,这个过程需要5ms,如果后面需要进行立即读取或再次写入操作,必须延时>5ms。
“写缓冲器容量”就代表器件可以一次性写入数据的大小,也就是“页”大小。24CXX系列“写缓冲器”(页容量)大小不同,再根据器件存储器大小,“页数”也不相同。
页写:每次对器件的写入(写缓冲器),可以进行多字节数据连续写(只要总线不发出STOP信号),写缓冲器地址位自动+1,如果写入的字节数超过写缓冲器容量,地址计数器自动翻转,从写缓冲器0x00地址重新计数,并覆盖原先写入的数据。
如果在对器件的写操作是从数据地址的0x00地址位开始,在写缓冲器也是从0x00位开始,写满一页需要写入字节数也就等于写缓冲器容量大小;如果设定的写数据地址不是0x00,对于写入写缓冲器的位置地址就是“写数据初始地址%写缓冲器容量(求余)”,这时写满第1页的字节数不一定等于写缓冲器容量大小。
4、    “存储数据地址位数”:(数据存储地址和器件地址不是一个概念),24CXX器件内部存储的每个字节(Byte)都可以进行单独的读写操作(单字节读写),“存储数据地址位数”就代表了其用于寻址的地址位长度。根据容量不同,24C01/02使用8位数据地址位,24C04/08/16虽然也使用了8位的数据地址位,但8位数据地址最大0xff,表示最高可寻址256位(0~255),而24C04/08/16的存储容量有512/1024/2048Byte,明显不够,这时就看图中黄色标注部分,也就是下面说到的A2、A1和A0的其他功能;
5、    “A2”、“A1”、“A0”引脚功能:24CXX系列不同型号器件的这3个引脚接法不同,部分型号可以悬空,但统一接VSS代表0,接VCC代表1。不同型号器件的这3个引脚功能也不同,具体如下:
功能1:图中引脚功能为A2、A1或A0时,说明这3个引脚可以配置为器件的总线地址(通过分别接VSS或VCC),也表示了同一I2C总线上可以连接的同一型号的器件数量。如24C01/02可以接8个,而24C16在同一个I2C总线上只能接1个器件;
功能2:引脚功能位P8、P9和P10时(黄色标注部分),其代表的是数据帧地址。刚才已经说了,24C04存储容量有512Byte,使用8位地址数据寻址只能寻址256位,这里其A0引脚的功能就是数据地址位的第9位,这样其实际寻址功能为2^9=512,24C08和24C16也同理。所以在操作24C04/08/16器件时,如果要使用全部的存储空间,相应P8、P9或P10引脚应单独使用IO控制。


遇到的问题:在实际操作中使用STM32的I2C总线读写24CXX系列EEPROM时,遇到很多问题,陆陆续续学习了好几天,才一一解决。主要的问题有:
1、    开始使用的是板载24C02,在以起始地址0x00进行操作,单字节读写正常,使用多页写时要注意,根据器件的数据手册,写数据首先是写入写缓冲器中,页写就是指向写缓冲器连续写入多个字节,只有在写满写缓冲器(页)或数据字节已经写完,当器件收到总线发出STOP信号后,器件将写缓冲器中数据转写入存储器中,这个事件需要5ms的时间,而且在此期间器件不会对总线做任何反应的。所以在进行页写、总线有多个发送STOP程序之间,或者写完立即读的时候,必须在每个STOP信号后延时5ms。
2、    在使用板载的24C02时,调试页写程序,按照查找的资料,包括程序中定义的24C02参数,应该是写缓冲器为16字节(页容量),也就是每次连续写最多16位,但实际情况是写入和读出的数据不符。最后仔细查看板载的芯片型号,详细的型号为24C02BN,再次查看数据手册,才发现这个型号的24C02,写缓冲器(页容量)是8位,而不是24C02的16位,修改程序,调用程序中24C01定义的参数,读写相符。
3、    使用的是板载24C02,在以起始地址不等于0x00进行操作时,例如起始地址0x05,写入看不出来异常,但是读取时从第0x08位置数据错误,最后确认数据在写入写缓冲器时,并不是始终都是从写缓冲器的头部开始写入,而是根据页(写缓冲器)对应(映射)的存储器地址来写入的。例如起始地址0x05,则在写入写缓冲器时也是从第6位开始写入,写到第8位就算写满本页,需要发送STOP使器件将写缓冲器的内容转写到存储器对应地址中。
4、    I2C总线可以挂在多个器件,正好手上有24C32芯片,刚开始调试单字节读写程序时就发现读写24C02正常,读写24C32不符的问题,仔细查看数据手册,发现24C32因为存储容量较大,数据的地址位使用8位已经不能够定义,24C32使用了16位数据地址长度,程序中也需要对各个芯片的数据地址位长度进行定义。同时也知道了24C04/08/16芯片的A0、A1和A2引脚的不同功能,虽然这三个型号也是8位数据地址位,但同样引用了A0/A1/A2的引脚硬件控制作为存储器数据地址的第9/10/11位;

/*****************************************************************
*  课例名称:学习STM32固件库I2C总线
*  内容说明:IIC总线上EEPROM存储器按页写操作及读的例程
*  平台芯片:STM32F103ZE
*  端口说明:I2C1_SCK=PB6;I2C1_SDA=PB7
*						 USART1_Tx=PA9;USART1_Rx=PA10;
*  其他说明:24CXX系列的型号只定义了容量大小,但尾标不同,其页容量和
*            数据地址字节长度也不同,具体以数据手册为准
*****************************************************************/
#include "stm32f10x.h"
#include "stdio.h"

/*********************定义I2C初始化数据**********************/
#define I2C_Speed      	  400000			//I2C1设置数据传输速度
#define I2C1_OWN_ADDRESS7 0X0a   			//主设备的从地址

/********************定义I2C中线器件参数*********************/
#define EE_24C32_ADDRESS 	0xae        //定义器件型号和器件地址
/*根据型号,定义PAGE_SIZE写存储器(页)大小和数据地址位长度*/
#ifdef EE_24C01_ADDRESS
   #define PAGE_SIZE           8
   #define WORD_ADDR_SIZE      8
	 #define EEPROM_ADDRESS      EE_24C01_ADDRESS
#endif
#ifdef EE_24C02_ADDRESS
   #define PAGE_SIZE           16
   #define WORD_ADDR_SIZE      8
	 #define EEPROM_ADDRESS      EE_24C02_ADDRESS
#endif
#ifdef EE_24C04_ADDRESS
   #define PAGE_SIZE           16
   #define WORD_ADDR_SIZE      8
	 #define EEPROM_ADDRESS      EE_24C04_ADDRESS
#endif
#ifdef EE_24C08_ADDRESS
   #define PAGE_SIZE           16
   #define WORD_ADDR_SIZE      8
	 #define EEPROM_ADDRESS      EE_24C08_ADDRESS
#endif
#ifdef EE_24C16_ADDRESS
   #define PAGE_SIZE           16
   #define WORD_ADDR_SIZE      8
	 #define EEPROM_ADDRESS      EE_24C16_ADDRESS
#endif
#ifdef EE_24C32_ADDRESS
   #define PAGE_SIZE           32
   #define WORD_ADDR_SIZE      16
	 #define EEPROM_ADDRESS      EE_24C32_ADDRESS
#endif
#ifdef EE_24C64_ADDRESS
   #define PAGE_SIZE           32
   #define WORD_ADDR_SIZE      16
	 #define EEPROM_ADDRESS      EE_24C64_ADDRESS
#endif
#ifdef EE_24C128_ADDRESS
   #define PAGE_SIZE           64
   #define WORD_ADDR_SIZE      16
	 #define EEPROM_ADDRESS      EE_24C128_ADDRESS
#endif

u8 ReadData;	//第二次测试读取数据变量
int fputc(int ch,FILE *f);
void Delay_MS(u16 nms);
void USART1_GPIO_Config(void);
void I2C1_GPIO_Config(void);
void I2C_WriteData(u8 addr,u8* dat,u8 size);
void I2C_PageWrite(u8 WriteAddr,u8* WriteDat,u16 WriteSize);
void I2C_ReadData(u8 ReadAddr,u8* ReadDat,u16 ReadSize);


/*****************************************************************
*  名称:Pritf重定向子函数
*****************************************************************/
int fputc(int ch,FILE *f)
{  
    while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET); 
    USART_SendData(USART1,(unsigned char)ch);    
    while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);  
    return (ch);  
}
/*****************************************************************
*  名称:SysTick_MS延时子函数
*****************************************************************/
void Delay_MS(u16 nms)
{
 u32 temp;
 SysTick->LOAD = 9000*nms;
 SysTick->VAL=0X00;//清空计数器
 SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
 do
 {
  temp=SysTick->CTRL;//读取当前倒计数值
 }
 while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
 SysTick->CTRL=0x00; //关闭计数器
 SysTick->VAL =0X00; //清空计数器
}

/*****************************************************************
*  名称:USART1|GPIOA初始化子函数
*****************************************************************/
static void USART1_GPIO_Config(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStruct;						
	GPIO_InitStruct.GPIO_Pin=(GPIO_Pin_9|GPIO_Pin_10);					
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;	
	GPIO_Init(GPIOA,&GPIO_InitStruct);	
	//配置USART1_Tx=PA9;USART1_Rx=PA10;端口为复用推挽输出模式
	USART_InitTypeDef USART_InitStruct;
	USART_InitStruct.USART_BaudRate=9600;
	USART_InitStruct.USART_WordLength=USART_WordLength_8b;
	USART_InitStruct.USART_StopBits=USART_StopBits_1;
	USART_InitStruct.USART_Parity=USART_Parity_No;
	USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_Init(USART1,&USART_InitStruct);
	USART_Cmd(USART1,ENABLE);
}

/*****************************************************************
*  名称:I2C1|GPIOB初始化子函数
*****************************************************************/
static void I2C1_GPIO_Config(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure; 
	
	/* 使能与 I2C1 有关的时钟 */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); 		
	
	/* PB6-I2C1_SCL、PB7-I2C1_SDA*/
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_OD;	       // 开漏输出
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	I2C_InitTypeDef  I2C_InitStructure; 
	/* I2C 配置 */
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	/* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_OwnAddress1 = I2C1_OWN_ADDRESS7; 
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;
	/* I2C的寻址模式 */
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	/* 通信速率 */
	I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;
	/* I2C1 初始化 */
	I2C_Init(I2C1, &I2C_InitStructure);
	/* 使能 I2C1 */
	I2C_Cmd(I2C1, ENABLE); 
}
/*****************************************************************
*  名称:I2C总线等待EEPROM状态检测子函数
*****************************************************************/
//void I2C_EE_WaitEepromStandbyState(void)      
//{
//	vu16 SR1_Tmp = 0;
//	do
//	{
//		/* Send START condition */
//		I2C_GenerateSTART(I2C1, ENABLE);
//		/* Read I2C1 SR1 register */
//		SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);
//		/* Send EEPROM address for write */
//		I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
//	}
//	while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));

//	/* Clear AF flag */
//	I2C_ClearFlag(I2C1, I2C_FLAG_AF);
//		/* STOP condition */    
//	I2C_GenerateSTOP(I2C1, ENABLE); 
//}

/*****************************************************************
*  函数名称:I2C总线向EEPROM写数据子函数
*  函数说明:使I2C向EEPROM器件发送数据前的准备工作
*  输入参数:addr - 写入的数据起始地址
*            dat  - 写入的数据
*            size - 写入的数据长度
*  输出参数:无
*****************************************************************/
void I2C_WriteData(u8 addr,u8* dat,u8 size)
{
//	I2C_EE_WaitEepromStandbyState();
	
	/* [1]Send STRAT condition向I2C总线发送START信号 */
	I2C_GenerateSTART(I2C1, ENABLE);

	/* [2]Test on EV5 and clear it验证EV5事件 */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));  

	/* [3]Send EEPROM address for write发送从设备地址 */
	I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);

	/* [4]Test on EV6 and clear it验证EV6事件 */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
	
	if(WORD_ADDR_SIZE==16)							//如果器件数据地址位长度为16位
	{
		/* [5]Send the EEPROM's internal address to write to发送写数据的起始地址 */
		I2C_SendData(I2C1, addr>>8);			//发送高8位数据地址位

		/* [6]Test on EV8 and clear it验证EV8事件 */
		while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));		
	}
			
	/* [5]Send the EEPROM's internal address to write to发送写数据的起始地址 */
	I2C_SendData(I2C1, addr);						//发送低8位数据地址位

	/* [6]Test on EV8 and clear it验证EV8事件 */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
	
	while(size)
	{
		/* [7]Send the current byte发送数据字节 */
		I2C_SendData(I2C1,*dat);
		/* [8]Test on EV8 and clear it验证EV8事件 */
		while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
		printf("0x%02X ",*dat);						//以16进制显示发送的数据
		dat++;
		size--;
	}
	/* [9]Send STOP condition发送STOP信号 */
	I2C_GenerateSTOP(I2C1, ENABLE);
}

/*****************************************************************
*  函数名称:I2C总线向EEPROM按页写数据子函数
*  函数说明:按页向EEPROM写数据
*  输入参数:WriteAddr - 写入的数据起始地址
*            WriteDat  - 写入的数据
*            WriteSize - 写入的数据长度
*  输出参数:无
*****************************************************************/
void I2C_PageWrite(u8 WriteAddr,u8* WriteDat,u16 WriteSize)
{
	/*FirstPageSize-首页字节数;NumPage-页数;LastPageSize-尾页字节数*/
	u8 FirstPageSize=0,NumPage=0,LastPageSize=0;
	FirstPageSize=(PAGE_SIZE-(WriteAddr%PAGE_SIZE));		//根据写入数据起始地址计算首页字节数
	if(WriteSize>FirstPageSize)													//如果写入数据字节数>计算的写入首页
	{
		I2C_WriteData(WriteAddr,WriteDat,FirstPageSize);	//写入首页字节数据
		Delay_MS(6);																			//24CXX器件每次写操作STOP后从写缓冲器到存储器需要5ms
		WriteSize-=FirstPageSize;													//计算目前仍需要写入数据字节数
		WriteAddr+=FirstPageSize;													//计算目前仍需要写入数据地址
		WriteDat+=FirstPageSize;													//计算目前仍需要写入数据指针
		NumPage=WriteSize/PAGE_SIZE;											//计算目前仍需要写入数据的页数
		LastPageSize=WriteSize%PAGE_SIZE;									//计算目前写入整页后余的字节数(尾页字节数)	
	}
	else
	{
		I2C_WriteData(WriteAddr,WriteDat,WriteSize);			
		return;	//如果写入数据字节数<=计算的写入首页字节数,则按数据字节数写入首页后直接跳出子函数
	}	
	while(NumPage>0)					//如果页数大于0,逐页写入
	{
		I2C_WriteData(WriteAddr,WriteDat,PAGE_SIZE);
		WriteAddr+=PAGE_SIZE;
		WriteDat+=PAGE_SIZE;
		NumPage--;
		Delay_MS(6);
	}
	if(LastPageSize>0)						//如果尾页仍有剩余的字节数,继续写入
	{
		I2C_WriteData(WriteAddr,WriteDat,LastPageSize);	
		Delay_MS(6);
	}
}

/*****************************************************************
*  名称:I2C总线从EEPROM读数据子函数
*****************************************************************/
void I2C_ReadData(u8 ReadAddr,u8* ReadDat,u16 ReadSize)
{  
	//*((u8 *)0x4001080c) |=0x80; 
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));   
		
	/* Send START condition */
	I2C_GenerateSTART(I2C1, ENABLE);
	//*((u8 *)0x4001080c) &=~0x80;

	/* Test on EV5 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

	/* Send EEPROM address for write */
	I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);

	/* Test on EV6 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

	/* Clear EV6 by setting again the PE bit */
	I2C_Cmd(I2C1, ENABLE);
	
	if(WORD_ADDR_SIZE==16)						//如果器件数据地址位长度为16位
	{
		/* Send the EEPROM's internal address to write to */
		I2C_SendData(I2C1, ReadAddr>>8);

		/* Test on EV8 and clear it */
		while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));		
	}
			
	/* Send the EEPROM's internal address to write to */
	I2C_SendData(I2C1, ReadAddr);

	/* Test on EV8 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	/* Send STRAT condition a second time */  
	I2C_GenerateSTART(I2C1, ENABLE);

	/* Test on EV5 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

	/* Send EEPROM address for read */
	I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);

	/* Test on EV6 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

	/* While there is data to be read */
	while(ReadSize)  
	{
		if(ReadSize == 1)
		{
			/* Disable Acknowledgement */
			I2C_AcknowledgeConfig(I2C1, DISABLE);
			
			/* Send STOP Condition */
			I2C_GenerateSTOP(I2C1, ENABLE);
		}

		/* Test on EV7 and clear it */
		if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))  
		{      
			/* Read a byte from the EEPROM */
			*ReadDat = I2C_ReceiveData(I2C1);

			/* Point to the next location where the byte read will be saved */
			ReadDat++; 
			
			/* Decrement the read bytes counter */
			ReadSize--;        
		}   
	}

	/* Enable Acknowledgement to be ready for another reception */
	I2C_AcknowledgeConfig(I2C1, ENABLE);
}

void I2C_ByteRead(u8 Addr)
{  
	//*((u8 *)0x4001080c) |=0x80; 
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));    
		
	/* Send START condition */
	I2C_GenerateSTART(I2C1, ENABLE);
	//*((u8 *)0x4001080c) &=~0x80;

	/* Test on EV5 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

	/* Send EEPROM address for write */
	I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);

	/* Test on EV6 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

	/* Clear EV6 by setting again the PE bit */
	I2C_Cmd(I2C1, ENABLE);

	if(WORD_ADDR_SIZE==16)
	{
		/* Send the EEPROM's internal address to write to */
		I2C_SendData(I2C1, Addr>>8);

		/* Test on EV8 and clear it */
		while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));		
	}
			
	/* Send the EEPROM's internal address to write to */
	I2C_SendData(I2C1, Addr);

	/* Test on EV8 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));


	/* Send STRAT condition a second time */  
	I2C_GenerateSTART(I2C1, ENABLE);

	/* Test on EV5 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

	/* Send EEPROM address for read */
	I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);

	/* Test on EV6 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

	/* Disable Acknowledgement */
	I2C_AcknowledgeConfig(I2C1, DISABLE);
		/* Send STOP Condition */
	I2C_GenerateSTOP(I2C1, ENABLE);
	/* Test on EV7 and clear it */
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
		/* Read a byte from the EEPROM */
	ReadData = I2C_ReceiveData(I2C1);  	

//	/* Enable Acknowledgement to be ready for another reception */
//	I2C_AcknowledgeConfig(I2C1, ENABLE);
       
}
/*****************************************************************
*  函数名称:I2C总线向24CXX器件读写测试主函数
*  函数说明:使用USART1串口打印显示功能,
*            写入时:首先显示发送数组的内容,然后在
*            向24CXX写入时再次逐个显示写入的内容;
*            读取时:先显示读取并验证读取的数据是否正确,再使用
*            单字节读取显示进行验证;
*****************************************************************/
int main(void)
{ 
	u8 i;
	u8 WriteTab[68];					//测试用写数据数组
	u8 ReadTab[68];						//测试用读数据数组
	u16 DataAddr=0x05;				//测试用数据起始地址
	u16 DataSize=68;					//测试用数据长度	

	USART1_GPIO_Config();
	I2C1_GPIO_Config();	
	printf("\r\n ********** STM32固件库I2C外设读写EEPROM器件测试例程 ********** \r\n");
	printf("写入的数据\n\r");
	for(i=0;i

 

 

你可能感兴趣的:(STM32初学)