找回密码
 立即注册
查看: 74|回复: 6

有关串口putchar函数重定向的疑惑

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:144
  • 最近打卡:2025-04-27 15:13:45

3

主题

11

回帖

175

积分

注册会员

积分
175
发表于 2025-4-15 21:05:10 | 显示全部楼层 |阅读模式
我在使用STC32G8K64的时候,发现像第二张图这样重定向串口会导致卡死,但是第一图就能正常使用,有没有哪位大佬解答一下,串口配置是在STC-ISP上生成的,while循环里一直发送字符串数据。
截图202504152103022875.jpg
截图202504152103441931.jpg
回复

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 2025-4-15 21:08:00 | 显示全部楼层
在嵌入式开发中,串口通信是一个非常重要的功能,而putchar函数的重定向则是实现串口输出的常见方法。针对您在使用STC32G8K64时遇到的串口putchar函数重定向问题,以下是一些可能的原因和解决方案。

1. 串口配置问题
首先,确保您的串口配置是正确的。STC-ISP工具生成的串口配置通常是可靠的,但仍需检查以下几个方面:
波特率:确保波特率设置正确,且与接收端匹配。
数据位、停止位和校验位:这些参数也需要与接收端一致。
时钟频率:确保MCU的时钟频率设置正确,因为波特率的计算依赖于时钟频率。

2. putchar函数重定向的实现
putchar函数的重定向通常是通过重写标准库中的putchar函数来实现的。以下是两种常见的实现方式:

方式一:直接发送字符
  1. c
  2. int putchar(int ch) {
  3.     while (!(UARTSTATUSREG & UARTTXREADYFLAG)); // 等待发送缓冲区为空
  4.     UARTDATAREG = ch; // 发送字符
  5.     return ch;
  6. }
复制代码
这种方式通过轮询发送缓冲区状态,确保字符被成功发送。这种方式简单直接,但可能会占用较多的CPU资源。

方式二:使用中断发送字符
  1. c
  2. int putchar(int ch) {
  3.     while (!(UARTSTATUSREG & UARTTXREADYFLAG)); // 等待发送缓冲区为空
  4.     UARTDATAREG = ch; // 发送字符
  5.     return ch;
  6. }
复制代码
这种方式与方式一类似,但可以通过中断机制来减少CPU的占用率。具体实现需要配置串口发送中断,并在中断服务程序中处理字符发送。

3. 卡死问题的可能原因
根据您的描述,第二种方式会导致卡死,而第一种方式正常。以下是一些可能的原因:

3.1 发送缓冲区未准备好
在第二种方式中,如果发送缓冲区未准备好,程序会一直等待,导致卡死。这可能是因为:
波特率设置错误:导致发送缓冲区无法及时清空。
硬件问题:如串口硬件故障或连接问题。

3.2 中断配置错误
如果使用了中断机制,确保中断配置正确,包括:
中断优先级:确保串口中断优先级设置合理,避免被其他高优先级中断阻塞。
中断服务程序:确保中断服务程序正确实现,能够及时处理发送缓冲区。

3.3 资源竞争
在多任务或中断环境中,可能会出现资源竞争问题。例如,如果putchar函数被多个任务或中断调用,可能会导致发送缓冲区被错误地占用或清空。

4. 解决方案
针对上述可能的原因,可以尝试以下解决方案:

4.1 检查串口配置
确保串口配置正确,特别是波特率、数据位、停止位和校验位等参数。

4.2 优化putchar函数
如果使用轮询方式,可以尝试优化putchar函数,减少CPU占用率。例如,可以增加超时机制,避免无限等待。
  1. c
  2. int putchar(int ch) {
  3.     uint32t timeout = 100000; // 超时计数器
  4.     while (!(UARTSTATUSREG & UARTTXREADYFLAG) && timeout--); // 等待发送缓冲区为空或超时
  5.     if (timeout > 0) {
  6.         UARTDATAREG = ch; // 发送字符
  7.     }
  8.     return ch;
  9. }
复制代码

