Q C51中printf跟直接用SBUF有什么区别?

[复制链接]
6000|13
 楼主| a5566255 发表于 2008-12-2 10:50 | 显示全部楼层 |阅读模式
我知道printf是格式化输出,那么我只要传一个8位数,它们是不是就没有区别?<br /><br />另外有个很重要的,printf只要我用了,就会不停得往串口输出数,哪怕我没把它放在循环语句中是不?比如我这样:<br />while(1){<br />&nbsp;while(RI){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n=SBUF;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RI=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t=read(n);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delay(10000);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%d
&quot;,t);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />我往串口只发一次数据,它就会不停的回复我数据(实测下来好像是的哦,不明白)???&nbsp;
zjw5000 发表于 2008-12-2 20:08 | 显示全部楼层

你用了个while(1)

当然为无限循环的printf
xiaoyu9466 发表于 2008-12-2 23:33 | 显示全部楼层

看库函数

库函数中的printf是不是直接向串口输出数据的<br />如果用keil编译器,同时库函数没有更改,那就是肯定的<br />
 楼主| a5566255 发表于 2008-12-4 13:16 | 显示全部楼层

顶楼会了,是我看错了,它跟本没有重复发送。。。

但是我仍然很抓狂了。。。。。。。<br /><br />郁闷的printf:<br />void&nbsp;main(void)&nbsp;<br />{&nbsp;<br />uint&nbsp;t,n,i;&nbsp;<br />uchar&nbsp;m;&nbsp;<br />SCON=0X50;&nbsp;<br />TMOD=0X20;&nbsp;<br />TH1=0XFD;&nbsp;<br />TL1=0XFD;&nbsp;<br />TI=0;&nbsp;<br />TR1=1;&nbsp;<br />i=0;&nbsp;<br />while(1){&nbsp;<br />while(RI){&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;n=SBUF;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;RI=0;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;for(m=0;m&nbsp;&lt80;m=m+1)&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;TI=1;&nbsp;//这句不写接收端就收不到printf发的数,但把printf换成SBUF=123就可以,WHY??&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;t=4000;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%d
&quot;,t);//SBUF=123;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;P3_2=1;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />}&nbsp;<br />如注释部分,学个单片机真难。。。。。。
 楼主| a5566255 发表于 2008-12-4 13:41 | 显示全部楼层

偶的猜想:

printf串口输出是采用中断方式,需要TI置位才能进入串口中断,<br />但这个函数本身被调用时确没有加入置位TI中断标志位的功能,所以需要自己在之前手动中断,<br />然后它被调用并执行完后却能自动清OTI退出中断。。。。。<br />请问各位大虾,如果是这样的话KEILC这么做什么意思???
 楼主| a5566255 发表于 2008-12-4 17:11 | 显示全部楼层

没人高人给新手解释下么。。。

  
mohanwei 发表于 2008-12-4 20:50 | 显示全部楼层

printf默认采用查询TI的方式进行发送。所以一定要先

把TI置位1次,才能使用printf。具体参考Keil的第一个例程即可(Hello,World!)
mohanwei 发表于 2008-12-4 20:52 | 显示全部楼层

printf会调用putchar函数来输出,库目录下有源码

你也可以在你的工程里使用自己写的putchar函数,从而实现一些特殊功能,例如让printf输出到液晶模块上、输出到数码管上、输出到I/O口……等等
walnutcy 发表于 2008-12-4 20:57 | 显示全部楼层

去看下printf源码了,别在那瞎猜了

  
quakegod 发表于 2008-12-5 03:19 | 显示全部楼层

我从来不用那个printf

因为printf默认使用的是查询方式,会一直等待串口,直到发送最后一个字符,<br />白白浪费MCU时间,试想我们现在用的最高的波特率也就是115200bps,很多时候用的是9600bps,然而晶振都是24MHz,甚至用1T的MCU,使用printf,9600bps发送10个字符需要10.4mS的时间,相当于250000个时钟周期,即使用115200bps也需要0.868mS,20833个时钟周期。所以我宁可在内存里面开辟出16个字节的串口缓冲区,然后用中断的方式来处理。<br />当然了,如果你不停得往串口发数据,或者一次发送了16个字节以上的数据,串口缓冲区满了,那你还是会停下来等待缓冲区,不过即使这样,你也能在两次发送之间获得很多时钟周期的好处。<br />我现在凡是涉及串口输出的程序都使用自己的串口缓冲程序,<br />具体性能没有测试,基本上在串口跑到90%流量的时候,其他程序还能得到90%的MCU时间。<br />
xwj 发表于 2008-12-5 08:44 | 显示全部楼层

quakegod ,Keil的printf是中断方式的!

只是51的串口收发是同一个中断,所以需要用RI、TI来判断是接收还是发送触发的中断<br /><br />首次使用必须置位TI,就是为了人为触发中断程序<br /><br /><br />不过呢...&nbsp;<br />偶也更喜欢使用自己的串口缓冲程序
 楼主| a5566255 发表于 2008-12-5 08:59 | 显示全部楼层

LS大虾好厉害啊

学习!<br />不过是汇编的耶~~
mohanwei 发表于 2008-12-5 09:05 | 显示全部楼层

楼上各位可能还不明白printf的工作原理……

最终发送的实际是putchar()……改一改putchar,就可以实现查询、中断、队列……所有你喜欢的算法。
xwj 发表于 2008-12-5 09:33 | 显示全部楼层

是的,LS正解

发送改putchar(),接收改getchar()即可<br /><br />问题是偶更喜欢用自己写的数据流处理程序,按需配置,充分利用资源
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

218

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部