【stm32】f1的I2C

I2C_OneBoard_Communication_PollingAndIT

单板轮询发送带中断。初始化,三步,GPIO开启,I2C时钟引脚,I2C模式配置。Enable开启,init函数包含enable。两个例子。

cpp 复制代码
/**
  * @brief  This function configures I2C1 in Master mode.
  * @note   This function is used to :
  *         -1- Enables GPIO clock.
  *         -2- Enable the I2C1 peripheral clock and configures the I2C1 pins.
  *         -3- Configure I2C1 functional parameters.
  * @note   Peripheral configuration is minimal configuration from reset values.
  *         Thus, some useless LL unitary functions calls below are provided as
  *         commented examples - setting is default configuration from reset.
  * @param  None
  * @retval None
  */
void Configure_I2C_Master(void)
{
  LL_RCC_ClocksTypeDef rcc_clocks;

  /* (1) Enables GPIO clock  **********************/

  /* Enable the peripheral clock of GPIOB */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);

  /* (2) Enable the I2C1 peripheral clock *************************************/

  /* Enable the peripheral clock for I2C1 */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);

  /* Configure SCL Pin as : Alternate function, High Speed, Open drain, Pull up */
  LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_6, LL_GPIO_MODE_ALTERNATE);
  LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_6, LL_GPIO_SPEED_FREQ_HIGH);
  LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_6, LL_GPIO_OUTPUT_OPENDRAIN);
  LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_6, LL_GPIO_PULL_UP);

  /* Configure SDA Pin as : Alternate function, High Speed, Open drain, Pull up */
  LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_7, LL_GPIO_MODE_ALTERNATE);
  LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_7, LL_GPIO_SPEED_FREQ_HIGH);
  LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_7, LL_GPIO_OUTPUT_OPENDRAIN);
  LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_7, LL_GPIO_PULL_UP);

  /* (3) Configure I2C1 functional parameters ********************************/
  
  /* Disable I2C1 prior modifying configuration registers */
  LL_I2C_Disable(I2C1);
  
  /* Retrieve Clock frequencies */
  LL_RCC_GetSystemClocksFreq(&rcc_clocks);

  /* Configure the SCL Clock Speed */
  LL_I2C_ConfigSpeed(I2C1, rcc_clocks.PCLK1_Frequency, I2C_SPEEDCLOCK, I2C_DUTYCYCLE);
  }
void MX_I2C1_Init(void)
{
    /* USER CODE BEGIN I2C1_Init 0 */

    /* USER CODE END I2C1_Init 0 */

    LL_I2C_InitTypeDef I2C_InitStruct = {0};

    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
    /**I2C1 GPIO Configuration
    PB6   ------> I2C1_SCL
    PB7   ------> I2C1_SDA
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_6 | LL_GPIO_PIN_7;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
    LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* Peripheral clock enable */
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);

    /* USER CODE BEGIN I2C1_Init 1 */

    /* USER CODE END I2C1_Init 1 */

    /** I2C Initialization
     */
    LL_I2C_DisableOwnAddress2(I2C1);
    LL_I2C_DisableGeneralCall(I2C1);
    LL_I2C_EnableClockStretching(I2C1);
    I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
    I2C_InitStruct.ClockSpeed = 400000;
    I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_2;
    I2C_InitStruct.OwnAddress1 = 0;
    I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
    I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
    LL_I2C_Init(I2C1, &I2C_InitStruct);
}

master发送数据,其中有带timeout和不带的。ll库是纯纯发数据,关于目标地址的内存地址发送和正常发数据一样。这里给两个例子。内存地址8位还是16位,自己定义就是16位拆开先发送低位在发送高位,I2C_MEMADD_SIZE_8BIT这个是hal库定义实际值就是0x01和0x00,自己定义一个同样作用。

