关于模拟串口的波特率的分析研究

来源:本站
导读:目前正在解读《关于模拟串口的波特率的分析研究》的相关信息,《关于模拟串口的波特率的分析研究》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《关于模拟串口的波特率的分析研究》的详细说明。
简介:在用单片机开发各种嵌入式应用系统中,由于异步串行通讯连接简单,因而成为经常用到的一种通信模式,很多应用中还要求实现多路异步串行通信。为了提高系统的性能价格比,就要求设计工程师用软件增加实现一路或多路异步串行通信。本文即是对模拟串口的波特率做出的一点分析。

首先简单的介绍一下串行异步通讯的数据格式定义,发送或接收一个完整的字节信息,必须有“起始位”、“若干数据位”、“奇偶校验位”和“停止位”;定义每位信息的时间宽度——每秒发送的信息位个数,即为“波特率”。本文附带的模拟串口源程序采用数据帧的格式为 1位起始位(低电平),8位数据位(先低位在高位),1位停止位(高电平),且在线路空闲状态时总是保持为高电平。当在11M晶振时钟频率下,采用波特率为9600或19200时。该模拟串口都可以无误差的进行传输,具体分析后面进行。

参照源程序,我们知道,在这个模拟串口设计中,模拟的是单片机串行异步通讯方式1,由P1^0做接收端,P1^1做发送端,通过定时器1定时溢出中断来确定每位数据的时间,由StartBitOn()函数不断查询接收端的状态,当出现低电平(即起始位)的时候,调用接收程序,接收发送的数据。

针对以下附带的源程序分析知,PGetChar(),PSendChar()都是通过移位方式来接收数据,每接收一位数据,需要定时器溢出产生中断一次,故要得到一帧的数据,就必须经过10个数据位的时间才能完成,同样的,在模拟串口的发送端,要完整的发送一帧数据也要经过10个数据位的时间。因而在如下连接时,引出了以下的问题。

当RS232单次发送一个字符时,可以正常接收和发送回RS232。

当RS232连续发送一串字符时,通过模拟串口返回给RS232的字符只有原来的一半。如发送1234567890这样一个字符串时,接收的字符为13579。

那为什么在单独发送一个字符是不会丢失,而连续发送时就只有原来的一半了呢!

____________ ______________________________

| | | |

| | | |

| PC |---------->| PGetChar() |

| RS232| | | MCU |

| | | V |

| |<----------| PSendChar() |

------------- -------------------------------

源程序:

/**********************************************

IO 口模拟232串行异步通讯程序

**********************************************/

#include <reg51.h>

sbit BT_SND =P1^1;

sbit BT_REC =P1^0;

#define F_TM F0 //自定义标志位,作为中断标志位

#define TIMER0_ENABLE TL0=TH0; TR0=1;//TR0 = 1,启动T

#define TIMER0_DISABLE TR0=0;

// Acc 累加器做发送的移位寄存器

sbit ACC0 = ACC^0;

sbit ACC1 = ACC^1;

sbit ACC2 = ACC^2;

sbit ACC3 = ACC^3;

sbit ACC4 = ACC^4;

sbit ACC5 = ACC^5;

sbit ACC6 = ACC^6;

sbit ACC7 = ACC^7;

//定时器计数器0的中断

void IntTimer0() interrupt 1

{

F_TM=1;

}

//发送一个字符

//数据格式一个启动位(0),8数据位,一个停止位(1)

void PSendChar(unsigned char Getch)

{

ACC=Getch;

F_TM=0;

BT_SND=0; //启动位

TIMER0_ENABLE; //记数器0启动

while(!F_TM) ;

BT_SND=ACC0; //先送出低位

F_TM=0;

while(!F_TM) ;

BT_SND=ACC1;

F_TM=0;

while(!F_TM) ;

BT_SND=ACC2;

F_TM=0;

while(!F_TM);

BT_SND=ACC3;

F_TM=0;

while(!F_TM);

BT_SND=ACC4;

F_TM=0;

while(!F_TM);

BT_SND=ACC5;

F_TM=0;

while(!F_TM);

BT_SND=ACC6;

F_TM=0;

while(!F_TM);

BT_SND=ACC7;

F_TM=0;

while(!F_TM);

BT_SND=1;

F_TM=0;

while(!F_TM);

TIMER0_DISABLE; //停止timer

}

