stm32的HAL庫i2c從機實現
阿新 • • 發佈:2019-01-23
stm32的i2c預設就是slave模式,本文基於HAL庫實現中斷方式的接收和傳送,首先是初始化gpio和i2c,程式碼如下:
I2C_HandleTypeDef I2cHandle; void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE() ; __HAL_RCC_GPIOC_CLK_ENABLE() ; /**I2C3 GPIO Configuration PA8 ------> I2C3_SCL PC9 ------> I2C3_SDA */ GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; //開漏輸出(i2c需要這種模式) GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C3; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C3; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* Peripheral clock enable */ __HAL_RCC_I2C3_CLK_ENABLE(); /* Peripheral interrupt init */ HAL_NVIC_SetPriority(I2C3_EV_IRQn, 0, 0); HAL_NVIC_EnableIRQ(I2C3_EV_IRQn); HAL_NVIC_SetPriority(I2C3_ER_IRQn, 0, 0); HAL_NVIC_EnableIRQ(I2C3_ER_IRQn); } void I2c_config() { I2cHandle.Instance = I2C3; //此處使用i2c3 I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; //7位地址模式 I2cHandle.Init.ClockSpeed = 1000000; //時鐘支援最高1M I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; //關閉雙地址模式 I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9; I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; I2cHandle.Init.OwnAddress1 = 0X34; //器件地址 I2cHandle.Init.OwnAddress2 = 0; if(HAL_I2C_Init(&I2cHandle) != HAL_OK) //呼叫初始化函式 { /* Initialization Error */ Error_Handler(); } HAL_I2C_Slave_Receive_IT(&I2cHandle,i2c_slave_recv,I2C_REC_BYTES); //開啟從機中斷接收 }
i2c3中斷回撥函式:
void I2C3_ER_IRQHandler() //異常回調
{
HAL_I2C_ER_IRQHandler(&I2cHandle);
}
void I2C3_EV_IRQHandler() //事件回撥(接收或傳送)
{
HAL_I2C_EV_IRQHandler(&I2cHandle);
}
兩個中斷對應的中斷事件如下圖所示:
傳送完成、接收完成和錯誤回撥函式:
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *I2cHandle) { //傳送完成回撥函式 { //一些其他操作 } HAL_I2C_Slave_Receive_IT(&I2cHandle,i2c_slave_recv,I2C_REC_BYTES); { //一些其他操作 } } void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle) { //接收完成回撥函式 { //一些其他操作 } HAL_I2C_Slave_Transmit_IT(&I2cHandle,send_buffer,send_cnt); { //一些其他操作 } } void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle) { //錯誤異常回調函式 }
實際操作時可以在接收完成中斷中處理資料然後開啟從機發送中斷,在傳送完成中斷中開啟從機接收中斷,可以實現收發。
目前用HAL庫傳送必須將send_cnt的位元組全部發送完成才行,不然通訊會出問題。這個問題需要進一步解決。