cpp 复制代码
/**
  * @brief  This Function handle Master events to perform a transmission process
  * @note  This function is composed in different steps :
  *        -1- Prepare acknowledge for Master data reception.
  *        -2- Initiate a Start condition to the Slave device.
  *        -3- Loop until Start Bit transmitted (SB flag raised).
  *        -4- Send Slave address with a 7-Bit SLAVE_OWN_ADDRESS for a write request.
  *        -5- Loop until Address Acknowledgement received (ADDR flag raised).
  *        -6- Clear ADDR flag and loop until end of transfer (ubNbDataToTransmit == 0).
  *             -6.1 Transmit data (TXE flag raised).
  *        -7- End of tranfer, Data consistency are checking into Slave process.
  * @param  None
  * @retval None
  */
void Handle_I2C_Master(void)
{
  /* (1) Prepare acknowledge for Master data reception ************************/
  LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
  
  /* (2) Initiate a Start condition to the Slave device ***********************/
  /* Master Generate Start condition */
  LL_I2C_GenerateStartCondition(I2C1);

  /* (3) Loop until Start Bit transmitted (SB flag raised) ********************/

#if (USE_TIMEOUT == 1)
  Timeout = I2C_SEND_TIMEOUT_SB_MS;
#endif /* USE_TIMEOUT */

  /* Loop until SB flag is raised  */
  while(!LL_I2C_IsActiveFlag_SB(I2C1))
  {
#if (USE_TIMEOUT == 1)
    /* Check Systick counter flag to decrement the time-out value */
    if (LL_SYSTICK_IsActiveCounterFlag()) 
    {
      if(Timeout-- == 0)
      {
        /* Time-out occurred. Set LED2 to blinking mode */
        LED_Blinking(LED_BLINK_SLOW);
      }
    }
#endif /* USE_TIMEOUT */
  }

  /* (4) Send Slave address with a 7-Bit SLAVE_OWN_ADDRESS for a write request */
    LL_I2C_TransmitData8(I2C1, SLAVE_OWN_ADDRESS | I2C_REQUEST_WRITE);

  /* (5) Loop until Address Acknowledgement received (ADDR flag raised) *******/

#if (USE_TIMEOUT == 1)
  Timeout = I2C_SEND_TIMEOUT_ADDR_MS;
#endif /* USE_TIMEOUT */

  /* Loop until ADDR flag is raised  */
  while(!LL_I2C_IsActiveFlag_ADDR(I2C1))
  {
#if (USE_TIMEOUT == 1)
    /* Check Systick counter flag to decrement the time-out value */
    if (LL_SYSTICK_IsActiveCounterFlag()) 
    {
      if(Timeout-- == 0)
      {
        /* Time-out occurred. Set LED2 to blinking mode */
        LED_Blinking(LED_BLINK_SLOW);
      }
    }
#endif /* USE_TIMEOUT */
  }

  /* (6) Clear ADDR flag and loop until end of transfer (ubNbDataToTransmit == 0) */

  /* Clear ADDR flag value in ISR register */
  LL_I2C_ClearFlag_ADDR(I2C1);

#if (USE_TIMEOUT == 1)
  Timeout = I2C_SEND_TIMEOUT_TXE_MS;
#endif /* USE_TIMEOUT */

  /* Loop until TXE flag is raised  */
  while(ubNbDataToTransmit > 0)
  {
    /* (6.1) Transmit data (TXE flag raised) **********************************/

    /* Check TXE flag value in ISR register */
    if(LL_I2C_IsActiveFlag_TXE(I2C1))
    {
      /* Write data in Transmit Data register.
      TXE flag is cleared by writing data in TXDR register */
      LL_I2C_TransmitData8(I2C1, (*pTransmitBuffer++));

      ubNbDataToTransmit--;

#if (USE_TIMEOUT == 1)
      Timeout = I2C_SEND_TIMEOUT_TXE_MS;
#endif /* USE_TIMEOUT */
    }

#if (USE_TIMEOUT == 1)
    /* Check Systick counter flag to decrement the time-out value */
    if (LL_SYSTICK_IsActiveCounterFlag()) 
    {
      if(Timeout-- == 0)
      {
        /* Time-out occurred. Set LED2 to blinking mode */
        LED_Blinking(LED_BLINK_SLOW);
      }
    }
#endif /* USE_TIMEOUT */
  }

  /* (7) End of tranfer, Data consistency are checking into Slave process *****/
  /* Generate Stop condition */
  LL_I2C_GenerateStopCondition(I2C1);

}
void oledMemWrite(I2C_TypeDef *I2Cx, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
{
    // 1. 生成起始条件
    LL_I2C_GenerateStartCondition(I2Cx);
    // 2. 等待总线就绪,准备发送从设备地址(写模式)
    while (!LL_I2C_IsActiveFlag_SB(I2Cx))
        ;
    // 3. 发送从设备地址(写模式:地址左移1位,最低位为0)
    LL_I2C_TransmitData8(I2Cx, (DevAddress << 1) | 0x00);
    // 4. 等待地址发送完毕并收到从设备的应答(ACK)
    while(!LL_I2C_IsActiveFlag_ADDR(I2Cx));
    LL_I2C_ClearFlag_ADDR(I2Cx);
    
    // 发送内存地址(根据MemAddSize决定发送几个字节)
    if(MemAddSize == I2C_MEMADD_SIZE_8BIT)
    {
        // 8位地址
        while(!LL_I2C_IsActiveFlag_TXE(I2Cx));
        LL_I2C_TransmitData8(I2Cx, (uint8_t)MemAddress);
    }
    else // 16位地址
    {
        // 高字节
        while(!LL_I2C_IsActiveFlag_TXE(I2Cx));
        LL_I2C_TransmitData8(I2Cx, (MemAddress >> 8) & 0xFF);
        
        // 低字节
        while(!LL_I2C_IsActiveFlag_TXE(I2Cx));
        LL_I2C_TransmitData8(I2Cx, MemAddress & 0xFF);
    }
    
    // 发送数据
    for (uint8_t i = 0; i < Size; i++)
    {
        // 等待上一个字节发送完成(TXE标志置1表示数据寄存器空,可写入新数据)
        while (!LL_I2C_IsActiveFlag_TXE(I2Cx))
            ;
        // 发送一个字节数据
        LL_I2C_TransmitData8(I2Cx, pData[i]);
    }
    // 6. 等待最后一个字节发送完成(BTF标志表示数据传输完成)
    while (!LL_I2C_IsActiveFlag_BTF(I2Cx))
        ;
    // 7. 生成停止条件
    LL_I2C_GenerateStopCondition(I2Cx);
}
相关推荐
不做无法实现的梦~11 小时前
ros2实现路径规划---nav2部分
linux·stm32·嵌入式硬件·机器人·自动驾驶
熊猫_豆豆15 小时前
同步整流 Buck 降压变换器
单片机·嵌入式硬件·matlab
chenchen0000000019 小时前
49元能否买到四核性能?HZ-RK3506G2_MiniEVM开发板评测:MCU+三核CPU带来的超高性价比
单片机·嵌入式硬件
孤芳剑影20 小时前
反馈环路设计总结
嵌入式硬件·学习
dump linux21 小时前
设备树子系统与驱动开发入门
linux·驱动开发·嵌入式硬件
专注VB编程开发20年21 小时前
简易虚拟 PLC 服务器-流水线自动化,上位机程序维护升级,西门子PLC仿真
服务器·单片机·自动化·上位机·plc·流水线·工控
LeoZY_21 小时前
CH347/339W开源项目:集SPI、I2C、JTAG、SWD、UART、GPIO多功能为一体(3)
stm32·单片机·嵌入式硬件·mcu·开源
chenchen000000001 天前
国产显示芯势力新篇章:内置DDR+四核A35!MY-SSD2351-MINI开发板深度评测
驱动开发·嵌入式硬件
BackCatK Chen1 天前
第13篇:TMC2240 StallGuard4失速检测|寄存器配置+状态读取(保姆级)
单片机·嵌入式硬件·tmc2240·stm32实战·stallguard4·失速检测·电机故障识别
Hello_Embed1 天前
libmodbus STM32 板载串口实验(双串口主从通信)
笔记·stm32·单片机·学习·modbus