4.3 使用中断机制
如果使用中断机制,确保中断配置正确,并在中断服务程序中正确处理发送缓冲区。
  1. c
  2. volatile uint8t txbuffer[TXBUFFERSIZE];
  3. volatile uint8t txhead = 0;
  4. volatile uint8t txtail = 0;
  5. void UARTISR(void) interrupt UARTINTERRUPTNUM {
  6.     if (UARTSTATUSREG & UARTTXREADYFLAG) {
  7.         if (txhead != txtail) {
  8.             UARTDATAREG = txbuffer[txtail];
  9.             txtail = (txtail + 1) % TXBUFFERSIZE;
  10.         }
  11.     }
  12. }
  13. int putchar(int ch) {
  14.     uint8t nexthead = (txhead + 1) % TXBUFFERSIZE;
  15.     while (nexthead == txtail); // 等待缓冲区有空闲位置
  16.     txbuffer[txhead] = ch;
  17.     txhead = nexthead;
  18.     UARTENABLETXINTERRUPT(); // 使能发送中断
  19.     return ch;
  20. }
复制代码

4.4 调试和测试
通过调试工具(如逻辑分析仪或串口调试助手)监控串口通信,检查发送和接收的数据是否正确。如果发现问题,可以逐步排查硬件和软件问题。

5. 总结
在使用STC32G8K64进行串口通信时,putchar函数的重定向是一个关键步骤。通过检查串口配置、优化putchar函数、正确使用中断机制以及进行调试和测试,可以有效解决卡死问题。希望以上分析和解决方案能够帮助您顺利实现串口通信功能。

如果您在实施过程中遇到其他问题,欢迎继续交流讨论。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2025-4-16 12:06:58 | 显示全部楼层
请提供测试项目,方便大伙帮忙分析。
像这样:
串口打印 - CHIPID-32G.zip (15.88 KB, 下载次数: 3)

不管哪种方式都能正常输出:
  1. void UartPutc(unsigned char dat)
  2. {
  3. #if(PrintUart == 1)
  4.         SBUF = dat;
  5. //        while(TI==0);
  6.         while(!TI);
  7.         TI = 0;
  8. #else
  9.         S2BUF  = dat;
  10.         while(S2TI == 0);
  11.         S2TI = 0;    //Clear Tx flag
  12. #endif
  13. }
复制代码


截图202504161207287278.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:144
  • 最近打卡:2025-04-27 15:13:45

3

主题

11

回帖

175

积分

注册会员

积分
175
发表于 2025-4-16 21:23:15 | 显示全部楼层
程序中仅使用printf打印,麻烦大佬帮看下哪一步存在问题

Template.zip

41.5 KB, 下载次数: 1

点评

你和楼上乘风版主的差异在于,一种是轮询模式,一种中断模式。不要混用  详情 回复 发表于 2025-4-16 22:39
这要是主流程 SBUF = c; 进中断TI = 0; 再恢复主流程 while(TI == 0); 不就卡死了吗。 参考官方例程学习  详情 回复 发表于 2025-4-16 22:36
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2938

积分

荣誉版主

无情的代码机器

积分
2938
发表于 2025-4-16 22:36:52 | 显示全部楼层
S1*** 发表于 2025-4-16 21:23
程序中仅使用printf打印,麻烦大佬帮看下哪一步存在问题


这要是主流程
SBUF = c;

进中断TI = 0;

再恢复主流程
while(TI == 0);
不就卡死了吗。


参考官方例程学习
10-串口1中断模式与电脑收发测试.zip (40.83 KB, 下载次数: 0)
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2938

积分

荣誉版主

无情的代码机器

积分
2938
发表于 2025-4-16 22:39:51 | 显示全部楼层
S1*** 发表于 2025-4-16 21:23
程序中仅使用printf打印,麻烦大佬帮看下哪一步存在问题

你和楼上乘风版主的差异在于,一种是轮询模式,一种中断模式。不要混用
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:144
  • 最近打卡:2025-04-27 15:13:45

3

主题

11

回帖

175

积分

注册会员

积分
175
发表于 2025-4-17 17:57:49 | 显示全部楼层
erci*** 发表于 2025-4-16 22:39
你和楼上乘风版主的差异在于,一种是轮询模式,一种中断模式。不要混用 ...

感谢大佬指点
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-1 21:37 , Processed in 0.125517 second(s), 97 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表