zoukankan      html  css  js  c++  java
  • 单片机模拟串口通讯注意事项

    波特率计算公式:方式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
    ");
        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;
    }

    实验现象:

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

        

  • 相关阅读:
    redhat 6安装详解
    使用pidstat查看进程资源使用情况
    (转)调优 DB2 UDB v8.1 及其数据库的最佳实践
    (转)LVS安装使用详解
    (转)[小工具] Linux下列格式化工具
    (转)zabbix3.4使用percona-monitoring-plugins监控mysql
    (转)zabbix之生产案例
    (转)CentOS7 LVM添加硬盘及扩容
    (转)计算机网络基础知识总结
    (转)网络基础之网络协议篇
  • 原文地址:https://www.cnblogs.com/xwtstudio/p/12602745.html
Copyright © 2011-2022 走看看