☰
博客发布稿
2026/10/15 5:01:15 网站建设 项目流程

STM32F103C8T6串口实验:发送hello、中断接收和DMA

这次实验还是用上次的C8T6板。要求是让板子一直发送hello windows!,电脑发一个#后暂停,发*后继续,再分别用轮询、中断和DMA来做。

串口程序不长,不过实际接线时还是遇到了问题。下面把配置、主要代码和接板后的结果记一下。

一、实验准备

  • STM32F103C8T6核心板
  • Horco DAP下载器,带串口功能
  • CubeMX、Keil,HAL库
  • 杜邦线、面包板
  • 电脑上的串口接收窗口

最开始接的是一只独立串口模块,但电脑没有识别到它。后来发现串口模块很热好像烧了,就换成DAP自带的串口,电脑显示为COM4。下载和串口通信可以共用这只DAP,但它们接的是不同的引脚。

C8T6DAP用途
PA9RXD板子发送,电脑接收
PA10TXD电脑发送,板子接收
GNDGND共地
PA13SWDIO/TMS下载程序
PA14SWCLK/TCK下载程序

TX和RX要交叉接。这样做实验才不烧芯。

二、串口参数和CubeMX配置

USART1选择异步模式,参数如下:

参数设置
波特率115200
数据位8位
停止位1位
校验无
硬件流控无
TX/RXPA9、PA10

SYS里面保留Serial Wire。时钟沿用原工程的内部HSI,通过PLL配置成64MHz:

HSI 8MHz / 2 × 16 = 64MHz APB1 = 32MHz APB2 = 64MHz

USART1用APB2时钟。这样不用依赖外部晶振,三个版本都保持相同的时钟设置。

中断版需要打开USART1的中断。DMA版添加USART1_TX,对应DMA1_Channel4,方向选Memory to Peripheral,模式选Normal,内存地址递增,外设地址不递增,数据宽度都选Byte。DMA中断和USART1中断都要打开。

三个工程分别放在01_HAL_Polling、02_HAL_Interrupt、03_HAL_DMA里。都可以直接打开Keil工程,配套的.ioc用来查看或重建配置。

三、先用轮询发送hello

发送的内容是下面这个数组:

staticuint8_thello[]="hello windows!\r\n";

这里用了英文感叹号,再加回车换行,一共16字节。轮询版每次发送一个字节,发送前检查有没有收到电脑的字符:

if(ch=='#')g_running=0U;elseif(ch=='*')g_running=1U;

发送时用HAL_UART_Transmit()。每发完一个字节,主循环继续检查接收状态。暂停时也要检查输入,否则发了#后就收不到恢复用的*了。

默认TX_DELAY_MS是0,没有额外等待。烧录后,电脑选COM4、115200、8N1,就能看到hello一直往下滚。

后面把TX_DELAY_MS改成50做对照。无间隔时,约2秒收到20929字节;加50ms间隔后,约2.037秒收到641字节,接收速度降到约315 Byte/s,变化很明显。

四、改成中断方式

中断版先挂载一个字节的接收:

HAL_UART_Receive_IT(&huart1,&rx_byte,1U);

USART1中断入口调用HAL处理函数:

voidUSART1_IRQHandler(void){HAL_UART_IRQHandler(&huart1);}

收到一个字节后,HAL进入接收完成回调。里面处理#、*,然后再调用一次HAL_UART_Receive_IT(),准备收下一个字节。重新挂载这一步不能漏。

发送也改为HAL_UART_Transmit_IT()。发完当前一行后,回调清除忙标志,主循环再决定是否发送下一行。中断里只处理简单状态,没有放延时或整段阻塞发送。

实际测试时,发#后接收计数停住,发*后继续增加。下面是暂停时的截图:

窗口里之前的文字还在,但是近约0.5秒接收显示0字节,总计数停在416604。这说明暂停的是后面的发送,并不是把历史内容清空。

恢复测试也保留了日志:中断版发*后,约0.5秒收到5697字节,内容符合hello加回车换行的格式。

五、DMA连续发送

DMA版准备了256字节的缓冲,相当于16行hello。启动发送的主要调用是:

HAL_UART_Transmit_DMA(&huart1,dma_data,sizeof(dma_data));

用Normal模式时,一组数据发完就结束,下一组由主循环重新启动。缓冲只在初始化时填好,发送过程中不修改。电脑发来的控制字符仍然用中断接收。

这里除了DMA中断,还要打开USART1中断。DMA搬完最后一个字节后,HAL还要等USART真正发送结束;如果只开DMA中断,发送状态可能一直忙,后面就不能正常续发。

收到#后,不启动下一组,当前256字节先发完。所以DMA版暂停可能比中断版稍晚一些。115200下,一组256字节的理论发送时间约22.22ms。

DMA先测了115200,之后把板子和电脑都改成460800再测一次。测试结束后,工程中的默认参数已恢复115200。

六、上板测试结果

三个版本都通过了Keil和GNU Arm编译,Keil是0错误、0警告。接板测试前备份了原来的64KiB Flash,每次烧录后也做了回读比较。

方式采样时间接收字节数接收速度
轮询1152002.0021s2092910453.3 Byte/s
中断1152002.0031s2291311438.5 Byte/s
DMA1152002.0028s2304111504.5 Byte/s
DMA4608002.0002s9209746042.8 Byte/s

四组测试都能暂停和恢复。表里的速度是电脑收到的字节数除以采样时间,不是用波形测出来的波特率。截图中的总计数来自更长时间运行,和表中单次采样的数量不同。

115200的8N1串口,每字节占10位,理论载荷上限是11520 Byte/s。中断和DMA的实测速度比较接近这个值,轮询版因为逐字节查询和调用,稍慢一些。

七、这次遇到的问题

第一个问题是串口选错了。独立模块没有被识别,电脑上出现的COM4其实属于DAP。最开始信号线接在独立模块上,却用COM4测试,当然收不到数据。换到DAP的RXD、TXD并交叉连接后才正常。

第二个是接收窗口有时停在半个单词,例如末尾只显示he。串口数据是分批读进窗口的,下一批到来后会继续显示,不能只凭这一小段就判断丢字节。检查原始接收数据后,本次采样符合重复格式。

还有一点要区分:CH340的TTL串口和RS-232电平不是同一种东西。RS-232需要电平转换,不能直接接到STM32引脚。不接VCC和不接GND也不是一回事,模块如果由USB供电,可以不用另接VCC;单端通信仍需要共同的地参考。

八、文件传输和波形测量

文件传输按8N1估算:

理论时间 = 文件字节数 × 10 / 波特率

115200下,1MiB至少约91.02秒,10MiB约15.17分钟,100MiB约151.70分钟。实际还会受软件间隔、协议开销等影响。收到文件后需要比较大小和SHA-256。双电脑RS-232传文件这部分还没有实际做,报告里保留了接线和操作步骤。

Keil位波形也还没有取得光标读数。可以用0x55辅助观察,按跨越位数除以光标时间差计算波特率。115200的理论位宽是8.680556μs,但不能把这个数直接填成实测值。

参考资料

配置和函数说明参考了下面两篇教程,实验记录采用准备、配置、代码、接板现象的写法。本次代码和接收数据对应自己的C8T6实验。就酱子把。

  • HAL库 STM32CubeMX教程四:UART串口通信详解
  • HAL库 STM32CubeMX教程十一:DMA串口发送接收
  • ST官方STM32CubeF1
  • Keil USART1仿真说明

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询