单片机模拟串口通讯注意事项

波特率计算公式:方式1,3的波特率=1/32或1/16*计时器2的溢出率

        波特率=1/16或1/32*(晶振的频率/12*(256-TH1))

    

 

 

 

 串口工作在方式1时,分别采用T/C1和T/C2常用波特率初值表如下

 

 

 

 

 

 有关模拟串口波特率设置方法:

9600b/s -> 104us——>定时计数器工作方式2时,为了达到104us的延时间——>即在12MHZ的频率下计数104次

——>单片机采用+1方式计数,设置初值为(256-104)——>由于函数运行需要消耗一定的时间,所以设置初值

为(256-99)降低误差

 

 

51单片机定时计数器的4中工作方式:

工作方式 特点
0 定时器/计数器T0工作在方式0时,16位计数器只用了13位,即TH0的高8位和TL0的低5位,组成一个13位定时器/计数器。
1 定时器T0工作方式1与工作方式0类同,差别在于其中的计数器的位数。工作方式0以13位计数器参与计数,工作方式1则以16位计数器参与计数。
2

定时器T0在工作方式2时,16位的计数器分成了两个独立的8位计数器TH0和TL0。

3 工作方式3仅对定时器T0有效。当定时器T0工作在方式3时,将16位的计数器分为两个独立的8位计数器TH0和TL0。

串口相关寄存器:

 

 

 

 

串口通讯时序图:

 输出时序图:

 

 输入时序图:

 

 

用软件置REN为1时,接收器以所选择波特率的16倍速率采样RXD引脚电平,检测到RXD引脚输入电平发生负跳变时,则说明起始位有效,将其移入输入移位寄存器,并开始接收这一帧信息的其余位。接收过程中,数据从输入移位寄存器右边移入,起始位移至输入移位寄存器最左边时,控制电路进行最后一次移位。当RI=0,且SM2=0(或接收到的停止位为1)时,将接收到的9位数据的前8位数据装入接收SBUF,第9位(停止位)进入RB8,并置RI=1,向CPU请求中断。
————————————————
版权声明:本文为CSDN博主「To_dreams」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/to_dreams/java/article/details/7716678

 

单片机的中断信号方式:

 INT0 外部中断0请求,低电平有效。通过P3.2引脚输入。
 INT1 外部中断1请求,低电平有效。通过P3.3引脚输入
T0 定时器/计数器0溢出中断请求。
T1 定时器/计数器1溢出中断请求
TXD/RXD 串行口中断请求。当串行口完成一帧数据的发送或接收时,便请求中断。

 

有关51单片机中断的形式和C语言编程格式

void INT0() interrupt  0  using  1
{

}
interrupt  0    指明外部中断0
interrupt  1    指明定时器中断0
    .
    .
    .
    .

using 0 是第0组寄存器
using 1 是第1组寄存器

 

举例说明:

/*  外部中断程序 */
void ISR_Key(void) interrupt 0 using 1
{
    P1=~P1; //s3 按下触发一次, P1取反一次
}

/*   串口中断程序  */
void UART_SER (void) interrupt 4 // 串行中断服务程序
{
    unsigned char Temp; // 定义临时变量
    if(RI) // 判断是接收中断产生
    {
        RI=0; // 标志位清零
        Temp=SBUF; // 读入缓冲区的值
        P1=Temp; // 把值输出到 P1口,用于观察
        SBUF=Temp; // 把接收到的值再发回电脑端
    }
    if(TI) // 如果是发送标志位,清零
    TI=0;
}

            

 

单片机模拟串口通讯代码:

#include"reg52.h"
//定义数据的收发引脚与最大接收字节数
//#include "stdio.h"
//sbit RXD=P3^0;


//#define TXD    P3^1

#define RECEIVE_MAX_BYTES    16

#define TIMER_ENABLE()    {TL0=TH0;TR0=1;fTimeouts=0;}//使能T/C
#define TIMER_DISABLE()    {TR0=0;fTimeouts=0;}//禁止T/C
#define TIMER_WAIT()    {while(!fTimeouts)fTimeouts=0;}//等待T/C超时


unsigned char fTimeouts=0;//T/C超时溢出标志位
unsigned char RecvBuf[16];//数据接收缓冲区
unsigned char RecvCount=0;//接收数据计数器

//发送字节
void SendByte(unsigned char b)
{
    unsigned char i=8;
    TXD = 0;
    TIMER_ENABLE();
    TIMER_WAIT();
    while(i--)
    {
            if(b&1)
                TXD=1;
            else 
                TXD=0;
            TIMER_WAIT();
            b>>=1;
    }
    
        TIMER_ENABLE();
    TIMER_DISABLE();
    
}

//接收字节
unsigned char RecvByte(void)
{
    unsigned char i;
    unsigned char b=0;

    TIMER_ENABLE();
    TIMER_WAIT();
    for(i=0;i<8;i++)
    {
            if(RXD)
                b|=(1<<i);
            TIMER_WAIT();
            
    }
    
    TIMER_WAIT();//等待结束位
    TIMER_DISABLE();
    return b;
    
}
// 打印字符串
void PrintfStr(char *pstr)
{
    while(pstr && *pstr)
    {
        SendByte(*pstr++);
    }
}

//T/C初始化
void TimerInit(void)
{
    TMOD=0X02;
    TR0=0;
    TF0=0;
    TH0=(256-99);
    TL0=TH0;
    ET0=1;
    EA=1;
}


//是否有起始位到达
unsigned char StartBitCome(void)
{
    return (RXD==0);
}



//主函数

void main (void)
{
    unsigned char i;
    TimerInit();
    //printf("hello 80c52\r\n");
    while(1)
    {
        if(StartBitCome())
        {
                RecvBuf[RecvCount++] = RecvByte();
            if(RecvCount >= RECEIVE_MAX_BYTES)
            {
                RecvCount=0;
                for(i=0;i<RECEIVE_MAX_BYTES;i++)
                {
                    SendByte(RecvBuf[i]);
                }
            }
                
        }
    }
    
}

//定时器中断服务函数
void Timer0IRQ(void)    interrupt 1 using 0
{
    fTimeouts=1;
}

 

实验现象:

 由于波特率原因一直显示乱码不推荐使用模拟串口

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    

posted @ 2020-03-31 08:47  三字经  阅读(925)  评论(0编辑  收藏  举报