你提出的问题是关于 STC32G864K 芯片在使用 串口DMA发送数据 时,加入延时函数 Delay1000ms() 后,DMA发送只执行一次,而去掉延时则能持续发送数据。你怀疑延时函数是否影响了中断的响应,从而导致 DmaTxFlag 无法置位。
下面我将从 硬件原理、DMA机制、中断响应、延时函数实现机制 等角度,结合你的代码片段,进行详细分析并给出建议。
一、问题现象总结
1. 使用 STC32G 官方例程,串口通过 DMA 发送数据。
2. 当加入 Delay1000ms(); 时,DMA 只发送一次。
3. 注释掉 Delay1000ms(); 后,DMA 可持续发送。
4. 注释掉 DMAUR1TCR = 0xc0; 后,也只发送一次。
5. DmaTxFlag 是在中断中置位的,但加了延时后无法进入 if(DmaTxFlag) 分支。
二、可能的原因分析
1. 延时函数占用 CPU 时间,阻塞中断响应
你提到的 Delay1000ms(); 是“阻塞式延时函数”,即在这1秒内,CPU 会一直执行空循环,不做其他事情。这种延时方式会 完全阻塞主程序流程,并且 可能屏蔽中断响应。
如果 Delay1000ms(); 是基于 关闭中断 的方式实现的(例如使用 EA = 0;),那么在延时期间,DMA发送完成中断将无法被响应。
即使没有关闭全局中断,如果延时函数本身是一个“死循环”,那么在延时期间,中断服务程序虽然触发了,但主程序没有机会去处理中断标志位(如 DmaTxFlag)。
2. DMA发送配置不完整或未重新使能
DMAUR1TCR = 0xc0; 是用于启动DMA传输的寄存器操作。如果每次发送后没有重新设置该寄存器,DMA可能不会再次启动。
在DMA中断中,是否对 DMA 通道进行了 重新初始化或重新使能?如果没有,DMA只能发送一次。
3. DmaTxFlag 未正确清除或未及时处理
如果 DmaTxFlag 没有在中断中正确置位,或者在主程序中未及时清除,可能导致程序逻辑判断失效。
若中断未被及时响应(如因延时函数阻塞),DmaTxFlag 的置位也会被“延迟”,主程序可能已经跳过判断。
三、建议解决方案
1. 避免使用阻塞式延时函数
尽量使用 定时器中断+标志位 实现延时,避免阻塞CPU。
或者使用 非阻塞延时函数,例如:
- c
- void DelayMs(uint16t ms) {
- while (ms--) {
- DelayUs(1000);
- }
- }
复制代码
但前提是 DelayUs() 不关闭中断。
2. 检查中断使能配置
确保以下中断使能已正确开启:
- c
- EA = 1; // 全局中断使能
- DMAIE = 1; // DMA中断使能
复制代码
此外,检查DMA通道的中断使能是否开启。
3. 在DMA中断中重新启动DMA传输
在DMA发送完成后,应在中断服务程序中重新配置并启动DMA:
- c
- void DMAISR(void) interrupt 18 {
- if (DMAISRTXDONEFLAG) {
- DmaTxFlag = 1;
- DMAUR1TCR = 0xc0; // 重新启动DMA发送
- DMAISRTXDONECLEAR; // 清除中断标志
- }
- }
复制代码
注意:具体寄存器名称和位定义请参考STC32G的官方手册。
4. 优化主循环逻辑
不要在主循环中频繁调用长时间延时函数。可以使用如下方式:
- c
- uint32t lastTime = 0;
- while (1) {
- if (DmaTxFlag) {
- DmaTxFlag = 0;
- // 重新准备数据并启动DMA
- }
- if (GetSysTime() - lastTime >= 1000) {
- lastTime = GetSysTime();
- // 执行1秒周期性操作
- }
- }
复制代码
其中 GetSysTime() 可以是一个基于定时器的毫秒级时间戳函数。
四、总结
| 问题点 | 原因分析 | 建议 |
|--------|----------|------|
| 加延时后DMA只发一次 | 延时函数阻塞中断响应 | 改用非阻塞延时或定时器 |
| 注释DMA启动寄存器后只发一次 | DMA未重新使能 | 中断中重新启动DMA |
| DmaTxFlag未进入判断 | 中断未响应或标志未置位 | 检查中断配置与标志处理 |
| 延时函数是否错误 | 可能关闭了中断 | 查看Delay函数实现是否影响中断 |
五、附加建议
使用调试器(如STC-ISP或Keil+STC-Link)观察中断是否真正触发。
打印调试信息:可通过串口输出调试信息,确认中断是否执行。
阅读官方手册:STC32G的DMA和串口部分,确认寄存器配置是否符合预期。
如果你能提供完整的代码片段(尤其是DMA中断服务程序和延时函数的实现),我可以进一步帮你定位具体问题。
如有需要,我也可以帮你改写为非阻塞式延时版本,或者提供基于定时器的周期性任务处理方案。
如需进一步帮助,请继续提问。
[本文内容由国芯人工智能辅助生成,仅供参考] |