stm32L0使用arduino

絮絮叨叨:
在做一个无线姿态传感器的小项目时,看中了 arduino 强大的第三方库,于是选型使用了 arduino 进行开发。
可是在第一步时就踩坑了。。。。

问题简述

我硬件使用 STM32L051K8U6 + NRF24L01 + MPU6050,准备用来做一个无线的姿态传感器。

在使用 arduino 对 stm32 时,烧录的 Demo 程序没有任何反应,而使用之前 keil 编译的程序则可以正常运行。

在简化程序后,发现 LED 可以正常运行,但是串口不能工作。于是开始排查问题

问题排查

在我使用 STM32F103C8T6 烧录相同的 Demo 程序后,可以正常运行。于是问题被锁定在 STM32L051 上。

串口波特率异常

在测试时,发现 L051 的板子,LED 可以运行,但是串口不能接受数据,于是首先怀疑波特率是否正确。但是手头暂时没有逻辑分析仪,只能通过软件测试。

使用 Keil 配置工程测试,串口 TX、RX 接线正常,芯片功能正常。由于我使用内部时钟源,而 F103 板子使用外部晶振,于是开始确认系统时钟频率是否正确。

好在 arduino 中可以直接使用 HAL 库的函数, 调用 HAL_RCC_GetSysClockFreq 函数读取判断系统时钟。

#define LED PB3
int ms = 200;
uint32_t sysclock = 0;

void setup() {
  sysclock = HAL_RCC_GetSysClockFreq();
  if (sysclock == 32000000){
    ms = 1000;
  }

  pinMode(LED, OUTPUT);
  Serial.begin(115200);
  Serial.println("system init\n");
}

void loop() {
  digitalWrite(LED, HIGH);
  delay(ms);
  digitalWrite(LED, LOW);
  delay(ms);
}

经过测试,芯片的时钟配置也是正常,此路不通。。

串口配置

在检查时钟正常后,开始怀疑串口配置是否正常。于是修改默认串口 SerialSerial1 编译失败,提示未定义引用。

修改为 Serial2 ,串口同样无输出。。。

既然可以使用 HAL 库进行配置,那就使用 HAL 库初始化串口,进行测试,失败。。。

在使用 HAL 库配置完串口后顺手使用 HAL 库的串口发送函数进行测试。

HAL_UART_Transmit(&huart1, (uint8_t *)"hello\n", 6, 1000 );

竟然可以用?!!!

arduino 移植调试

于是问题确认在 arduino 内部的代码中,奈何在 arduino 中无法进行调试,于是尝试将 arduino 的代码移植到 makefile 中编译,方便进行调试。

不过之前也移植过,这个好说,然后开始各种折腾,离初始目标越来越远。。。

在移植 arduino 到 makefile 的过程中,想到查看一下符号表,只需要把用到的文件进行编译调试即可。

于是 objdump 查看了一下,在查看符号表的时候发现一个奇怪的问题,引起我的注意:

在符号表中出现的怎么都是 Serial2 的配置,没有关于 ``````Serial1 的初始化,所以 Serial 的宏是指向 Serial2 ?

于是查看了一下 variant 中 IO 的配置,不看不知道,一看吓一跳。。。。

// UART Definitions
#ifndef SERIAL_UART_INSTANCE
  #define SERIAL_UART_INSTANCE  2
#endif

// Default pin used for generic '```Serial```' instance
// Mandatory for Firmata
#ifndef PIN_SERIAL_RX
  #define PIN_SERIAL_RX         PA3
#endif
#ifndef PIN_SERIAL_TX
  #define PIN_SERIAL_TX         PA2
#endif

在配置文件中赤裸裸的使用着串口2 🤦‍♂️

问题解决

找到问题后,就很好解决了。既然 Serial 使用的是 Serial2 ,那我初始化 Serial1 然后将这个宏重新定义到 Serial1 不就解决问题了。

上面的代码变为:

#undef Serial
#define Serial Serial1
HardwareSerial Serial(USART1);

#define LED PB3
int ms = 200;

void setup() {
  pinMode(LED, OUTPUT);
  Serial.begin(115200);
  Serial.println("system init");
}

void loop() {
  digitalWrite(LED, HIGH);
  delay(ms);
  digitalWrite(LED, LOW);
  delay(ms);
}

下载运行,完美解决~

复盘分析

其实在最开始在怀疑串口配置的时候,已经想到了是否是串口号配置不对,而且编译报错信息已经提示了 Serial1 未定义,只是在当时未引起注意。

在经过一番折腾后,发现还是串口号配置错误导致的。

在 debug 的过程中应该本着 “大胆假设,小心求证” 的心态去排查问题。

虽然分析问题时想到这个原因,但是在求证的过程中却忽略了这个重要信息,导致后面走了不少弯路。

如果这是一个复杂代码的 debug , 同样不能运行调试,那问题应该怎么被发现解决呢?

这种情况在之前 debug 时已经碰到过了,最后的结果是花费大量时间和精力,最后发现问题原因早被猜想中了,只是在验证时被忽略一些细节而放过。


stm32L0使用arduino
https://gary-hobson.github.io/2022/09/04/stm32L0使用arduino/
作者
非典型技术宅
发布于
2022年9月4日
许可协议