关于模拟串口的波特率的分析研究
时间:11-18
来源:互联网
点击:
(声明:本程序是以网上下载程序为基础,并根据需要做了适当修改得来的)
在用单片机开发各种嵌入式应用系统中,由于异步串行通讯连接简单,因而成为经常用到的一种通信模式,很多应用中还要求实现多路异步串行通信。为了提高系统的性能价格比,就要求设计工程师用软件增加实现一路或多路异步串行通信。本文即是对模拟串口的波特率做出的一点分析。
首先简单的介绍一下串行异步通讯的数据格式定义,发送或接收一个完整的字节信息,必须有“起始位”、“若干数据位”、“奇偶校验位”和“停止位”;定义每位信息的时间宽度——每秒发送的信息位个数,即为“波特率”。本文附带的模拟串口源程序采用数据帧的格式为 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
sbit BT_SND =P1^1;
sbit BT_REC =P1^0;
#define F_TM F0//自定义标志位,作为中断标志位
#define TIMER0_ENABLETL0=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(unsignedCHARGetch)
{
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
}
//接收一个字符
unsignedCHARPGetChar()
{
unsignedCHARrch,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()
{
unsignedCHARGetch;
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单片机及相应的硬件设备
在用单片机开发各种嵌入式应用系统中,由于异步串行通讯连接简单,因而成为经常用到的一种通信模式,很多应用中还要求实现多路异步串行通信。为了提高系统的性能价格比,就要求设计工程师用软件增加实现一路或多路异步串行通信。本文即是对模拟串口的波特率做出的一点分析。
首先简单的介绍一下串行异步通讯的数据格式定义,发送或接收一个完整的字节信息,必须有“起始位”、“若干数据位”、“奇偶校验位”和“停止位”;定义每位信息的时间宽度——每秒发送的信息位个数,即为“波特率”。本文附带的模拟串口源程序采用数据帧的格式为 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
sbit BT_SND =P1^1;
sbit BT_REC =P1^0;
#define F_TM F0//自定义标志位,作为中断标志位
#define TIMER0_ENABLETL0=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(unsignedCHARGetch)
{
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
}
//接收一个字符
unsignedCHARPGetChar()
{
unsignedCHARrch,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()
{
unsignedCHARGetch;
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单片机及相应的硬件设备
模拟串口波特 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)