[PIC32/SAM] dsPIC33c scanf 不在UART上阻塞输入

[复制链接]
 楼主| cr315 发表于 2025-6-10 18:00 | 显示全部楼层 |阅读模式
我正在使用XC16编译器在MPLAB X中进行dsPIC33C项目。我已配置UART用于printf输出,这工作得很好。然而,当我使用scanf时,它没有像我预期的那样阻塞输入——它只是立即返回。
我查看了项目的地图文件,看到 scanf 解析为 libc99-elf.a 中的低级实现(函数如 ___vscanf 和 __scanf_core)。似乎缺少一个实际从UART读取字符的低级挂钩。
为了测试,我已经实现了UART1_Read(),并且它按预期工作——直到接收到数据为止。我还添加了对getchar()和getch()的实现,它们调用了UART1_Read(),但是scanf仍然不阻塞,只是不读取任何内容就返回。

我怎样才能scanf()在我的项目中使块并等待UART输入?

任何帮助或建议都将不胜感激!

dongnanxibei 发表于 2025-6-12 09:08 | 显示全部楼层
要让 scanf() 在 XC16 编译器中正确阻塞并等待 UART 输入,你需要确保底层标准输入(stdin)的实现正确挂钩到你的 UART 驱动程序。
dongnanxibei 发表于 2025-6-12 09:09 | 显示全部楼层
关键步骤:
实现 __read 系统钩子(低级 I/O 函数)

确保 getchar() 正确调用 UART 读取

检查流缓冲行为
dongnanxibei 发表于 2025-6-12 09:09 | 显示全部楼层
  1. #include <xc.h>
  2. #include <sys/attribs.h>
  3. #include <stdio.h>

  4. // 实现 __read 系统调用(文件描述符 0 = stdin)
  5. size_t __read(int fd, void *buf, size_t len) {
  6.     if (fd != 0) return 0; // 仅处理 stdin
  7.    
  8.     char *p = (char *)buf;
  9.     size_t n = 0;
  10.     while (n < len) {
  11.         *p++ = UART1_Read(); // 调用你的 UART 读取函数
  12.         n++;
  13.     }
  14.     return n;
  15. }
dongnanxibei 发表于 2025-6-12 09:09 | 显示全部楼层
  1. int getchar(void) {
  2.     return UART1_Read(); // 阻塞直到收到数据
  3. }
dongnanxibei 发表于 2025-6-12 09:09 | 显示全部楼层
setvbuf(stdin, NULL, _IONBF, 0); // 无缓冲
// 或
setvbuf(stdin, NULL, _IOLBF, 32); // 行缓冲
dongnanxibei 发表于 2025-6-12 09:10 | 显示全部楼层
确认 UART1_Read() 是阻塞式的:
  1. char UART1_Read(void) {
  2.     while (!U1STAbits.URXDA); // 等待数据到达
  3.     return U1RXREG;
  4. }
dongnanxibei 发表于 2025-6-12 09:10 | 显示全部楼层
  1. #include <xc.h>
  2. #include <stdio.h>

  3. // UART 初始化(假设已实现)
  4. void UART1_Init(void) { /* ... */ }

  5. // 阻塞式 UART 读取
  6. char UART1_Read(void) {
  7.     while (!U1STAbits.URXDA);
  8.     return U1RXREG;
  9. }

  10. // 系统级 read 实现
  11. size_t __read(int fd, void *buf, size_t len) {
  12.     if (fd != 0) return 0;
  13.     for (size_t i = 0; i < len; i++) {
  14.         ((char *)buf)[i] = UART1_Read();
  15.     }
  16.     return len;
  17. }

  18. int main(void) {
  19.     UART1_Init();
  20.     setvbuf(stdin, NULL, _IONBF, 0); // 无缓冲

  21.     printf("Enter a number: ");
  22.     int num;
  23.     scanf("%d", &num); // 现在应该会阻塞
  24.     printf("You entered: %d\n", num);

  25.     while (1);
  26. }
我是一颗胖蘑菇 发表于 2025-6-13 14:34 | 显示全部楼层
看起来像是你的scanf实现没有正确地与UART读取函数链接起来。你可以尝试自己实现一个自定义的scanf函数,它调用你的UART1_Read()函数来获取输入。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1448

主题

4810

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部

1448

主题

4810

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部