分类: 嵌入式
2015-06-30 09:53:15
我们分析中断程序,它是模拟串口的中心程序。
void tm0() interrupt 1 using 1 //time0中断查询来模拟串口
{
if (RING) //开始接收
{
if (--RCNT == 0)
{
RCNT = 3; // 重置发送波特率计数器
if (--RBIT == 0)
{
RBUF = RDAT; //数据保存到RBUF
RING = 0; //停止接收
REND = 1; //设置接收完成标志
}
else
{
RDAT >>= 1;
if (RXB)
RDAT |= 0x80; //shift RX data to RX buffer
}
}
}
else if (!RXB)
{
RING = 1; //启动标志位
RCNT = 4; // 初始接收波特率计数器 修改为3,间隔相同了,第一位就没问题了
RBIT = 9; //初始接收比特数(8位加一位停止位)
}
先看中断中的接收程序,RING初始为0,所以直接进入else if (!RXB)。由串口协议知当串口有数据接收时起始位为低电平,接收结束后结束为为高电平。所以如果有数据接收(RXB=0)进入else if语句中,RING=1启动标志位,RCNT=4初始化波特率计数器,RBIT=9初始比特数。这是第一次对接收数据抽样,此时是对数据第一位之前的一位起始位进行抽样(起始位为低电平)。
第二次进入中断时RING==1进入if (RING),--RCNT==3不执行下面语句,此时是对起始位第二次抽样。第三次进入中断--RCNT==2,不执行下面语句,此时是对起始位第三次抽样,此时抽样的位置为一个周期(即一个波特率的周期频率),这也是为什么我们在计算溢出时要除以的那个“3”的原因。第4次进入中断--RCNT==1,不执行下面语句,此时是数据位第一位的1/3处抽样。第5次进入中断--RCNT==0(在数据位第一位的2/3处抽样),将RCNT重新赋值3,执行else语句(--RBIT==8不为0),RDAT初始为0,右移一位还为0(RDAT >>= 1;),读取接收位,若接收位为0,则RDAT数据为不变为0,若接收位为1,那么将RDAT最高位置1。
上面讲述的过程为读取第一位数据的过程。RCNT赋值3,进行下一轮的抽样,定时器定时一周,--RCNT==2后第一次进入中断(此时在数据第一位的末端),--RCNT==1进行第二次抽样(此时在数据第二位的1/3处),--RCNT==0将RCNT重新置3,执行读数。直到抽样进行8轮,也就是读取8位接收数据结束,进行第九轮抽样的时候(读取结束位为高电平),--RBIT==0那么RBUF = RDAT;数据保存到RBUF,RING =
0停止接收,REND = 1设置接收完成标志 。读取一个字节结束。 为方便理解,见图 2.5?3,数字为TCNT,我们设我们要接收的数据是10101010。