Keil重定向printf到串口UART输出
来源:互联网 发布:淘宝店铺的推广方式 编辑:程序博客网 时间:2024/04/19 23:44
下面是我搜索到的可以借鉴的讨论+我的评述
评述:在一个芯片系统里,uart的驱动是厂商自己写好的,那他们是怎么关联printf到uart的呢?有人说,printf最终是调用了putchar,我搜索了源码,没有这个函数,估计是开发工具,像KeilC u3,里面已经集成了putchar。于是我奇怪,这个工具怎么知道厂商哪个函数时uart的,有没有命名规则要求?好像没有,看了下面的讨论,估计是通过UART的收发寄存器来关联的。我猜想应该是在某个地方,keilc关联了系统的寄存器列表,找到了串口的寄存器的地址,然后putchar操作该寄存器,就相当于操作了厂商或者开发者自定义的uart_write_byte.uart_read_byte.
所以在keilc里,别人写好的系统,可以直接调用printf输出。我觉得要弄明白,得研究下keil是怎么处理库函数和寄存器的关系的。
关于putchar函数,估计printf是通过
http://www.amobbs.com/thread-5479867-1-1.html
其实也不用首先写一个数据到SBUF寄存器,只需在串口初始化后,加上一句TI=1;即可。原因是printf函数事实上是调用putchar输出字符的。之所以能输出到串口上,就是因为putchar函数把字符通过串口输出。
这是keil中putchar最简单的版本,其他版本也一样,看函数就明白为什么要先让TI=1;了,楼主写的那个SBUF=0,原理是相同的,写入了数据,那么TI就等于1了,然后就可以使用putchar函数和printf函数了。
putchar函数的源码在{keil安装目录下}\C51\LIB文件夹里的PUTCHAR.C文件里,另外在keil的帮助文档里有说明
从下面这篇文章中,我好像找到答案了
评述:我在某个CortextM3的源码里的debug.c找到了fputc。应该说,某些系统是通过fputc建立联系,而不是putchar的。如下:
void fputc_hook(char ch){ if (DebugType == 0) { UARTWriteByte(ch, 1000); } else { VirtualUartWrite(ch); }}int fputc(int ch, FILE *f){ uint8 dgbBuffer[DEBUG_TIME_LEN]; uint32 tmpcnt, i; if (ch == '\n') { tmpcnt = SysTickCounter; for (i = 0; i < DEBUG_TIME_LEN; i++) { dgbBuffer[i] = tmpcnt % 10; tmpcnt = tmpcnt / 10; } fputc_hook('\r'); fputc_hook('\n'); fputc_hook('['); for (i = 0; i < DEBUG_TIME_LEN; i++) { fputc_hook(dgbBuffer[DEBUG_TIME_LEN - 1 -i]+0x30); if (DEBUG_TIME_LEN - 1 -i == 2) { fputc_hook('.'); } } fputc_hook(']'); return OK; } fputc_hook(ch); return OK;}下面是参考文章的转载:
http://blog.chinaunix.net/uid-27631233-id-3345008.html
在实际工作中,遇到了这么一个问题,需要向不同的串口传输ASCII码,无疑使用printf函数是最方便的。然而printf打印出的信息无法选择出口。在网上搜到的程序,printf要调用fputc函数发送字符。该函数如下:
int fputc(int ch, FILE *f)
{
/* e.g. write a character to the USART */
USART_SendData(USART1, (uint8_t) ch);
/* Loop until the end of transmission */
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}
return ch;
}
入口参数有字符和字符要输出到的文件指针。根据搜索,printf函数输出到stdout,而fprintf可以指定字符到达的文件。可FILE结构体中,没有一个是与串口相关的。
typedef struct {
char *fpos; /* Current position of file pointer (absolute address) */
void *base; /* Pointer to the base of the file */
unsigned short handle; /* File handle */
short flags; /* Flags (see FileFlags) */
short unget; /* 1-byte buffer for ungetc (b15=1 if non-empty) */
unsigned long alloc; /* Number of currently allocated bytes for the file */
unsigned short buffincrement; /* Number of bytes allocated at once */
} FILE;
该如何重定向呢?不知道。但有一个弥补的方法。
自己定义n个FILE*指针,并任意赋值。在fputc中利用if..else来做判断,代码如下:
FILE* FileUart1 = (FILE*)0x19;
FILE* FileUart2 = (FILE*)0x28;
int fputc(int ch, FILE *f) {
if ( f == FileUart1 ) {
USART_SendData(COM_USART[0], (uint8_t) ch);
while (USART_GetFlagStatus(COM_USART[0], USART_FLAG_TC) == RESET){}
}
else if ( f == FileUart2 ) {
USART_SendData(COM_USART[1], (uint8_t) ch);
while (USART_GetFlagStatus(COM_USART[1], USART_FLAG_TC) == RESET){}
}
}
这样,fprintf(FileUart1,...)和fprintf(FileUart2,...)便能向不同的串口发送数据。哈哈,虽然没有真正做到重定向,只是用了个歪招,但最初的目的还是达到了。
如果哪位牛人能告知如何真正重定向,感激感激~~~~
还要请问,如何使用__DEBUG__宏定义才能使fprintf("val is %d", val)或fprintf("val1 is %d, val2 is %d", val1, val2)在程序中任意被编译上或编译掉。当然,不包括#ifdef..#endif方法。不这么做就是为了代码清晰一些,便于阅读。谢谢啊~~
0 0
- Keil重定向printf到串口UART输出
- Keil C51重定向printf到串口
- Keil C51重定向printf到串口
- Keil C51重定向printf到串口
- keil C51 重定向printf到串口
- 串口输出重定向到 printf
- 编写读取内存的程序 ——keil uVision3 printf函数重定向到串口输出
- keil C51 printf 重定向 串口
- STM32输出调试信息-printf重定向到串口
- Keil 重定向 printf
- 【STM32】keil MDK下重定向printf到串口(基于STM32CubeMX)
- STM32中printf重定向到串口
- STM32中printf重定向到串口
- 关于printf重定向到串口
- STM32中printf重定向到串口
- STM32Cube Printf uart重定向
- printf重定向输出到文件
- vc6 printf重定向输出到文件
- 解决Android SDK下载和更新失败的方法
- Web Service描述语言 WSDL 详解
- Transformations
- find 命令的mtime参数的使用
- SSH(spring+hibernate+struts)框架
- Keil重定向printf到串口UART输出
- eclipse使用技巧
- 项目2 - 用文件保存的学生名单
- 传递Bitmap + 图片压缩处理 并保存 + 壁纸设置 总结
- 获取一张网络图片(安卓)
- html form表单
- mysql 高可用(主备自动切换)
- Struts 2.0 学习一 struts的基本原理与基本配置
- java缓冲字符流,复制文件,逐个读取、写入