STM32F030 IIC2通用读写24C02、24C16、24C32、24C64等例程
前言:咱们做嵌入式开发经常用到EEPROM,但是EEPROM的大小不同会需要不同代码来适配,这不利于快捷开发。在此本人分享自己优化总结后一段代码给大家,该代码通用读写24C02、24C16、24C32、24C64等EEPROM,只需在宏定义做相应芯片型号定义,则可使用。注意!该代码适用于STM32F030的I2C2,如果需要用I2C1或者芯片型号是STM32F0XX其他系列的,需要做相应的驱动代码
·
前言:
咱们做嵌入式开发经常用到EEPROM,但是EEPROM的大小不同会需要不同代码来适配,这不利于快捷开发。在此本人分享自己优化总结后一段代码给大家,该代码通用读写24C02、24C16、24C32、24C64等EEPROM,只需在宏定义做相应芯片型号定义,则可使用。
注意!该代码适用于STM32F030的I2C2,如果需要用I2C1或者芯片型号是STM32F0XX其他系列的,需要做相应的驱动代码改动。
C文件代码:
/* Includes ------------------------------------------------------------------*/
#include "bs_iic.h"
uint32_t AT24Cxx_Timeout;
uint8_t AT24Cxx_Address=0;
uint8_t AT24Cxx_DataNum=0;
/*
主机模式
普通模式 100kHZ
I2C时钟频率32000KHz
使用模拟滤波器
不使用数字滤波器
上升时间100ns
下降时间10ns
*/
uint32_t AT24Cxx_TIMEOUT_UserCallback(void)
{
/* Block communication and all processes */
/* while (1)
{
}*/
return AT24Cxx_FAIL;
}
void I2C2_Init(void)
{
I2C_InitTypeDef I2C_InitStruct;
GPIO_InitTypeDef GPIO_InitStructure;
I2C_DeInit(I2C1);
//RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_1);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
I2C_InitStruct.I2C_Ack=I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_AnalogFilter=I2C_AnalogFilter_Enable;
I2C_InitStruct.I2C_DigitalFilter=0x00;
I2C_InitStruct.I2C_Mode=I2C_Mode_I2C;
I2C_InitStruct.I2C_OwnAddress1=0x00;//0x55;//
I2C_InitStruct.I2C_Timing=0x30E32E44;//0x20D22E37;
I2C_Init(I2C2,&I2C_InitStruct);
//RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
I2C_Cmd(I2C2, ENABLE);
}
void AT24CXX_Init(void)
{
I2C2_Init();
AT24Cxx_Address = AT24Cxx_HW_Address;
}
uint32_t AT24Cxx_WaitEepromStandbyState(void)
{
__IO uint32_t sEETrials = 0;
/* Configure CR2 register : set Slave Address and end mode */
I2C_TransferHandling(AT24Cxx_I2C,
AT24Cxx_Address,
0,
I2C_AutoEnd_Mode,
I2C_No_StartStop);
do
{
/* Initialize sEETimeout */
AT24Cxx_Timeout = AT24Cxx_FLAG_TIMEOUT;
/* Clear NACKF */
I2C_ClearFlag(AT24Cxx_I2C,
I2C_ICR_NACKCF | I2C_ICR_STOPCF);
/* Generate start */
I2C_GenerateSTART(AT24Cxx_I2C, ENABLE);
/* Wait until timeout elapsed */
while (AT24Cxx_Timeout-- != 0);
/* Check if the maximum allowed numbe of trials has bee reached */
if (sEETrials++ == AT24Cxx_MAX_TRIALS_NUMBER)
{
/* If the maximum number of trials has been reached, exit the function */
return AT24Cxx_TIMEOUT_UserCallback();
}
}
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_NACKF) != RESET);
/* Clear STOPF */
I2C_ClearFlag(AT24Cxx_I2C, I2C_ICR_STOPCF);
/* Return sEE_OK if device is ready */
return AT24Cxx_OK;
}
uint32_t AT24Cxx_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite)
{
uint32_t DataNum = 0;
#if defined(AT24C04) || defined(AT24C08)|| defined(AT24C16) || defined(AT24C32)|| defined(AT24C64)
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, 2, I2C_Reload_Mode, I2C_Generate_Start_Write);
#else
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);
#endif
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_TXIS) == RESET)
{
if((AT24Cxx_Timeout--) == 0)
{
return AT24Cxx_TIMEOUT_UserCallback();
}
}
#if defined(AT24C04) || defined(AT24C08)|| defined(AT24C16) || defined(AT24C32)|| defined(AT24C64)
/* Send MSB of memory address */
I2C_SendData(AT24Cxx_I2C, (uint8_t)((WriteAddr & 0xFF00) >> 8));
/* Wait until TXIS flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_TXIS) == RESET)
{
if((AT24Cxx_Timeout--) == 0)
{
return AT24Cxx_TIMEOUT_UserCallback();
}
}
#endif
/* Send LSB of memory address */
I2C_SendData(AT24Cxx_I2C, (uint8_t)(WriteAddr & 0x00FF));
/* Wait until TCR flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_TCR) == RESET)
{
if((AT24Cxx_Timeout--) == 0)
{
return AT24Cxx_TIMEOUT_UserCallback();
}
}
/* Update CR2 : set Slave Address , set write request, generate Start and set end mode */
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, (uint8_t)(*NumByteToWrite), I2C_AutoEnd_Mode, I2C_No_StartStop);
while (DataNum != (*NumByteToWrite))
{
/* Wait until TXIS flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_TXIS) == RESET)
{
if((AT24Cxx_Timeout--) == 0)
{
return AT24Cxx_TIMEOUT_UserCallback();
}
}
/* Write data to TXDR */
I2C_SendData(AT24Cxx_I2C, (uint8_t)(pBuffer[DataNum]));
/* Update number of transmitted data */
DataNum++;
}
/* Wait until STOPF flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_STOPF) == RESET)
{
if((AT24Cxx_Timeout--) == 0)
{
return AT24Cxx_TIMEOUT_UserCallback();
}
}
/* Clear STOPF flag */
I2C_ClearFlag(AT24Cxx_I2C, I2C_ICR_STOPCF);
return AT24Cxx_OK;
}
void AT24Cxx_WriteBuffer(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite)
{
uint16_t NumOfPage = 0, NumOfSingle = 0, count = 0;
uint16_t Addr = 0;
Addr = WriteAddr % AT24Cxx_PAGESIZE;
count = AT24Cxx_PAGESIZE - Addr;
NumOfPage = NumByteToWrite / AT24Cxx_PAGESIZE;
NumOfSingle = NumByteToWrite % AT24Cxx_PAGESIZE;
/*!< If WriteAddr is sEE_PAGESIZE aligned */
if(Addr == 0)
{
/*!< If NumByteToWrite < sEE_PAGESIZE */
if(NumOfPage == 0)
{
/* Store the number of data to be written */
AT24Cxx_DataNum = NumOfSingle;
/* Start writing data */
AT24Cxx_WritePage(pBuffer, WriteAddr, (uint8_t*)(&AT24Cxx_DataNum));
AT24Cxx_WaitEepromStandbyState();
}
/*!< If NumByteToWrite > sEE_PAGESIZE */
else
{
while(NumOfPage--)
{
/* Store the number of data to be written */
AT24Cxx_DataNum = AT24Cxx_PAGESIZE;
AT24Cxx_WritePage(pBuffer, WriteAddr, (uint8_t*)(&AT24Cxx_DataNum));
AT24Cxx_WaitEepromStandbyState();
WriteAddr += AT24Cxx_PAGESIZE;
pBuffer += AT24Cxx_PAGESIZE;
}
if(NumOfSingle!=0)
{
/* Store the number of data to be written */
AT24Cxx_DataNum = NumOfSingle;
AT24Cxx_WritePage(pBuffer, WriteAddr, (uint8_t*)(&AT24Cxx_DataNum));
AT24Cxx_WaitEepromStandbyState();
}
}
}
/*!< If WriteAddr is not sEE_PAGESIZE aligned */
else
{
/*!< If NumByteToWrite < sEE_PAGESIZE */
if(NumOfPage== 0)
{
/*!< If the number of data to be written is more than the remaining space
in the current page: */
if (NumByteToWrite > count)
{
/* Store the number of data to be written */
AT24Cxx_DataNum = count;
/*!< Write the data conained in same page */
AT24Cxx_WritePage(pBuffer, WriteAddr, (uint8_t*)(&AT24Cxx_DataNum));
AT24Cxx_WaitEepromStandbyState();
/* Store the number of data to be written */
AT24Cxx_DataNum = (NumByteToWrite - count);
/*!< Write the remaining data in the following page */
AT24Cxx_WritePage((uint8_t*)(pBuffer + count), (WriteAddr + count), (uint8_t*)(&AT24Cxx_DataNum));
AT24Cxx_WaitEepromStandbyState();
}
else
{
/* Store the number of data to be written */
AT24Cxx_DataNum = NumOfSingle;
AT24Cxx_WritePage(pBuffer, WriteAddr, (uint8_t*)(&AT24Cxx_DataNum));
AT24Cxx_WaitEepromStandbyState();
}
}
/*!< If NumByteToWrite > sEE_PAGESIZE */
else
{
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / AT24Cxx_PAGESIZE;
NumOfSingle = NumByteToWrite % AT24Cxx_PAGESIZE;
if(count != 0)
{
/* Store the number of data to be written */
AT24Cxx_DataNum = count;
AT24Cxx_WritePage(pBuffer, WriteAddr, (uint8_t*)(&AT24Cxx_DataNum));
AT24Cxx_WaitEepromStandbyState();
WriteAddr += count;
pBuffer += count;
}
while(NumOfPage--)
{
/* Store the number of data to be written */
AT24Cxx_DataNum = AT24Cxx_PAGESIZE;
AT24Cxx_WritePage(pBuffer, WriteAddr, (uint8_t*)(&AT24Cxx_DataNum));
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
AT24Cxx_WaitEepromStandbyState();
WriteAddr += AT24Cxx_PAGESIZE;
pBuffer += AT24Cxx_PAGESIZE;
}
if(NumOfSingle != 0)
{
/* Store the number of data to be written */
AT24Cxx_DataNum = NumOfSingle;
AT24Cxx_WritePage(pBuffer, WriteAddr, (uint8_t*)(&AT24Cxx_DataNum));
AT24Cxx_WaitEepromStandbyState();
}
}
}
}
uint32_t AT24Cxx_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead)
{
uint32_t NumbOfSingle = 0, Count = 0, DataNum = 0, StartCom = 0;
/* Get number of reload cycles */
Count = (*NumByteToRead) / 255;
NumbOfSingle = (*NumByteToRead) % 255;
#if defined(AT24C04) || defined(AT24C08)|| defined(AT24C16) || defined(AT24C32)|| defined(AT24C64)
/* Configure slave address, nbytes, reload and generate start */
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
#else
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
#endif
/* Wait until TXIS flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_TXIS) == RESET)
{
if((AT24Cxx_Timeout--) == 0)
{
return AT24Cxx_TIMEOUT_UserCallback();
}
}
#if defined(AT24C04) || defined(AT24C08)|| defined(AT24C16) || defined(AT24C32)|| defined(AT24C64)
/* Send MSB of memory address */
I2C_SendData(AT24Cxx_I2C, (uint8_t)((ReadAddr & 0xFF00) >> 8));
/* Wait until TXIS flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_TXIS) == RESET)
{
if((AT24Cxx_Timeout--) == 0)
return AT24Cxx_TIMEOUT_UserCallback();
}
#endif
/* Send LSB of memory address */
I2C_SendData(AT24Cxx_I2C, (uint8_t)(ReadAddr & 0x00FF));
/* Wait until TC flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_TC) == RESET)
{
if((AT24Cxx_Timeout--) == 0) return AT24Cxx_TIMEOUT_UserCallback();
}
/* If number of Reload cycles is not equal to 0 */
if (Count != 0)
{
/* Starting communication */
StartCom = 1;
/* Wait until all reload cycles are performed */
while( Count != 0)
{
/* If a read transfer is performed */
if (StartCom == 0)
{
/* Wait until TCR flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_TCR) == RESET)
{
if((AT24Cxx_Timeout--) == 0) return AT24Cxx_TIMEOUT_UserCallback();
}
}
/* if remains one read cycle */
if ((Count == 1) && (NumbOfSingle == 0))
{
/* if starting communication */
if (StartCom != 0)
{
/* Configure slave address, end mode and start condition */
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, 255, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
}
else
{
/* Configure slave address, end mode */
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, 255, I2C_AutoEnd_Mode, I2C_No_StartStop);
}
}
else
{
/* if starting communication */
if (StartCom != 0)
{
/* Configure slave address, end mode and start condition */
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, 255, I2C_Reload_Mode, I2C_Generate_Start_Read);
}
else
{
/* Configure slave address, end mode */
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, 255, I2C_Reload_Mode, I2C_No_StartStop);
}
}
/* Update local variable */
StartCom = 0;
DataNum = 0;
/* Wait until all data are received */
while (DataNum != 255)
{
/* Wait until RXNE flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_RXNE) == RESET)
{
if((AT24Cxx_Timeout--) == 0) return AT24Cxx_TIMEOUT_UserCallback();
}
/* Read data from RXDR */
pBuffer[DataNum]= I2C_ReceiveData(AT24Cxx_I2C);
/* Update number of received data */
DataNum++;
(*NumByteToRead)--;
}
/* Update Pointer of received buffer */
pBuffer += DataNum;
/* update number of reload cycle */
Count--;
}
/* If number of single data is not equal to 0 */
if (NumbOfSingle != 0)
{
/* Wait until TCR flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_TCR) == RESET)
{
if((AT24Cxx_Timeout--) == 0) return AT24Cxx_TIMEOUT_UserCallback();
}
/* Update CR2 : set Nbytes and end mode */
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, (uint8_t)(NumbOfSingle), I2C_AutoEnd_Mode, I2C_No_StartStop);
/* Reset local variable */
DataNum = 0;
/* Wait until all data are received */
while (DataNum != NumbOfSingle)
{
/* Wait until RXNE flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_RXNE) == RESET)
{
if((AT24Cxx_Timeout--) == 0) return AT24Cxx_TIMEOUT_UserCallback();
}
/* Read data from RXDR */
pBuffer[DataNum]= I2C_ReceiveData(AT24Cxx_I2C);
/* Update number of received data */
DataNum++;
(*NumByteToRead)--;
}
}
}
else
{
/* Update CR2 : set Slave Address , set read request, generate Start and set end mode */
I2C_TransferHandling(AT24Cxx_I2C, AT24Cxx_Address, (uint32_t)(NumbOfSingle), I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
/* Reset local variable */
DataNum = 0;
/* Wait until all data are received */
while (DataNum != NumbOfSingle)
{
/* Wait until RXNE flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_RXNE) == RESET)
{
if((AT24Cxx_Timeout--) == 0) return AT24Cxx_TIMEOUT_UserCallback();
}
/* Read data from RXDR */
pBuffer[DataNum]= I2C_ReceiveData(AT24Cxx_I2C);
/* Update number of received data */
DataNum++;
(*NumByteToRead)--;
}
}
/* Wait until STOPF flag is set */
AT24Cxx_Timeout = AT24Cxx_LONG_TIMEOUT;
while(I2C_GetFlagStatus(AT24Cxx_I2C, I2C_ISR_STOPF) == RESET)
{
if((AT24Cxx_Timeout--) == 0) return AT24Cxx_TIMEOUT_UserCallback();
}
/* Clear STOPF flag */
I2C_ClearFlag(AT24Cxx_I2C, I2C_ICR_STOPCF);
/* If all operations OK, return sEE_OK (0) */
return AT24Cxx_OK;
}
/************************ (C) COPYRIGHT LKL0305 ****************END OF FILE****/
H文件代码:
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __BS_I2C_H
#define __BS_I2C_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx.h"
#define AT24Cxx_FLAG_TIMEOUT ((uint32_t)0x2000)
#define AT24Cxx_LONG_TIMEOUT ((uint32_t)(10 * AT24Cxx_FLAG_TIMEOUT))
#define AT24Cxx_MAX_TRIALS_NUMBER 300
#define AT24Cxx_OK 0
#define AT24Cxx_FAIL 1
#define AT24Cxx_I2C I2C2
//AT24C01 AT24C02 一页 8Byte
//AT24C04 AT24C08 AT24C16 一页 16Byte
//AT24C32 AT24C64 一页 32Byte
//-------注意!!!本代码只适用24C64及以下的EEPROM ,大于8K的ROM不能使用此代码--------------
#define AT24C02 //定义你使用的芯片型号
#if defined(AT24C01) || defined(AT24C02)
#define AT24Cxx_PAGESIZE 8
#elif defined(AT24C04) || defined(AT24C08)|| defined(AT24C16)
#define AT24Cxx_PAGESIZE 16
#else
#define AT24Cxx_PAGESIZE 32
#endif
#define AT24Cxx_HW_Address 0xAE//0xA0 这个注意对应你的硬件地址!!!!
extern void AT24CXX_Init(void);
extern void AT24Cxx_WriteBuffer(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite);
extern uint32_t AT24Cxx_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead);
#endif
主程序代码:
#include "stm32f0xx.h"
#include "bs_iic.h"
int main(void)
{
//app_run();
//-----------IIC2-测试代码-----
uint8_t read_b[64]={0};
uint8_t wirte_b[64]={1,2,3,4,4,4,8,5,22,66,88,77};
AT24CXX_Init();
while(1){
uint16_t r_num=10;
uint16_t w_num=10;
AT24Cxx_ReadBuffer(read_b,0,&r_num);//注意!这里num在读取数据后减少对应长度
AT24Cxx_WriteBuffer(wirte_b,0,w_num);
if(wirte_b[0]<250)
wirte_b[0]++;
else
wirte_b[0]=0;
}
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献3条内容
所有评论(0)