You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ATxmega128A1用fwrite写stdout发二进制数据0x0a前自动加0x0d如何解决

根本原因说明

avr-libc的标准IO库没有实现文本/二进制模式的区分,你遇到的0x0a自动转0x0d0x0a是默认串口输出回调里硬编码的换行转换逻辑,所以通用桌面系统的freopen、fdopen加wb参数的方法完全不兼容,底层没有对应的实现逻辑。


可行解决方案

方案1:修改stdout绑定的串口输出回调(最推荐,可保留标准IO调用习惯)

avr-gcc环境下的stdout本质是通过FDEV_SETUP_STREAM宏绑定用户自定义的字符输出回调实现的,你现有代码里的回调肯定包含了换行转换的逻辑,删除对应判断即可:

// 原串口输出回调示例,删除换行转换逻辑即可
static int uart_putchar(char c, FILE *stream) {
    // --- 删除下面这行代码即可消除自动加\r的逻辑 ---
    // if (c == '\n') uart_putchar('\r', stream);

    // 原有串口发送逻辑保留
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = c;
    return 0;
}

// 绑定stdout的逻辑不需要修改
static FILE uart_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

int main(void) {
    stdout = &uart_stdout;
    // 后续初始化、业务逻辑
    uint8_t data[10] = {1,2,3,10,/*其余值*/3,5};
    fwrite(data, 1, 10, stdout); // 此时输出完全为原始二进制,无转换
}

如果后续需要同时支持文本换行输出和二进制传输,可以定义两个不同的FILE流,分别绑定带换行转换和不带转换的回调,按需选择使用即可。

方案2:绕过标准IO直接操作串口寄存器发数据

如果不想修改现有stdout的逻辑,可直接写串口外设寄存器批量发送二进制数据,完全跳过标准IO的转换逻辑:

void uart_send_binary(const uint8_t *buf, size_t len) {
    for (size_t i = 0; i < len; i++) {
        // 等待串口发送缓冲区为空
        loop_until_bit_is_set(UCSR0A, UDRE0);
        // 直接写入字节到串口数据寄存器
        UDR0 = buf[i];
    }
}

// 调用示例
uint8_t data[10] = {1,2,3,10,/*其余值*/3,5};
uart_send_binary(data, 10);

这个方法不会影响现有printf等文本输出的换行逻辑,适合仅部分场景需要传输二进制数据的情况。


内容的提问来源于stack exchange,提问作者WPFGermany

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 10:36:03