導語“本次 教程使用CubeMx配置I2C進行I2C總線設備的數據讀寫操作,使用EEPROM作為實驗對象”
01第一節 系統要求
?硬件
野火指南者開發板
?軟件
CubeMx & MDK & 串口調試助手
?原理圖
我們可以從原理圖中得到使用的I2C1,AT24C02的設備地址的第三位是000,容量是256個字節。設備地址從下圖得到:
不帶讀寫方向的使用左移得到的地址為0b10100000->0xA0, 讀地址為:0xA1,寫地址為0xA0;
注意:(1) 操作ATC02的時候,多字節寫入的時候沒寫入一個字節,延時最小5ms, 多字節讀的時候沒有要求,頁寫入的時候每8個字節為一頁,共32頁。
02第二節 CubeMx的配置
我們依然使用之前的USART的項目,在此基礎上進行I2C的配置,串口的使用是進行EEPROM讀寫數據顯示在控制臺上,使用CubeMx進行I2C的配置:
I2C的配置很簡單,完成上述配置后生成代碼。
03第三節MDK的代碼編寫
使用MDK打開CubeMx生成的代碼進行應用代碼編寫。
(1)在main.c 中進行AT24C02的相關宏定義和變量定義:
#define ADDR_AT24C_Write 0xA0
#define ADDR_AT24C_Read 0xA1
#define DEV_ADDR_ATC02 0xA0 //0x50 左移得到的。
#define ATC02_BufferSize 256 // 256
#define I2C_TIMEOUT 0xFF
#define AT_I2C hi2c1
uint8_t AT24_WriteBuffer[ATC02_BufferSize],AT24_ReadBuffer[ATC02_BufferSize];
( 2 ) 應用函數申明:
HAL_StatusTypeDef I2C_Write_Buffer(I2C_HandleTypeDef *hi2c,
uint16_t DevAddress, uint16_t MemAddress,
uint16_t MemAddSize, uint8_t *pData, uint16_t Size,
uint32_t Timeout);
HAL_StatusTypeDef I2C_Read_Buffer(I2C_HandleTypeDef *hi2c,
uint16_t DevAddress, uint16_t MemAddress,
uint16_t MemAddSize, uint8_t *pData, uint16_t Size,
uint32_t Timeout);
I2CWriteBuffer()是自定義的任意字節寫入I2C-AT24C02的函數,I2CReadBuffer()是任意字節讀寫函數。這兩個函數的實現采用HAL庫的這兩個函數:
1)HALStatusTypeDef HALI2CMemWrite(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress, uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);
參數依次是:(I2C句柄,AT24C02的設備地址,設備中數據地址,數據地址的大小,寫的數據,數據大小,超時時間)
2)HALStatusTypeDef HALI2CMemRead(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress, uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);
參數依次是:(I2C句柄,AT24C02的設備地址,設備中數據地址,數據地址的大小,讀出數據,數據大小,超時時間)
為什么不直接使用庫函數呢?是因為在測試中AT24C02讀寫不正常,查看AT24C02的手冊發現,單個字節寫入沒問題,多字節的寫入需要每個字節延時5ms, 其實多字節的讀沒有問題,這個從新實現了下。可以連續8個字節的頁寫入,這個不需要延時。
(3)多字節的讀寫函數:
/*這里自己實現多字節的ATC02的寫操作*/
HAL_StatusTypeDef I2C_Write_Buffer(I2C_HandleTypeDef *hi2c,
uint16_t DevAddress, uint16_t MemAddress,
uint16_t MemAddSize, uint8_t *pData, uint16_t Size,
uint32_t Timeout)
{
uint16_t count=0;
for(count=0;count
{
if(HAL_I2C_Mem_Write(hi2c,DevAddress,MemAddress, MemAddSize,pData,1,Timeout)==HAL_OK)
{
MemAddress ++;
pData ++;
HAL_Delay(5);
}
else
{
printf("i2c write is error tn");
return HAL_ERROR;
}
}
return HAL_OK;
}
/*這里自己實現多字節的ATC02的讀操作*/
HAL_StatusTypeDef I2C_Read_Buffer(I2C_HandleTypeDef *hi2c,
uint16_t DevAddress, uint16_t MemAddress,
uint16_t MemAddSize, uint8_t *pData, uint16_t Size,
uint32_t Timeout)
{
uint16_t count=0;
for(count=0;count< Size;count ++)
{
if(HAL_I2C_Mem_Read(hi2c,DevAddress,MemAddress, MemAddSize,pData,1,Timeout)==HAL_OK)
{
MemAddress ++;
pData ++;
//HAL_Delay(5);
}
else
{
printf("i2c read is error n");
return HAL_ERROR;
}
}
return HAL_OK;
}
(4)在main函數中添加測試代碼:
uint16_t num_atc=0;
printf("this is test for I2C device read and write in ATC02rn");
printf("/**--------------------開始I2C-------------------------**/rn");
for( num_atc=0;num_atc
{
AT24_WriteBuffer[num_atc]=num_atc;
printf("0x%xt",AT24_WriteBuffer[num_atc]);
}
if(I2C_Write_Buffer(&AT_I2C,DEV_ADDR_ATC02, 0, I2C_MEMADD_SIZE_8BIT,AT24_WriteBuffer,ATC02_BufferSize, I2C_TIMEOUT) == HAL_OK)
{
printf("write i2c lots bytes is oktn");
}
if(HAL_I2C_Mem_Read(&AT_I2C,DEV_ADDR_ATC02, 0, I2C_MEMADD_SIZE_8BIT,AT24_ReadBuffer,ATC02_BufferSize,I2C_TIMEOUT)== HAL_OK)
{
printf("rn EEPROM 24C02 read data Test OK rn");
}
else
{
printf("rn EEPROM 24C02 read data Test False rn");
}
/*這里使用自定義多字節讀函數也是正常的*/
/*
if(I2C_Read_Buffer(&AT_I2C,DEV_ADDR_ATC02, 0, I2C_MEMADD_SIZE_8BIT,AT24_ReadBuffer,ATC02_BufferSize,I2C_TIMEOUT)== HAL_OK)
{
printf("i2c read lots is oktn");
}
*/
for(num_atc=0; num_atc< ATC02_BufferSize; num_atc++)
{
printf("0x%xt",AT24_ReadBuffer[num_atc]);
}
if(memcmp(AT24_WriteBuffer,AT24_ReadBuffer,ATC02_BufferSize) == 0 ) /* check date */
{
printf("rn EEPROM 24C02 Read and write Test OKrn");
}
else
{
printf("rn EEPROM 24C02 Read and write Test Falsern");
}
printf("/**--------------------結束I2C-------------------------**/rn");
編譯上述程序后下載。
04第四節效果演示
使用串口觀察寫入的數據和讀出的數據是否一致?
可以看到I2C操作EEPROM進行讀寫都是正常的。
評論
查看更多