基于 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_getchar
和 uart_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/