
導語“本次 教程使用CubeMx配置I2C進行I2C總線設(shè)備的數(shù)據(jù)讀寫操作,使用EEPROM作為實驗對象”
(資料圖片)
?硬件
野火指南者開發(fā)板
?軟件
CubeMx & MDK & 串口調(diào)試助手
?原理圖
我們可以從原理圖中得到使用的I2C1,AT24C02的設(shè)備地址的第三位是000,容量是256個字節(jié)。設(shè)備地址從下圖得到:
不帶讀寫方向的使用左移得到的地址為0b10100000->0xA0, 讀地址為:0xA1,寫地址為0xA0;
注意:(1) 操作ATC02的時候,多字節(jié)寫入的時候沒寫入一個字節(jié),延時最小5ms, 多字節(jié)讀的時候沒有要求,頁寫入的時候每8個字節(jié)為一頁,共32頁。
我們依然使用之前的USART的項目,在此基礎(chǔ)上進行I2C的配置,串口的使用是進行EEPROM讀寫數(shù)據(jù)顯示在控制臺上,使用CubeMx進行I2C的配置:
I2C的配置很簡單,完成上述配置后生成代碼。
使用MDK打開CubeMx生成的代碼進行應用代碼編寫。
(1)在main.c 中進行AT24C02的相關(guān)宏定義和變量定義:
#define ADDR_AT24C_Write0xA0#define ADDR_AT24C_Read 0xA1#define DEV_ADDR_ATC02 0xA0 //0x50 左移得到的。#define ATC02_BufferSize 256 // 256#define I2C_TIMEOUT 0xFF#define AT_I2C hi2c1uint8_t AT24_WriteBuffer[ATC02_BufferSize],AT24_ReadBuffer[ATC02_BufferSize];
( 2 ) 應用函數(shù)申明:
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()是自定義的任意字節(jié)寫入I2C-AT24C02的函數(shù),I2CReadBuffer()是任意字節(jié)讀寫函數(shù)。這兩個函數(shù)的實現(xiàn)采用HAL庫的這兩個函數(shù):
1)HALStatusTypeDef HALI2CMemWrite(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress, uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);
參數(shù)依次是:(I2C句柄,AT24C02的設(shè)備地址,設(shè)備中數(shù)據(jù)地址,數(shù)據(jù)地址的大小,寫的數(shù)據(jù),數(shù)據(jù)大小,超時時間)
2)HALStatusTypeDef HALI2CMemRead(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress, uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);
參數(shù)依次是:(I2C句柄,AT24C02的設(shè)備地址,設(shè)備中數(shù)據(jù)地址,數(shù)據(jù)地址的大小,讀出數(shù)據(jù),數(shù)據(jù)大小,超時時間)
為什么不直接使用庫函數(shù)呢?是因為在測試中AT24C02讀寫不正常,查看AT24C02的手冊發(fā)現(xiàn),單個字節(jié)寫入沒問題,多字節(jié)的寫入需要每個字節(jié)延時5ms, 其實多字節(jié)的讀沒有問題,這個從新實現(xiàn)了下。可以連續(xù)8個字節(jié)的頁寫入,這個不需要延時。
(3)多字節(jié)的讀寫函數(shù):
/*這里自己實現(xiàn)多字節(jié)的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;}/*這里自己實現(xiàn)多字節(jié)的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函數(shù)中添加測試代碼:
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"); }/*這里使用自定義多字節(jié)讀函數(shù)也是正常的*//* 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("/**--------------------結(jié)束I2C-------------------------**/rn");
編譯上述程序后下載。
使用串口觀察寫入的數(shù)據(jù)和讀出的數(shù)據(jù)是否一致?
可以看到I2C操作EEPROM進行讀寫都是正常的。
標簽: