评述:在一个芯片系统里,uart的驱动是厂商自己写好的,那他们是怎么关联printf到uart的呢?有人说,printf最终是调用了putchar,我搜索了源码,没有这个函数,估计是开发工具,像keilc u3,里面已经集成了putchar。于是我奇怪,这个工具怎么知道厂商哪个函数时uart的,有没有命名规则要求?好像没有,看了下面的讨论,估计是通过uart的收发寄存器来关联的。我猜想应该是在某个地方,keilc关联了系统的寄存器列表,找到了串口的寄存器的地址,然后putchar操作该寄存器,就相当于操作了厂商或者开发者自定义的uart_write_byte.uart_read_byte.
所以在keilc里,别人写好的系统,可以直接调用printf输出。我觉得要弄明白,得研究下keil是怎么处理库函数和寄存器的关系的。
关于putchar函数,估计printf是通过
就是在你配置完串口的时候首先写一个数到sbuf寄存器中然后在用printf函数打印就可以,当让这个顺序是不可以变的,如果你想在追问细节为什么,我只能告诉你这应该是开发环境决定的,这一点我就理解这么多,如果有大侠给出更好的解释我也一起共勉。
其实也不用首先写一个数据到sbuf寄存器,只需在串口初始化后,加上一句ti=1;即可。原因是printf函数事实上是调用putchar输出字符的。之所以能输出到串口上,就是因为putchar函数把字符通过串口输出。
这是keil中putchar最简单的版本,其他版本也一样,看函数就明白为什么要先让ti=1;了,楼主写的那个sbuf=0,原理是相同的,写入了数据,那么ti就等于1了,然后就可以使用putchar函数和printf函数了。
putchar函数的源码在{keil安装目录下}\c51\lib文件夹里的putchar.c文件里,另外在keil的帮助文档里有说明
char putchar (char c) {
while (!ti);
ti = 0;
return (sbuf = c);
}
从下面这篇文章中,我好像找到答案了
评述:我在某个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;
}
下面是参考文章的转载:
在实际工作中,遇到了这么一个问题,需要向不同的串口传输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,...)便能向不同的串口发送数据。哈哈,虽然没有真正做到重定向,只是用了个歪招,但最初的目的还是达到了。
传谷歌拟推出互联网电视服务 正洽谈内容许可协议
基于IR2127的电机驱动芯片
单片机中断与CPU的轮询有什么区别
铅酸蓄电池工作原理及氢气泄露检测
干货分享|3步走从AI闭环走向质量闭环,实现真正&quot;0&quot; 缺陷管控
浅谈keil中库函数和寄存器关系
纸箱耐破强度试验机/纸箱破裂试验机/破裂强度试验机
物联网四层核心元件的计量标准体系建设
em357是什么芯片
C程序设计基础-分支结构
OPPO新专利曝光:未来手机或可独立升级摄像头模块
大载重无人机挂载灭火弹灭火 精准高效且能保证人身安全
小米6最新消息:6月6日小米6新机开售,颜色骚气,不过没有现货还是要抢
生物质气体燃料发动机测量控制系统
【EMC案例】PCB中闲置线路对辐射发射的影响
关于LED驱动连接基础四种连接方式的分析介绍
A12X仿生芯片全面拆解,爆表式性能碾压
防爆电动球阀及电动、液控阀驱动的优点是什么
1月北美半导体设备制造商出货金额为30.4亿美元
微软提出极低资源下语音合成与识别新方法,小语种不怕没数据