c - UART 上的 UTF-8 输入

标签 c utf-8 avr stdio uart

基于 Mika Tuupola's tutorial我正在尝试使用来自 UART 的串行输入作为 stdin。底层UART通信代码如下:

#ifndef BAUD
#define BAUD 9600
#endif

#include <avr/io.h>
#include <stdio.h>
#include <util/setbaud.h>

void uart_init ()
{
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;

#if USE_2X
    UCSR0A |= _BV(U2X0);
#else
    UCSR0A &= ~(_BV(U2X0));
#endif

    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);
}

void uart_putchar (char c)
{
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = c;
}

char uart_getchar ()
{
    loop_until_bit_is_set(UCSR0A, RXC0);
    return UDR0;
}

下一层将 uart_getcharuart_putchar 公开为流处理程序兼容函数:

int uart_putchar_s (char c, FILE *stream)
{
    if (c == '\n')
        uart_putchar('\r');
    uart_putchar(c);
    return 0;
}

int uart_getchar_s (FILE *stream)
{
    return uart_getchar();
}

FILE uart_output = FDEV_SETUP_STREAM(uart_putchar_s, NULL, _FDEV_SETUP_WRITE);
FILE uart_input =  FDEV_SETUP_STREAM(NULL, uart_getchar_s, _FDEV_SETUP_READ);

void uart_init_stdio()
{
    stdout = &uart_output;
    stdin  = &uart_input;
}

然后我的 main 只是读入一个字符并将其打印出来。它特意使用 printf,以便输出始终通过 stdout 流抽象。

int main ()
{
    uart_init();
    uart_init_stdio();

    for (;;)
    {
        char c = uart_getchar();
        printf("%c", c);
    }
}

如果我从 UTF-8 串行终端连接到它,然后输入例如á,我正确地看到我以 UTF-8 返回表示 á 的两个字节:本地回显显示我的终端发送字节 C3 A1,这些是我返回的相同的两个字节。到目前为止,还不错。

但是,如果我随后将 main 更改为使用 getchar() 而不是 uart_getchar()(即如果我通过 stdin 输入的流抽象),然后在发送相同的 C3 A1 字节后,我得到的只是 FF FF。这是为什么?从 UTF-8 的角度来看,除了发送和接收恰好编码单个字形的单个字节之外,这里还有其他事情吗?

最佳答案

问题是,uart_getchar() 返回一个在您的平台上签名的“char”。 因此,> 0x7f 的字符被解释为负返回值,因此,stdio 层返回 EOF,在您的平台上为 -1(如果解释为无符号则为 0xFF)。

尝试将 uart_getchar() 声明为返回“int”:

int uart_getchar ()
{
    loop_until_bit_is_set(UCSR0A, RXC0);
    return (unsigned char) UDR0;
}

关于c - UART 上的 UTF-8 输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34270110/

相关文章:

c - snprintf - 安全风险

C程序,while循环不接受小数

mysql - Hibernate mysql utf8配置

mysql - 没有将字符串隐式转换为哈希(smarter_csv gem,上传带有输入的文件)

c - AVR:C 微 Controller 中的设置位

c - 如何仅更新微 Controller 中代码的某些部分或 API

c - 传递一个常量二维数组作为 C 中的结构体

python - Unicode解码错误: 'ascii' codec can't decode byte 0xec in position

avr - 读取 I2C 传感器值(位联动)

c - 有效类型限定符有哪些规则?