The i2c of stm32 is the slave mode by default. In this paper, we implement the receiving and sending of interrupt mode based on HAL library. First, we initialize gpio and i2c. The code is as follows:
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; //Open drain output (i2c requires this mode) 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; //Use i2c3 here I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; //7-bit address mode I2cHandle.Init.ClockSpeed = 1000000; //Clock support up to 1M I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; //Turn off dual address mode I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9; I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; I2cHandle.Init.OwnAddress1 = 0X34; //Device address I2cHandle.Init.OwnAddress2 = 0; if(HAL_I2C_Init(&I2cHandle) != HAL_OK) //Call initialization function { /* Initialization Error */ Error_Handler(); } HAL_I2C_Slave_Receive_IT(&I2cHandle,i2c_slave_recv,I2C_REC_BYTES); //Enable slave interrupt reception }
i2c3 interrupt callback function:
void I2C3_ER_IRQHandler() //Abnormal callback { HAL_I2C_ER_IRQHandler(&I2cHandle); } void I2C3_EV_IRQHandler() //Event callback (receive or send) { HAL_I2C_EV_IRQHandler(&I2cHandle); }
The interrupt events corresponding to the two interrupts are shown in the following figure:
Send complete, receive complete, and error callback functions:
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *I2cHandle) { //Send completion callback function { //Some other operations } HAL_I2C_Slave_Receive_IT(&I2cHandle,i2c_slave_recv,I2C_REC_BYTES); { //Some other operations } } void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle) { //Receive completion callback function { //Some other operations } HAL_I2C_Slave_Transmit_IT(&I2cHandle,send_buffer,send_cnt); { //Some other operations } } void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle) { //Error exception callback function }
In actual operation, data can be processed in the receiving completion interrupt and then the slave sending interrupt can be turned on. In the sending completion interrupt, the slave receiving interrupt can be turned on to realize the receiving and sending.
At present, if you want to send with HAL library, you have to send all the bytes of send ﹣ CNT. Otherwise, there will be problems in communication. This problem needs to be further solved.