Inter-Integrated Circuit(I2C)
大綱
以下文章主要以I2C master為出發,如果是要尋找I2C slave 可點擊右邊文章
- 硬體Nucleo-F401RE(STM32F401RE)
- STM32CubeMx軟體設置
- IDE: STM32CubeIDE
- STM32F1xx/STM32F4xxHAL庫
- IIC:硬件硬件IIC1
I2C的物理層
I2C傳輸數據線=> SDA數據線:時鐘 Ref:《IIC原理超詳細講解—值得一看》
Ps:的理論理想傳輸距離為通信,用於由於乾擾和傳輸速度的提高,實際上的IC只有15M遠,一般適合板極器件,不適合中長距離的通信
本題STM32與硬體須注意事項
I2C數據傳輸
IIC的每一天偵查數據由9bit組成
如果是發送數據 8bit data+1bit ACK
如果是設備地址數據則8bit包含7bit設備地址+1bit方向
數據是由為一組而傳輸的,因此需要額外發送8位傳感器或應用程序體去設置接收設置
PS:因傳輸訊號為先傳輸數據為雙線結構,所以傳輸數據發送端:地址(8bit)+數據(8bit)
STM32CubeMX I2C設定
Ref:【STM32】HAL庫STM32CubeMX教程十二—IIC(讀取AT24C02)
PS:共用Clock是需要盡可能避免的,因為會出現時序互相干擾現象,如需在使用時必須排好時間流程序
最後是轉出STM32cubeIDE可編輯的程式碼
I2C 程式撰寫
HAL_I2C_Mem_Write
HAL_I2C_Mem_Read
uint8_t read_register(uint8_t Sensor_register)
{
HAL_StatusTypeDef status = HAL_OK;
uint8_t return_value = 0;
status = HAL_I2C_Mem_Read(&hi2c1,Devadress,Sensor_register, I2C_MEMADD_SIZE_8BIT, &return_value, 1, 100);
HAL_Delay(10);
/* Check the communication status */
if(status != HAL_OK)
{
printf("I2C read status error =%#x \n\r",status);
/*
HAL_ERROR = 0x01U,
HAL_BUSY = 0x02U,
HAL_TIMEOUT = 0x03U
*/
}
return return_value;
};
void write_register(uint8_t Sensor_register, uint8_t register_value)
{
HAL_StatusTypeDef status = HAL_OK;
status = HAL_I2C_Mem_Write(&hi2c1, Devadress, Sensor_register, I2C_MEMADD_SIZE_8BIT, ®ister_value,1, 100);
HAL_Delay(10);
/* Check the communication status */
if(status != HAL_OK)
{
printf("I2C write status error =%#x \n\r",status);// Error handling, for example re-initialization of the I2C peripheral
}
}
另外也有以下4種Function可以使用
- HAL_I2C_Mem_Write_IT
- HAL_I2C_Mem_Read_IT
- HAL_I2C_Mem_Write_DMA
- HAL_I2C_Mem_Read_DMA
- 其中IT的使用要注意Clock流程序是否會出現打結現象
- DMA的話是必須知道資料長度,如果不知道資料長度會導致程式錯誤
- HAL_I2C_Master_Transmit/Receive基本上使用差不多
I2C傳輸失敗
- 事先確認是否有加外加電阻
- 第二部份最常錯的就是adress錯誤
針對第2點可以使用以下程式去解
void Scan_i2c_bus_device(void)
{
int status;
int i;
int u8GetDevCnt;
unsigned char u8data[2];
printf("Start Scan:\r\n");
u8GetDevCnt=0;
for(i=0;i<0xfe;i=i+2)
{
status = HAL_I2C_Master_Receive(&hi2c1,(uint16_t)(i), &u8data[0], 1, 10000);
if(status==HAL_OK)
{
printf("get device on slave addr=0x%x\r\n",i);
u8GetDevCnt++;
}
HAL_Delay(10);
}
printf("Scan get =%d device\r\n",u8GetDevCnt);
printf("Scan Done!\r\n");
}
Pingback: Pull-up Resistors For I2C Bus - AMS and STM32
Pingback: I2C Slave mode on STM32 Introduction - AMS and STM32