zoukankan      html  css  js  c++  java
  • 串口接收数据

    在stc89c52单片机的sfr特殊功能寄存器里面,有一个SBUF区域,是一个发送数据和接收数据公用的数据缓存区。当你的单片机发送数据的时候会先将数据存在这个缓冲区里面,累计一定量后再发送出去。接收数据的时候也会将接收的数据先存在这个缓存区里面,再去读取。也就是说接收数据的时候我们就去读这个缓冲区,发送数据的时候我们就往里面写入数据。

    还有sfr中的EA全局中断控制符,ES串口中断控制符,当我们要使用串口中断的时候这两个值都需要设置为1,以开启串口中断功能。

    sfr中的SMOD用于配置波特率。公式是:(2SMOD/32)*(定时器1的频率)。SMOD设置为1的时候是0的时候的两倍。

    sfr中的SM0和SM1来配置串口的工作模式。我们一般使用将SM0设置为0,SM1设置为1。这种方式它的博客率计算公式为(2SMOD/32)*(定时器1的频率)

    sfr中REN用于配置是否允许串口接收,1为允许接收,0为禁止接收。

    sfr中的TI为发送中断请求标志位。在发送完成后标志位变为1,需要我们再手动置为0。

    sfr中的RI为接收中断请求标志位。在接收完成后标志位变为1,需要我们再手动置为0。

    比较重要的是波特率的计算,首先它是根据定时器1的频率,和SMOD的值,和SM0和SM1两位设置的串口工作方式来决定的。这里我们将SM0设置为0,SM1设置为1后,波特率的计算公式就是(2SMOD/32)*(定时器1的频率),定时器1的频率就是1秒钟中断的次数。而定时器计数一次就是一个机器周期,这个周期和单片机型号和晶振型号又有关系,比如stc89c52是12T的也就是12次晶振周期为一个机器周期即计数一次,使用的晶振是11.0592MHz的也就是一秒11.0592*106次。那么一个机器周期就是1秒11.0592*106/12次。然后是设置定时器1多少次产生中断,这个值的设置在定时器那里有讲,也是就给定时器1的计数空间设置初始值。这里我们使用只用定时器1计数空间的一个8位并且中断后自动置为初始值的方式,也就是只能用一个8位来计数,最多也就256次计数,如果我们初值设位n,则计数256-n次后产生中断,所以定时器的频率变为11.0592*106/(12*(256-n))。波特率就变为(2SMOD/32)*  (11.0592*106/(12*(256-n)))。

    在下面的代码例子中我们将波特率设置位19200,也即是19200 = (21/32)*  (11.0592*106/(12*(256-n))),SMOD设置为1。解出n为253,十六进制就是0xFD。

    因为在串口通信的两端必须要将波特率设置为一致来能正常通信。波特率就是就是每秒钟传送的数据位数,bit/s(bps)。

    下面的代码是使用19200波特率,接收数据,如果接收到的数据是1就点亮第1个led灯(两秒后熄灭),2就是点亮第2个led灯(两秒后熄灭),依次类推,当超过8后就点亮全部led灯然后两秒后熄灭。

    #include <reg52.h>

    sbit LED0 = P0^0;
    sbit LED1 = P0^1;
    sbit LED2 = P0^2;
    sbit LED3 = P0^3;
    sbit LED4 = P0^4;
    sbit LED5 = P0^5;
    sbit LED6 = P0^6;
    sbit LED7 = P0^7;


    char rData = 0;
    char RFlag = 0;

    void UartInit(void)
    {
    TMOD = 0x20; //T1 方式2
    PCON = 0x80; //SMOD = 1
    SCON = 0x50; //方式1 8个数据位
    TH1=0xFD;
    TL1=0xFD;
    TR1 = 1; //启动定时器1
    ES=1; //开串口中断
    EA=1; //开总中断
    }

    void SerialInt() interrupt 4
    {
    RI = 0;
    RFlag = 1;
    rData = SBUF;
    }

    void DelayMs(unsigned int n)
    {
    unsigned int i,j;
    for(i = n; i > 0; i--)
    for(j = 114; j > 0; j--)
    ;
    }

    void LedOff(int i)
    {
    switch(i)
    {
    case 1:
    LED0 = 1;
    break;
    case 2:
    LED1 = 1;
    break;
    case 3:
    LED2 = 1;
    break;
    case 4:
    LED3 = 1;
    break;
    case 5:
    LED4 = 1;
    break;
    case 6:
    LED5 = 1;
    break;
    case 7:
    LED6 = 1;
    break;
    case 8:
    LED7 = 1;
    break;
    default:
    P0 = 0xFF;
    }
    }
    void LedOn(int i)
    {
    switch(i)
    {
    case 1:
    LED0 = 0;
    break;
    case 2:
    LED1 = 0;
    break;
    case 3:
    LED2 = 0;
    break;
    case 4:
    LED3 = 0;
    break;
    case 5:
    LED4 = 0;
    break;
    case 6:
    LED5 = 0;
    break;
    case 7:
    LED6 = 0;
    break;
    case 8:
    LED7 = 0;
    break;
    default:
    P0 = 0;
    }
    DelayMs(2000);
    LedOff(i);
    }


    void main()
    {
    UartInit();
    while(1)
    {
    if(RFlag)
    {
    RFlag = 0;
    LedOn(rData);
    }
    }
    }

     发送数据可以由另外的单片机来发送,需要外接线。由于单片机的usb数据线也带了转串口,所以可以在电脑上用usb连接单片机后使用软件模拟向单片机发送数据用来测试:

  • 相关阅读:
    php mysql基本操作
    php之curl的使用
    linux下操作php和apache
    ThinkPHP_目录结构和初始化
    ubuntu下计划任务cron的使用
    linux下操作mysql
    php操作csv文件
    HTML5基础一:常用布局标签
    liunx下shell脚本的创建和使用
    一个完整的ajax登陆实例
  • 原文地址:https://www.cnblogs.com/maycpou/p/13610425.html
Copyright © 2011-2022 走看看