<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post/3357/</link>
<title><![CDATA[单片机IO口模拟串口程序（发送+接收）]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Sat, 31 Jul 2010 09:19:25 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/3357/</guid> 
<description>
<![CDATA[ 
	前一阵一直在做单片机的程序，由于串口不够，需要用IO口来模拟出一个串口。经过若干曲折并参考了一些现有的资料，基本上完成了。现在将完整的测试程序，以及其中一些需要总结的部分贴出来。<br/><br/>程序硬件平台：11.0592M晶振，STC单片机（兼容51）<br/><br/><br/><div class="code">/***************************************************************<br/>*&nbsp;&nbsp;&nbsp;&nbsp;在单片机上模拟了一个串口，使用P2.1作为发送端<br/>*&nbsp;&nbsp;&nbsp;&nbsp;把单片机中存放的数据通过P2.1作为串口TXD发送出去<br/>***************************************************************/<br/>#include &lt;reg51.h&gt;<br/>#include &lt;stdio.h&gt;<br/>#include &lt;string.h&gt;<br/><br/>typedef unsigned char uchar;<br/><br/>int i;<br/><br/>uchar code info&#91;&#93; = <br/>&#123;<br/>0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55<br/>&#125;;<br/><br/>sbit newTXD = P2^1;//模拟串口的发送端设为P2.1<br/><br/>void UartInit()<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; SCON&nbsp;&nbsp;= 0x50;&nbsp;&nbsp; // SCON: serail mode 1, 8-bit UART<br/>&nbsp;&nbsp;&nbsp;&nbsp; TMOD &#124;= 0x21;&nbsp;&nbsp; // T0工作在方式1，十六位定时<br/>&nbsp;&nbsp;&nbsp;&nbsp; PCON &#124;= 0x80;&nbsp;&nbsp; // SMOD=1;<br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0xFE;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器0初始值，延时417us，目的是令模拟串口的波特率为2400bps fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp;TL0&nbsp;&nbsp; = 0x7F;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器0初始值，延时417us，目的是令模拟串口的波特率为2400bps fosc=11.0592MHz<br/><br/>//&nbsp;&nbsp;&nbsp;&nbsp;TH0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0xFD;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器0初始值，延时417us，目的是令模拟串口的波特率为2400bps fosc=18.432MHz<br/>//&nbsp;&nbsp;&nbsp;&nbsp;TL0&nbsp;&nbsp; = 0x7F;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器0初始值，延时417us，目的是令模拟串口的波特率为2400bps fosc=18.432MHz<br/>&#125;<br/><br/>void WaitTF0(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; while(!TF0);<br/>&nbsp;&nbsp;&nbsp;&nbsp; TF0=0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0=0xFE;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器重装初值 fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL0=0x7F;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器重装初值 fosc=11.0592MHz<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;TH0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0xFD;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器重装初值 fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;TL0&nbsp;&nbsp; = 0x7F;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器重装初值 fosc=18.432MHz<br/>&#125;<br/><br/>void WByte(uchar input)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; //发送启始位<br/>&nbsp;&nbsp;&nbsp;&nbsp; uchar j=8;<br/>&nbsp;&nbsp;&nbsp;&nbsp; TR0=1;<br/>&nbsp;&nbsp;&nbsp;&nbsp; newTXD=(bit)0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; WaitTF0();<br/>&nbsp;&nbsp;&nbsp;&nbsp; //发送8位数据位<br/>&nbsp;&nbsp;&nbsp;&nbsp; while(j--)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newTXD=(bit)(input&amp;0x01);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//先传低位<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WaitTF0();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; input=input&gt;&gt;1;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; //发送校验位(无)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; //发送结束位<br/>&nbsp;&nbsp;&nbsp;&nbsp; newTXD=(bit)1;<br/>&nbsp;&nbsp;&nbsp;&nbsp; WaitTF0();<br/>&nbsp;&nbsp;&nbsp;&nbsp; TR0=0;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>void Sendata()<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; for(i=0;i&lt;sizeof(info);i++)//外层循环，遍历数组<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WByte(info&#91;i&#93;);<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&#125;<br/><br/>void main()<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; UartInit();<br/>&nbsp;&nbsp;&nbsp;&nbsp; while(1)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sendata();<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&#125;</div><br/>##############################################################################<br/><br/><br/><div class="code">/***************************************************************<br/>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 模拟接收程序，这个程序的作用从模拟串口接收数据，然后将这些数据发送到实际串口<br/>*&nbsp;&nbsp;&nbsp;&nbsp;在单片机上模拟了一个串口，使用P3.2作为发送和接收端<br/>*&nbsp;&nbsp;&nbsp;&nbsp;以P3.2模拟串口接收端，从模拟串口接收数据发至串口<br/>***************************************************************/<br/>#include&lt;reg51.h&gt;<br/>#include&lt;stdio.h&gt;<br/>#include&lt;string.h&gt;<br/><br/>typedef unsigned char uchar ;<br/><br/>//这里用来切换晶振频率，支持11.0592MHz和18.432MHz<br/>//#define F18_432<br/>#define F11_0592 <br/>uchar tmpbuf2&#91;64&#93;=&#123;0&#125;;<br/>//用来作为模拟串口接收数据的缓存<br/><br/>struct <br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; uchar recv :6 ;//tmpbuf2数组下标，用来将模拟串口接收到的数据存放到tmpbuf2中<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uchar send :6 ;//tmpbuf2数组下标，用来将tmpbuf2中的数据发送到串口<br/>&#125;tmpbuf2_point=&#123;0,0&#125;;<br/><br/>sbit newRXD=P3^2 ;//模拟串口的接收端设为P3.2<br/><br/>void UartInit()<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; SCON=0x50 ;// SCON: serail mode 1, 8-bit UART<br/>&nbsp;&nbsp;&nbsp;&nbsp; TMOD&#124;=0x21 ;// TMOD: timer 1, mode 2, 8-bit reload,自动装载预置数(自动将TH1送到TL1);T0工作在方式1，十六位定时<br/>&nbsp;&nbsp;&nbsp;&nbsp; PCON&#124;=0x80 ;// SMOD=1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; #ifdef F11_0592 <br/>&nbsp;&nbsp;&nbsp;&nbsp; TH1=0xE8 ;// Baud:2400&nbsp;&nbsp;fosc=11.0592MHz 2400bps为从串口接收数据的速率<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL1=0xE8 ;// 计数器初始值，fosc=11.0592MHz 因为TH1一直往TL1送，所以这个初值的意义不大<br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0=0xFF ;// 定时器0初始值，延时208us，目的是令模拟串口的波特率为9600bps fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TL0=0xA0 ;// 定时器0初始值，延时208us，目的是令模拟串口的波特率为9600bps fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#endif <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; #ifdef F18_432 <br/>&nbsp;&nbsp;&nbsp;&nbsp; TH1=0xD8 ;&nbsp;&nbsp;&nbsp;&nbsp; // Baud:2400&nbsp;&nbsp;fosc=18.432MHz 2400bps为从串口接收数据的速率<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL1=0xD8 ;&nbsp;&nbsp;&nbsp;&nbsp; // 计数器初始值，fosc=18.432MHz 因为TH1一直往TL1送，所以这个初值的意义不大<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TH0=0xFF ;// 定时器0初始值，延时104us，目的是令模拟串口的波特率为9600bps fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TL0=0x60 ;// 定时器0初始值，延时104us，目的是令模拟串口的波特率为9600bps fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#endif <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; IE&#124;=0x81 ;// 中断允许总控制位EA=1;使能外部中断0<br/>&nbsp;&nbsp;&nbsp;&nbsp; TF0=0 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; IT0=1 ;// 设置外部中断0为边沿触发方式<br/>&nbsp;&nbsp;&nbsp;&nbsp; TR1=1 ;// 启动TIMER1,用于产生波特率<br/>&#125;<br/><br/>void WaitTF0(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; while(!TF0);<br/>&nbsp;&nbsp;&nbsp;&nbsp; TF0=0 ;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; #ifdef F11_0592 <br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0=0xFF ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL0=0xA0 ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; #endif <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; #ifdef F18_432 <br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0=0xFF ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; // 定时器重装初值 fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL0=0x60 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; // 定时器重装初值 fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; #endif <br/>&#125;<br/><br/>//接收一个字符<br/>uchar RByte()<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; uchar Output=0 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; uchar i=8 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; TR0=1 ;&nbsp;&nbsp;&nbsp;&nbsp; //启动Timer0<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; #ifdef F11_0592 <br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0=0xFF ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL0=0xA0 ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; #endif <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; #ifdef F18_432 <br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0=0xFF ;// 定时器重装初值 fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL0=0x60 ;// 定时器重装初值 fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; #endif <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; TF0=0 ;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; WaitTF0();//等过起始位<br/>&nbsp;&nbsp;&nbsp;&nbsp; //接收8位数据位<br/>&nbsp;&nbsp;&nbsp;&nbsp; while(i--)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Output&gt;&gt;=1 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(newRXD)Output&#124;=0x80 ;//先收低位<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WaitTF0();//位间延时<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; TR0=0 ;//停止Timer0<br/>&nbsp;&nbsp;&nbsp;&nbsp; return Output ;<br/>&#125;<br/><br/>//向COM1发送一个字符<br/>void SendChar(uchar byteToSend)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; SBUF=byteToSend ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; while(!TI);<br/>&nbsp;&nbsp;&nbsp;&nbsp; TI=0 ;<br/>&#125;<br/><br/>void main()<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; UartInit();<br/>&nbsp;&nbsp;&nbsp;&nbsp; while(1)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(tmpbuf2_point.recv!=tmpbuf2_point.send)//差值表示模拟串口接收数据缓存中还有多少个字节的数据未被处理（发送至串口）<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SendChar(tmpbuf2&#91;tmpbuf2_point.send++&#93;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&#125;<br/><br/><br/>//外部中断0，说明模拟串口的起始位到来了<br/>void Simulated_Serial_Start()interrupt 0 <br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; EX0=0 ;&nbsp;&nbsp;&nbsp;&nbsp; //屏蔽外部中断0<br/>&nbsp;&nbsp;&nbsp;&nbsp; tmpbuf2&#91;tmpbuf2_point.recv++&#93;=RByte();&nbsp;&nbsp;&nbsp;&nbsp; //从模拟串口读取数据，存放到tmpbuf2数组中<br/>&nbsp;&nbsp;&nbsp;&nbsp; IE0=0 ;&nbsp;&nbsp;&nbsp;&nbsp; //防止外部中断响应2次，防止外部中断函数执行2次<br/>&nbsp;&nbsp;&nbsp;&nbsp; EX0=1 ;&nbsp;&nbsp;&nbsp;&nbsp; //打开外部中断0<br/>&#125;</div><br/>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br/><br/>以上是两个独立的测试程序，分别是模拟串口发送的测试程序和接收的测试程序<br/>上面两个程序在编写过程中参考了这篇文章《51单片机模拟串口的三种方法》（在后文中简称《51》），但在它的基础上做了一些补充，下面是若干总结的内容：<br/><br/>1、《51》在接收数据的程序中，采用的是循环等待的方法来检测起始位（见《51》的“附：51 IO口模拟串口通讯C源程序（定时器计数法）” 部分），这种方法在较大程序中，可能会错过起始位（比如起始位到来的时候程序正好在干别的，而没有处于判断起始位到来的状态），或者一直在检测起始位，而没有办法完成其他工作。为了避免这个问题，在本接收程序中采用了外部中断的方法，将外部中断0引脚作为模拟串口的接收端，设IT0=1（将外部中断0设为边缘触发）。这样当起始位（低电平）到来时，就会引发外部中断，然后在外部中断处理函数中接收余下的数据。这种方法可以保证没数据的时候程序该干什么干什么，一旦模拟串口接收端有数据，就可以立即接收到。<br/><br/>2、加入了模拟串口接收缓冲区。在较大程序中，单片机要完成的工作很多，在模拟串口接收到了数据之后立即处理的话，有可能处理不过来造成丢失数据，或者影响程序其他部分执行。本程序中加入了64个字节的缓冲区，从模拟串口接收到的数据先存放在缓冲区中。这样就算程序一时没工夫处理这些数据，腾出手来之后也能在缓冲区中找到它们。<br/><br/>3、《51》文中的WByte函数和RByte函数中都先打开计数器后关闭计数器。如果使用本文的外部中断法来接收数据，并且外部中断处理函数里外都调用了WByte或RByte的话，需要将这两个函数中的TR0=1，TR0=0操作的语句除去，并在UartInit()中加入一句TR0=1;即让TR0始终开着就可以。<br/>由于之前没有意识到这个问题，因此在具体应用时出现了奇怪的问题：表现为中断处理函数执行完毕之后，似乎回不到主程序，程序停在了一个不知道的地方。后来经过排查后找到了问题所在，那个程序的中断处理函数中用了RByte，中断处理函数外用到了WByte，而这两个函数的最后都有TR0=0。这样当中断处理函数执行完毕后，TR0实际上是为0的，返回主程序后（中断前的主程序可能正好处于其他的WByte或RByte执行中），原先以来定时器0溢出改变TF0才能执行下去的WByte函数就无法进行下去，从而导致整个程序停下来不动。（在本文的接收测试程序中不存在这个问题，因为中断处理程序中虽调用了RByte，但中断处理程序外却没有调用RByte或WByte）<br/>下面是修改后的RByte、WByte和WaitTF0函数，仅供参考：<br/>/**********************************************<br/>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;定时器0溢出后重装初值<br/>**********************************************/<br/><br/><div class="code">void WaitTF0(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; TF0=0 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; #ifdef F11_0592 <br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0=0xFF ;// 定时器重装初值 fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL0=0xA0 ;// 定时器重装初值 fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; #endif <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; #ifdef F18_432 <br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0=0xFF ;// 定时器重装初值 fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL0=0x60 ;// 定时器重装初值 fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; #endif <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; while(!TF0);<br/>&nbsp;&nbsp;&nbsp;&nbsp; TF0=0 ;<br/>&#125;</div><br/>/**********************************************<br/>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;从串口B接收一个字符<br/>**********************************************/<br/><br/><div class="code">uchar RByte()<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; uchar Output=0 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; uchar i=8 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;TR0=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //启动Timer0<br/>/*<br/>&nbsp;&nbsp;&nbsp;&nbsp; #ifdef F11_0592<br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0xFF;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL0&nbsp;&nbsp; = 0xA0;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; #endif<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; #ifdef F18_432<br/>&nbsp;&nbsp;&nbsp;&nbsp; TH0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0xFF;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器重装初值 fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; TL0&nbsp;&nbsp; = 0x60;&nbsp;&nbsp;&nbsp;&nbsp;// 定时器重装初值 fosc=18.432MHz<br/>&nbsp;&nbsp;&nbsp;&nbsp; #endif<br/>*/<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; WaitTF0();//等过起始位<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; //接收8位数据位<br/>&nbsp;&nbsp;&nbsp;&nbsp; while(i--)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Output&gt;&gt;=1 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(newRXD)Output&#124;=0x80 ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//先收低位<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WaitTF0();//位间延时<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;while(!TF0) if(newRXD) break;&nbsp;&nbsp;&nbsp;&nbsp;//此句和下一句不能加，如果加上了将导致耗时过长，影响下一个字节的接收<br/>&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;WaitTF0();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//等过结束位<br/>&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;TR0=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //停止Timer0<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; return Output ;<br/>&#125;</div>/**********************************************<br/>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;发送一个字节到串口B<br/>**********************************************/<br/><br/><div class="code">void WByte(uchar input)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; //发送启始位<br/>&nbsp;&nbsp;&nbsp;&nbsp; uchar j=8 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; //TR0=1;<br/>&nbsp;&nbsp;&nbsp;&nbsp; newTXD=(bit)0 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; WaitTF0();<br/>&nbsp;&nbsp;&nbsp;&nbsp; //发送8位数据位<br/>&nbsp;&nbsp;&nbsp;&nbsp; while(j--)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newTXD=(bit)(input&amp;0x01);//先传低位<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WaitTF0();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input=input&gt;&gt;1 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; //发送校验位(无)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; //发送结束位<br/>&nbsp;&nbsp;&nbsp;&nbsp; newTXD=(bit)1 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; WaitTF0();<br/>&nbsp;&nbsp;&nbsp;&nbsp; //TR0=0;<br/>&#125;</div><br/>4、在上面的新修改后的RByte()函数中，有被注释掉的如下两句：<br/>//&nbsp;&nbsp;while(!TF0) if(newRXD) break;&nbsp;&nbsp;&nbsp;&nbsp;//此句和下一句不能加，如果加上了将导致耗时过长，影响下一个字节的接收<br/>//&nbsp;&nbsp;&nbsp;&nbsp;WaitTF0();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//等过结束位<br/>这两句在《51》文中的程序是存在的，但是使用中断接收法后，加上这两句后出现了问题。表现为接收到的下一个字节的数据不完整或直接接收不到，似乎这两句占用了过多的时间。<br/>看这两句的目的似乎是要延时以跳过结束位，但是我感觉这个结束位可以不用管它，反正结束位是个高电平，不会妨碍下一个字节是否到来的判断（下一个字节的起始位是低电平）。那就由它去吧，没有必要为了它而占用CPU的时间。<br/>在本文的程序中，去掉这两句后程序执行正确，如果其他朋友在使用时真的出现问题，可以试着再把它们加上试一下。<br/><br/>来源：http://hi.baidu.com/mcu99/blog/item/954a511011e28908213f2ecd.html
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post/3357/#blogcomment63965</link>
<title><![CDATA[[评论] 单片机IO口模拟串口程序（发送+接收）]]></title> 
<author>liuxing &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Sat, 13 Dec 2014 08:04:39 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/3357/#blogcomment63965</guid> 
<description>
<![CDATA[ 
	请问你程序2中TH0=0xFF，TL0=0xA0是怎么算来的？
]]>
</description>
</item>
</channel>
</rss>