STM32 ADC读取电压和USART串口输出实践日志

举报
Outlook2020 发表于 2024/09/20 16:07:13 2024/09/20
【摘要】 ADC读取电压和USART串口输出这几天做实习程序开发,遇到了一些和ADC和USART的相关问题,做个记录。如果有错误也请各位大佬批评指正! 环境芯片型号:STM32G070CubeMX生成Keil工程后使用VSCode配合Keil Assistant插件共同编程并build下载SSCOM、波特律动助手(serial.keysking.com) 需求很简单:小灯以640ms为周期闪烁每20...

ADC读取电压和USART串口输出

这几天做实习程序开发,遇到了一些和ADC和USART的相关问题,做个记录。如果有错误也请各位大佬批评指正!

环境

  • 芯片型号:STM32G070
  • CubeMX生成Keil工程后使用VSCode配合Keil Assistant插件共同编程并build下载
  • SSCOM、波特律动助手(serial.keysking.com

需求很简单:

  • 小灯以640ms为周期闪烁
  • 每20ms对芯片上链接的三个引脚Temp、Ref、Sig读取电压值
  • 将读到的电压值通过USART4串口输出到外界

初步的实现思路

首先,不能使用STM32学习初期“HAL_Delay()”的方式实现定时功能。否则“何时解决冲突”、“如何计时”、“在哪里完成这些功能”这种问题很难解决。

可以使用STM32的TIM定时器来实现这个功能。定时器在内部时钟计时达到设定值之后便会触发中断处理函数,在中断处理函数中完成我们需要实现的功能即可。

由于存在两个定时功能,我们需要两个定时器。我选择了TIM16和TIM17,上网查说这两个是通用定时器(General Purpose)。之后在中断处理函数中加入触发来源的判断,来自16即是LED的需求,来自17就是另一个。

if (htim == &htim16) // LED Flashing!
{
    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}
else if (htim == &htim17) // Read Pin, and sent it through Port(USART)
{
    // ...
}

开始遇到问题

第一个遇到的问题就是程序无法下载。Target DLL has been cancelled.

尝试了各种方法:

  • 下载驱动
  • 调节Keil项目设置(J-Link等)

都不太好使。最后在网上找到这样的解决方法:

找到MDK-ARM/J-LinkSettings.ini,把Device的值改为Cortex-M0+,成功烧录!

Device="Cortex-M0+"

第二个问题,串口助手接收不到发送的数据

到底是硬件配置有问题,还是CubeMX工程参数有问题,抑或是代码逻辑有问题呢?在遇到问题初期,我不能确定是哪一种,于是我只能一一排查。(最后证明三者都有问题)

首先在硬件上,直接说结论。Waveshare的USB to RS232/485/TTL那个小开关应该拨到“3.3V”档,否则没有任何输出。同时,两边的TXD/RXD线应该交叉连接而不是对应连接。

改正之后,发现开始有输出了,但是输出乱码。最后发现是缺共地线。也就是说,两者的地线没有接到一起导致乱码。

此时,测试信息已经没有问题了。

Hello World!

但是继续测试发现电压输出仍然是乱码。

HAL_UART_Transmit_IT(&huart4, (uint8_t *)voltageStr, strlen(voltageStr));

太奇怪了,几乎同样的位置,输出两个字符串竟然一个乱码一个正常?

之后我把这句代码放在函数的不同位置进行测试,又惊奇地发现:只有这句代码在最后一行的时候会乱码。而业务逻辑已经决定了这句代码在最后一行,因为一定是最后串口输出。

于是我想到:中断模式的串口输出只开启输出流程,但是不监控其是否结束,而只是在结束时触发一个中断处理函数。而这里输出的字符串voltageStr是一个局部变量!因此,如果代码在最后一句,函数马上就会结束,变量也会随着函数一起被析构。你传过去的是一个地址,那么USART通过地址寻址的时候当然是一个脏数据。

原因明晰了,解决方法自然就出来了。与其自己想办法等待传输结束之后再结束函数,倒不如直接使用阻塞模式传输数据。阻塞模式会让CPU一直处在忙的状态,直到传输结束,那句代码结束一定是传输结束,因此函数一定在代码执行结束之后结束。自己写一个等待本质上还是让CPU等,此时已经失去了中断模式CPU利用率高的优势,没有任何必要。

于是,在CubeMx里面关闭中断,最后将代码改成阻塞模式:

HAL_UART_Transmit(&huart4, (uint8_t *)voltageStr, strlen(voltageStr), 20);

这样,输出的问题就解决啦。

关于ADC的使用

这里反而几乎没有遇到问题。只是,当时在CubeMX里面似乎无法打开连续扫描模式,后来发现是要求启用通道数大于1的时候才允许打开连续扫描。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。