linux i2c dev.h freq,STM32F103ZET(基于秉火开发板)+Cubemx(F1 V1.60库)+IIC+AT24C02(修复官方例程读写死机bug)...
首先說明下開發條件:
1、開發板:秉火霸道,STM32F103ZET
2、軟件:Cubemx V4.23(F1 V1.60庫)
3、硬件:AT24C02 256KByte
問題描述:Cubemx生成IIC代碼會出現死機問題,或者壓根運行不了!
問題原因:
1、ST為了規避飛利浦IIC專利問題,將STM32的硬件IIC設計的比較復雜,而且穩定性不怎么好,所以一般教程都不推薦使用。
2、Cubemx生成的代碼有Bug!
解決辦法:
1、設置
2、IIC的回調函數里面需要將時鐘初始化放在引腳初始化之前!
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
__HAL_RCC_I2C1_CLK_ENABLE(); //默認生成的放在了引腳初始化后面!
/* USER CODE END I2C1_MspInit 0 */
/**I2C1 GPIO Configuration
PB6 ? ? ------> I2C1_SCL
PB7 ? ? ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
3、函數的具體應用需要結合AT24C02的數據手冊,符合AT24C02的要求!
我們在讀寫IIC時,即使不知道IIC的協議是什么,直接調用 HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) 這個函數就可以對IIC的設備進行讀寫,這就是Cubemx的優勢!
我先解釋下這個函數里面的幾個變量:
I2C_HandleTypeDef *hi2c IIC的句柄
uint16_t DevAddress IIC設備的外部地址
uint16_t MemAddress?IIC設備的內部地址
uint16_t MemAddSize 讀寫內部地址的方式,一般使用I2C_MEMADD_SIZE_8BIT方式
注意只有兩種選擇:I2C_MEMADD_SIZE_8BIT 或者 I2C_MEMADD_SIZE_16BIT
uint8_t *pData 寫入的數組或者指針
uint16_t Size 寫入的字節數!
注意:如果是AT24C02,這個字節數不能超過8!!!!!這也叫AT24C02的頁寫入!當然這是為了提高速度,如果你想不出錯也不在乎速度,你可以將字節數設置為1,這樣肯定不會出錯!
????uint32_t Timeout 時間超時
4、程序實現
注意:需要在寫函數后面加入短延時!
uint8_t I2c_Buf_Write[256];
uint8_t I2c_Buf_Read[256];
uint8_t I2C_Test(void)
{
uint16_t i;
i2cStatus=HAL_I2C_IsDeviceReady(&hi2c1, 0xA0, 256, 1000); ?//0表示ready
printf("i2cStatus = %d\r\n ", i2cStatus);
i2cStatus1=HAL_I2C_GetState(&hi2c1);//32表示ready ?HAL_I2C_STATE_READY ?= 0x20U, ? /*!< Peripheral Initialized and ready for use ?*/
printf("i2cStatus1 = %d\r\n ", i2cStatus1);
printf("寫入的數據\n\r");
for ( i=0; i<256; i++ ) //填充緩沖
{
I2c_Buf_Write[i] = i;
HAL_I2C_Mem_Write(&hi2c1, (uint16_t)EEPROM_Block0_ADDRESS, i, I2C_MEMADD_SIZE_8BIT, (uint8_t*)(&(I2c_Buf_Write[i])), 1, 10000);//一個字節一個字節寫,如果需要頁寫入(不超過8),使用40行的函數
// HAL_I2C_Mem_Write(&hi2c1, (uint16_t)EEPROM_Block0_ADDRESS, 0x00, I2C_MEMADD_SIZE_8BIT,(uint8_t*)I2c_Buf_Write, 8, 10000);//不能超過8個字節,如果超過需要分開寫,for循環里面改為i=i+8
printf("0xX ", I2c_Buf_Write[i]);
HAL_Delay(5);//不能少
}
EEPROM_INFO("\n\r寫成功\n\r");
HAL_Delay(500);
EEPROM_INFO("\n\r讀出的數據\n\r");
//將EEPROM讀出數據順序保持到I2c_Buf_Read中
//if(HAL_I2C_GetState(&hi2c1) == 0x20 ) //加入檢測
if( HAL_I2C_IsDeviceReady(&hi2c1, 0xA0, 256, 1000) == HAL_OK)//另外一種檢測方法
{
HAL_I2C_Mem_Read(&hi2c1, (uint16_t)(EEPROM_Block0_ADDRESS+1 ),0x00, I2C_MEMADD_SIZE_8BIT,(uint8_t *)I2c_Buf_Read, 256, 10000); //讀對字節數沒有限制
}
//將I2c_Buf_Read中的數據通過串口打印
for (i=0; i<256; i++)
{
printf("0xX ", I2c_Buf_Read[i]);
if(I2c_Buf_Read[i] != I2c_Buf_Write[i])
{
EEPROM_ERROR("0xX ", I2c_Buf_Read[i]);
EEPROM_ERROR("錯誤:I2C EEPROM寫入與讀出的數據不一致\n\r");
return 0;
}
}
EEPROM_INFO("I2C(AT24C02)讀寫測試成功\n\r");
return 1;
}
5、聯系方式:微信Startingray,本人準備將cubemx的小bug解決的過程記錄下來,也是給愛好者一點啟示,歡迎微信和我溝通,共同進步!個人覺得Cubemx是未來的發展方向,可以使我們避免很多小錯誤,但是由于現在軟件版本之間的兼容性,加上不同版本庫之間存在的bug,還是需要我們在使用時時刻保持警惕!
2020.08.22重新學習記錄:
1、開發板:秉火霸道,STM32F103ZET
2、軟件:Cubemx V6.01(F1 V1.80庫)
還有IIC的7bit地址是0x50,但是調用的函數需要的是8bit表示的這個地址應該是0xA0
很遺憾IIC的BUG還存在,而且如果使用FSMC的時候,IIC的配置會影響FSMC,兩者一起用的時候要注意。
總結
以上是生活随笔為你收集整理的linux i2c dev.h freq,STM32F103ZET(基于秉火开发板)+Cubemx(F1 V1.60库)+IIC+AT24C02(修复官方例程读写死机bug)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 巨量算数data解密
- 下一篇: linux 移动硬盘 machine,M