×
单片机 > 单片机程序设计 > 详情

stm32的HAL库i2c从机实现

发布时间:2020-05-30 发布时间:
|

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的字节全部发送完成才行,不然通信会出问题。这个问题需要进一步解决。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
C51 特殊功能寄存器SFR的名称和地址