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;
    }

    实验现象:

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

        

  • 相关阅读:
    AJAX异步传输——以php文件传输为例
    js控制json生成菜单——自制菜单(一)
    vs2010中关于HTML控件与服务器控件分别和js函数混合使用的问题
    SQL数据库连接到服务器出错——无法连接到XXX
    PHP错误:Namespace declaration statement has to be the very first statement in the script
    【LeetCode】19. Remove Nth Node From End of List
    【LeetCode】14. Longest Common Prefix
    【LeetCode】38. Count and Say
    【LeetCode】242. Valid Anagram
    【LeetCode】387. First Unique Character in a String
  • 原文地址:https://www.cnblogs.com/xwtstudio/p/12602745.html
Copyright © 2011-2022 走看看