×
单片机 > 单片机程序设计 > 详情

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

发布时间:2020-06-19 发布时间:
|
   (声明:本程序是以网上下载程序为基础,并根据需要做了适当修改得来的)
   在用单片机开发各种嵌入式应用系统中,由于异步串行通讯连接简单,因而成为经常用到的一种通信模式,很多应用中还要求实现多路异步串行通信。为了提高系统的性能价格比,就要求设计工程师用软件增加实现一路或多路异步串行通信。本文即是对模拟串口的波特率做出的一点分析。
   首先简单的介绍一下串行异步通讯的数据格式定义,发送或接收一个完整的字节信息,必须有“起始位”、“若干数据位”、“奇偶校验位”和“停止位”;定义每位信息的时间宽度——每秒发送的信息位个数,即为“波特率”。本文附带的模拟串口源程序采用数据帧的格式为 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                         |
|           | -------------            -------------------------------
源程序:
/**********************************************
IO 口模拟232串行异步通讯程序

**********************************************/
#include
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单片机及相应的硬件设备
关键字:模拟串口  波特率 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
8051单片机的函数发生器的设计