STM32CubeIDE HAL库操作IIC (一)配置篇

本文深入解析IIC通信的三种方式:轮询、中断和DMA,提供了详细的HAL库函数使用示例,包括错误处理和状态检查。同时,文章还介绍了如何通过IIC总线对从设备的寄存器进行读写操作,适用于SHT21、MPU6050、AT24C02等设备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、MX配置

使能中断(可选):

DMA设置(可选):

二、生成的代码

三、IIC通信的三种方式(Polling、IT、DMA)(代码源自官方例程)

1、Polling (常用)

2、IT(开启中断,接收到数据时会调用回调函数)

3、DMA模式(回调函数同中断)

四、对IIC从设备的寄存器操作(适用于SHT21、MPU6050、AT24C02等)


一、MX配置

标准模式,100KHz时钟,7位地址

 

使能中断(可选):

DMA设置(可选):

 

二、生成的代码

初始化函数

底层初始化

确定了引脚为开漏模式、时钟、DMA以及开启EV中断。

三、IIC通信的三种方式(Polling、IT、DMA)(代码源自官方例程)

1、Polling (常用)

//主机模式发送  
/* Timeout is set to 10S */
  while(HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 10000)!= HAL_OK)
  {
    /* Error_Handler() function is called when Timeout error occurs.
       When Acknowledge failure occurs (Slave don't acknowledge its address)
       Master restarts communication */
    if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
    {
      Error_Handler();
    }
  }

//主机模式接收
/* Timeout is set to 10S */ 
  while(HAL_I2C_Master_Receive(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t *)aRxBuffer, RXBUFFERSIZE, 10000) != HAL_OK)
  {
    /* Error_Handler() function is called when Timeout error occurs.
       When Acknowledge failure occurs (Slave don't acknowledge it's address)
       Master restarts communication */
    if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
    {
      Error_Handler();
    }
  }

//从机模式接收
/* Timeout is set to 10S  */
  if(HAL_I2C_Slave_Receive(&hi2c1, (uint8_t *)aRxBuffer, RXBUFFERSIZE, 10000) != HAL_OK)
  {
    /* Transfer error in reception process */
    Error_Handler();
  }
  
//从机模式发送
  /* Timeout is set to 10S */
  if(HAL_I2C_Slave_Transmit(&hi2c1, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 10000)!= HAL_OK)
  {
    /* Transfer error in transmission process */
    Error_Handler();    
  }

//错误回调函数
/**
  * @brief  I2C error callbacks.
  * @param  I2cHandle: I2C handle
  * @note   This example shows a simple way to report transfer error, and you can
  *         add your own implementation.
  * @retval None
  */
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle)
{
  //
}

2、IT(开启中断,接收到数据时会调用回调函数)