//接收一个字符

unsigned char PGetChar()

{

unsigned char rch,ii;

TIMER0_ENABLE;

F_TM=0;

ii=0;

rch=0;

while(!F_TM); //等过起始位

while(ii<8)

{

rch>>=1;

if(BT_REC)

{

rch|=0x80;

}

ii++;

F_TM=0;

while(!F_TM);

}

F_TM=0;

while(!F_TM)

{

if(BT_REC)

{

break;

}

}

TIMER0_DISABLE; //停止timer

return rch;

}

//检查是不是有起始位

bit StartBitOn()

{

return (BT_REC==0);

}

void main()

{

unsigned char Getch;

TMOD=0x22; /*定时器1为工作模式2(8位自动重装),0为模式2(8位

自动重装) */

PCON=00;

TR0=0; //在发送或接收才开始使用

TF0=0;

TH0=(256-96); //9600bps 就是 1000000/9600=104.167微秒 执行的

//时间是104.167*11.0592/12= 96

TL0=TH0;

ET0=1;//定时器/记数器T0的溢出中断允许位,ET,允 许中断

EA=1;

while(1)

{

if(StartBitOn())

{

Getch=PGetChar();

PSendChar(Getch);

}

}

}

实验环境:

串口调试助手软件

AT89S51单片机及相应的硬件设备

win2000操作系统

原因分析如下:

PC的RS232像单片机发送1234567890字符串时,是连续一次发送的。当StartBitOn()检测到低电平起始位时,运行Getch=PGetChar()函数,显然上面说过要得到一帧的数据,就必须经过10个数据位的时间,同样运行PSendChar(Getch)函数时,也必须经过10个数据位的时间,且都是在忽略单片机本身执行指令的时间得到的。因而在当单片机接收了一个数据在接收下一位数据期间,必须至少消耗20个数据位的时间,等它在开始检测起始位时候,已经传输到第三个字符了,因而才会出现第上面的情况,当发送1234567890,而接收的字符是13579的原因。也就才会出现了很多工程师朋友们会对用软件实现的UART在可靠性和效率方面持怀疑态度的现象

if(StartBitOn())

{

Getch=PGetChar(); //采用移位方式要消耗10个数据位的时间

PSendChar(Getch); //采用移位方式要消耗10个数据位的时间

}

BT_REC 接收到的电平:

第1帧数据(10个数据位)第2帧(10个数据位)第3帧(10个起始位)

起始位1 起始位2 起始位3

参照上面的数据格式示意图知,当单片机StartBitOn()检测到起始位1并完成相应的接收转发Getch=PGetChar(); PSendChar(Getch),在进行下一次检测时,检测到的下一个起始位就是起始位3了。

综合上面分析可得出以下结论,在用软件模拟串行通讯时候,是以时间来模拟硬件设备的,用软件实现的UART的效率肯定没有办法和硬件UART比,在上叙连接时候,实际接收的数据确实只能有原来的一半,因为它是连续进行接收和发送两项工作的,但在实际应用中,可以通过一定的手段,比如先一次接收好PC所发送过来的所有数据,保存在预先设置的缓冲区里,稍后再去进行发送的工作,这样在接收的时候消耗的时间就只有10个数据位,在接收过程中不会丢失数据,能正确接收到所发送的所有字符。

提醒:《关于模拟串口的波特率的分析研究》最后刷新时间 2024-03-14 01:20:25,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《关于模拟串口的波特率的分析研究》该内容的真实性请自行鉴别。