打印
[PIC32/SAM]

dsPIC33c scanf 不在UART上阻塞输入

[复制链接]
232|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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 | 只看该作者
#include <xc.h>
#include <sys/attribs.h>
#include <stdio.h>

// 实现 __read 系统调用(文件描述符 0 = stdin)
size_t __read(int fd, void *buf, size_t len) {
    if (fd != 0) return 0; // 仅处理 stdin
   
    char *p = (char *)buf;
    size_t n = 0;
    while (n < len) {
        *p++ = UART1_Read(); // 调用你的 UART 读取函数
        n++;
    }
    return n;
}

使用特权

评论回复
5
dongnanxibei| | 2025-6-12 09:09 | 只看该作者
int getchar(void) {
    return UART1_Read(); // 阻塞直到收到数据
}

使用特权

评论回复
6
dongnanxibei| | 2025-6-12 09:09 | 只看该作者
setvbuf(stdin, NULL, _IONBF, 0); // 无缓冲
// 或
setvbuf(stdin, NULL, _IOLBF, 32); // 行缓冲

使用特权

评论回复
7
dongnanxibei| | 2025-6-12 09:10 | 只看该作者
确认 UART1_Read() 是阻塞式的:
char UART1_Read(void) {
    while (!U1STAbits.URXDA); // 等待数据到达
    return U1RXREG;
}

使用特权

评论回复
8
dongnanxibei| | 2025-6-12 09:10 | 只看该作者
#include <xc.h>
#include <stdio.h>

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

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

// 系统级 read 实现
size_t __read(int fd, void *buf, size_t len) {
    if (fd != 0) return 0;
    for (size_t i = 0; i < len; i++) {
        ((char *)buf)[i] = UART1_Read();
    }
    return len;
}

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

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

    while (1);
}

使用特权

评论回复
9
我是一颗胖蘑菇| | 2025-6-13 14:34 | 只看该作者
看起来像是你的scanf实现没有正确地与UART读取函数链接起来。你可以尝试自己实现一个自定义的scanf函数,它调用你的UART1_Read()函数来获取输入。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1401

主题

4612

帖子

0

粉丝