Mega128 实现UART1用printf,scanf函数的一点心得及疑问
编译环境:ICCAVR
MCU : Mega128
仿真测试软件: Protues
系统默认的printf函数是基于UART0的。跟踪了ICCAVR的库函数源代码发现,printf函数最终调用的是putchar.
贴出源代码:
int printf(CONST char *fmt, ...)
{
va_list va;
int val;
va_start(va, fmt);
val = _print((void (*)(char))putchar, fmt, va);
va_end(va);
return val;
}
因此只需要重新定义putchar函数就可以把printf函数重定向到UART1,当然最好是可以实现在UART0 和UART1之间根据需要来选择。
贴出我的代码:
char UARTx ; //UART0 or UART1
char send_byte(char data)
{
if (UARTx == 0)
{
while(!(UCSR0A &(1<<UDRE0)))//waiting for UDR0 empty
{
}
UDR0=data;
while(!(UCSR0A &(1<<TXC0))) //waiting for sending finish
{
}
}
else if (UARTx == 1)
{
while(!(UCSR1A &(1<<UDRE1)))//waiting for UDR1 empty
{
}
UDR1=data;
while(!(UCSR1A &(1<<TXC1))) //waiting for sending finish
{
}
}
else
{
return FALSE;
}
return TRUE ;
}
int putchar(char c)
{ send_byte(c);
}
char UARTx_select(unsigned char ch)
{ if( (0 <= ch) && (ch < 2) )
{UARTx = ch ;
return TRUE ;
}
else
return FALSE ;
}
经测试,printf函数在UART0 和UART1都可以正常工作。
测试代码:
void main()
{ int a = 128 ;
int b = -128;
int c = 0xfa;
char d = 'J';
char *s = "Hello Jackwen!";
float PI = 3.1415926535;
uart0_init();
uart1_init();
UARTx_select(0);
printf("UART0 Test !\r\n");
printf("a = %d \r\n",a);
printf("b = %d \r\n",b);
printf("c = %x \r\n",c);
printf("d = %sc \r\n",d);
printf("s = %s \r\n",s);
printf("PI = %f \r\n",PI);
UARTx_select(1);
printf("UART1 Test !\r\n");
printf("a = %d \r\n",a);
printf("b = %d \r\n",b);
printf("c = %x \r\n",c);
printf("d = %sc \r\n",d);
printf("s = %s \r\n",s);
printf("PI = %f \r\n",PI);
}
运行的结果:
![Mega128使用printf <wbr>,scanf Mega128使用printf <wbr>,scanf](https://i-blog.csdnimg.cn/blog_migrate/704c99bd3fcb251251c39620727f2dea.jpeg)
同理,将getchar重新定义一下,就可以使用scanf函数了
贴出我的代码:
char receive_byte(void)
{ if(UARTx == UART0)
{
while( (!(UCSR0A & (1<<RXC0))) );
return UDR0;
}
else if(UARTx ==UART1)
{while( ( !(UCSR1A & (1<<RXC1)) ) ) ;
return UDR1;
}
else
return FALSE ;
}
int getchar(void)
{
int res ;
res = receive_byte();
return res;
}
关于重新定义的putchar ,getchar函数,个人认为C编译器先判断自定义的函数,然后在调用系统的库函数。也就是说自定义的函数优先级比库函数的优先级高!如果我的理解错误还请高人指点,谢谢!
ICCAVR库函数原型代码下载:http://www.ouravr.com/bbs/bbs_upload565213/files_3/armok0168487.rar
IAR AVR中如果需要实现上面的功能,就需要设置一下
1.Data stack 的大小,当设置为256时候,才能完全实现打印float.
2.库文件选择可是是DLIB ,也可以是CLIB
3.printf formatter设置为large 或则是 full