You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino向STM32通过I2C传输数组或整数时遇到问题

Arduino(从机)与STM32(主机HAL库)I2C通信异常问题

现状与问题

  • STM32作为I2C主机,向Arduino从机发送整数、整数数组、uint8_t字符串数组均正常,可通过UART终端验证接收结果。
  • STM32接收Arduino发送的String类型数据正常(Arduino端需用Wire.write(Message.c_string()))。
  • 异常情况:
    • 接收Arduino发送的单个整数时,STM32的UART终端无任何输出。
    • 接收Arduino发送的整数数组时,终端显示与数组长度一致的不可见字符,确认有数据接收,但无法判断是数据错误还是显示方式问题。

STM32端main函数代码(UART、I2C配置已确认正确)

/* On STM32. I'm just sharing the main function to avoid to flood the topic. Please be assured that all the other stuff, as UART or I2C configuration, is done properly*/

int main(void)
{
    HAL_StatusTypeDef retour_i2c;

    uint8_t message_envoye[] = "Hello World !!";
    uint8_t entier_envoye = 32;
    uint8_t tableau_envoye[] = {1, 2, 3, 4};

    uint8_t message_recu[10];
    uint8_t entier_recu;
    uint8_t tableau_recu[4]; // My Arduino is sending an array of 4 integers

  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_I2C1_Init();

  I2C_Verif_Addresses();

  while (1)
  {
      // Transmition part is OK
      retour_i2c = HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)(I2C_SLAVE_ADDR << 1), tableau_envoye, sizeof(tableau_envoye), 1000);
      if(retour_i2c != HAL_OK){
          I2C_Error_Handler(&hi2c1);
      }
      else{
          HAL_Delay(1000);
          HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
      }


      // Reception part is not OK
      // retour_i2c = HAL_I2C_Master_Receive(&hi2c1, (uint16_t)(I2C_SLAVE_ADDR << 1), message_recu, sizeof(message_recu), 1000); // "strings" are working
      retour_i2c = HAL_I2C_Master_Receive(&hi2c1, (uint16_t)(I2C_SLAVE_ADDR << 1), tableau_recu, sizeof(tableau_recu), 1000); // Receiving an array cause invisible characters to be printed
      // retour_i2c = HAL_I2C_Master_Receive(&hi2c1, (uint16_t)(I2C_SLAVE_ADDR << 1), entier_recu, sizeof(entier_recu), 1000);
      if(retour_i2c != HAL_OK){
          I2C_Error_Handler(&hi2c1);
      }
      else{
          HAL_Delay(1000);
          HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
          HAL_UART_Transmit(&huart2, tableau_recu, sizeof(tableau_recu), 10);
      }
  }
}

问题原因及解决办法

核心原因:参数传递错误 + 终端显示逻辑偏差

  1. 整数/数组显示为不可见字符的原因
    你用HAL_UART_Transmit直接发送uint8_t类型的整数/数组,终端会把这些数值当作ASCII码解析。比如数值1对应ASCII控制字符SOH,数值2对应STX,这类字符本身不可见,所以终端显示空白或乱码。而字符串能正常显示,是因为字符串元素都是可见字符的ASCII码。

  2. 接收单个整数无反应的原因
    看注释掉的接收代码:retour_i2c = HAL_I2C_Master_Receive(&hi2c1, ..., entier_recu, sizeof(entier_recu), 1000);
    这里犯了参数传递错误:HAL_I2C_Master_Receive的第三个参数需要指针类型(内存地址),你直接传了entier_recu(变量值),而非&entier_recu(变量地址)。这会导致I2C接收时写入错误内存区域,要么程序异常,要么没接收到正确数据,所以终端无输出。

解决步骤

  • 修复单个整数接收的参数错误
    修改接收代码为:

    retour_i2c = HAL_I2C_Master_Receive(&hi2c1, (uint16_t)(I2C_SLAVE_ADDR << 1), &entier_recu, sizeof(entier_recu), 1000);
    
  • 正确显示整数/数组数据
    不能直接把数值通过UART发送给终端,需先将数值转换为ASCII字符串再发送。可以用标准库sprintf实现:
    数组显示示例:

    else{
        HAL_Delay(1000);
        HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
        // 转换数组为字符串后发送
        char uart_buf[50] = {0};
        int len = sprintf(uart_buf, "Received array: %d, %d, %d, %d\r\n", tableau_recu[0], tableau_recu[1], tableau_recu[2], tableau_recu[3]);
        HAL_UART_Transmit(&huart2, (uint8_t*)uart_buf, len, 10);
    }
    

    单个整数显示示例:

    char uart_buf[20] = {0};
    int len = sprintf(uart_buf, "Received integer: %d\r\n", entier_recu);
    HAL_UART_Transmit(&huart2, (uint8_t*)uart_buf, len, 10);
    
  • 确认Arduino端发送逻辑
    确保Arduino端按字节发送数值本身,而非转换为字符串。比如发送数组的代码:

    int data[] = {1,2,3,4};
    Wire.write((uint8_t*)data, sizeof(data));
    

    发送单个整数的代码:

    int num = 100;
    Wire.write((uint8_t*)&num, sizeof(num));
    

    注意:若Arduino发送的是16位int类型,STM32端需用对应长度的变量(如uint16_t)接收,避免数据截断。


内容的提问来源于stack exchange,提问作者Tsu'Na

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:59:51