//主机模式中断发送
/* While the I2C in reception process, user can transmit data through 
    "aTxBuffer" buffer */
    if(HAL_I2C_Master_Transmit_IT(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
    {
      /* Error_Handler() function is called in case of error. */
      Error_Handler();
    }
/*##-3- Wait for the end of the transfer ###################################*/
while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
    {
    }

//主机模式中断接收
if(HAL_I2C_Master_Receive_IT(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
    {
      /* Error_Handler() function is called in case of error. */
      Error_Handler();
    }

//主机模式发送回调函数
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
//
}
//主机模式接收回调函数
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
//
}

//从机模式中断接收
 if(HAL_I2C_Slave_Receive_IT(&hi2c1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
  {
    /* Transfer error in reception process */
    Error_Handler();
  }
  
  /*##-3- Wait for the end of the transfer ###################################*/  
  while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
  {
  }

//从机模式中断发送
  /*##-4- Start the transmission process #####################################*/  
  /* While the I2C in reception process, user can transmit data through 
     "aTxBuffer" buffer */
if(HAL_I2C_Slave_Transmit_IT(&hi2c1, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
  {
    /* Transfer error in transmission process */
    Error_Handler();    
  }


//从机模式发送回调函数
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
//
}
//从机模式接收回调函数
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
//
}

3、DMA模式(回调函数同中断)

//主机模式DMA发送
while(HAL_I2C_Master_Transmit_DMA(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
  {
    if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
    {
      Error_Handler();
    }
  }
  /*##-3- Wait for the end of the transfer ###################################*/  
  while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY);

//主机模式DMA接收
while(HAL_I2C_Master_Receive_DMA(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
  {
    if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
    {
      Error_Handler();
    }
  }

//从机模式DMA发送
  if(HAL_I2C_Slave_Receive_DMA(&hi2c1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
  {

    Error_Handler();
  }
  while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY);
//从机模式DMA接收
  if(HAL_I2C_Slave_Transmit_DMA(&hi2c1, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
  {
    /* Transfer error in transmission process */
    Error_Handler();    
  }
  while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY);

四、对IIC从设备的寄存器操作(适用于SHT21、MPU6050、AT24C02等)

下面对库函数的操作做了一次封装,函数前还可以加上 __STATIC_INLINE

I2C_Addr 器件地址,例如MPU6050为0xd0

reg 寄存器地址,例如陀螺仪配置寄存器 0x1B

data 操作数,例如操作陀螺仪配置寄存器数值0x18,开启满量程

*buf 读取数存储地址指针

uint8_t HALIIC_WriteByteToSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t data)
{
  uint8_t  *pData;
  pData = &data;
  return HAL_I2C_Mem_Write(&hi2c1, I2C_Addr, reg, I2C_MEMADD_SIZE_8BIT, pData, 1, 100);
}
uint8_t HALIIC_ReadByteFromSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t *buf)
{
  return HAL_I2C_Mem_Read(&hi2c1, I2C_Addr, reg, I2C_MEMADD_SIZE_8BIT, buf, 1, 100);
}

uint8_t HALIIC_ReadMultByteFromSlave(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data)
{
  return HAL_I2C_Mem_Read(&hi2c1, dev, reg, I2C_MEMADD_SIZE_8BIT, data, length, 200);
}
uint8_t HALIIC_WriteMultByteToSlave(uint8_t dev, uint8_t reg, uint8_t length, uint8_t* data)
{
  return HAL_I2C_Mem_Write(&hi2c1, dev, reg, I2C_MEMADD_SIZE_8BIT, data, length, 200);
}

 

### STM32CubeIDE 使用 HAL 驱动 OLED 教程 #### 初始化项目并配置硬件资源 为了在STM32CubeIDE中使用HAL驱动OLED屏,首先需要创建个新的STM32工程,并通过STM32CubeMX工具配置所需的外设。对于0.96寸OLED屏幕而言,通常会涉及到SPI或IIC通信接口的选择[^1]。 #### 安装必要的软件包和文件 确保安装了最新的STM32Cube固件包以及任何特定于目标MCU系列的支持包。如果要支持中文字符显示,则可能还需要额外下载字体或其他相关资源[^4]。 #### 编写初始化函数 下面是个简单的C语言代码片段用于初始化OLED设备: ```c #include "main.h" #include "ssd1306.h" void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void){ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); SSD1306_Init(); // 初始化OLED while (1){ // 主循环体可以放置其他任务逻辑 } } ``` 此部分代码展示了如何调用`SSD1306_Init()`来完成显示器的基本设置工作。 #### 显示测试图案或文字 旦完成了上述准备工作之后就可以尝试向屏幕上输出些简单的内容来进行验证了。这里给出段用来打印字符串到指定位置的例子: ```c char *str = "Hello World!"; SSD1306_SetCursor(0, 0); // 设置光标位置为左上角 SSD1306_WriteString(str, Font_7x10, White); // 输出白色的文字 SSD1306_UpdateScreen(); // 刷新整个画面缓冲区至实际可见区域 ``` 这段程序将会把“Hello World!”这几个字以7×10大小的英文字体呈现在屏幕顶部中央附近的位置。 #### 支持多国语言包括中文 为了让OLED能够正确渲染汉字等复杂字符集,除了基本图形绘制功能之外还需引入相应的编码表数据结构及其解析算法。这往往意味着开发者得自己实现套适合应用场景需求的文字处理机制或者是寻找现成开源解决方案集成进来。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值