微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 51单片机串口如何接收多位字节数据

51单片机串口如何接收多位字节数据

时间:10-02 整理:3721RD 点击:
各位大侠看一下,我下面的程序为什么不能接收两个字节的数据呢?
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
void rs232_init();
uchar flag,i,g,d;
uchar code table[]="I get ";
//sbit led=P1^0;
main()
{
        rs232_init();
        while(1)
        {
                if(flag==1)
                {
                        ES=0;
                        for(i=0;i<6;i++)
                        {
                                SBUF=table[i];
                                while(!TI);
                                TI=0;
                        }
                        SBUF=g;
                        while(!TI);
                        TI=0;
                        SBUF=d;
                        while(!TI);
                        TI=0;
                        ES=1;
                        flag=0;
                }               
        }
}
void rs232_init()
{
        TMOD=0x20;
        TH1=0xfd;
        TL1=0xfd;
        TR1=1;
        REN=1;
        SM0=0;
        SM1=1;
        EA=1;
        ES=1;       
}
void ser()interrupt 4
{
        RI=0;
        g=SBUF;
        d=SBUF;
        flag=1;
}
我用串口调试助手调试时,上位机给单片机发送两个字节的数据,例如发送ck两个字母时,只接收到cc两个字母呢?

很久没用c语言了,研究研究先

首先数据发送是一位一位发送的,串口接收也是一位一位接收的,当接收8位数据后,申请中断。
你的程序中,程序进入中断后,你用了g=SBUF,d=SBUF,程序之所以进入中断是因为串口接收到了八位数据,是八位数据,不是十六位数据,也就是你发送的字母ck中的c,k还没有发送完呢,所以g和d都被赋值了c,打印结果当然是cc了。
你要了解串口是接收八位数据后申请中断,你必须在下一个八位数据接收完(下一次中断到来前)以前取走这个数据,不然这个数据将会丢失。
我给你改 的程序如下,我定义一个宏N,N就是你每次发送的数据个数,然后一个数组,数组有N个元素,用于存储串口接受的数据。
当串口有中断时,我立即把这个数据存储到数组中,同时将数组指针指向下一位,然后当下一个中断来时重复上面步骤,直到接收数据个数到达N。
这里中断中程序不能太长,如果程序很长,我本次数据还没存储好,下一个数据已经到了,会丢失数据。

  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. #define N 2                                                        //可一次接收数据量
  5. void rs232_init();
  6. uchar flag,i;                                                       //删除无用变量                          
  7. uchar code table[]="I get ";
  8. uchar table1[N];                                              //接收缓存数组
  9. uchar j=0;                                                             //接收计数器
  10. //sbit led=P1^0;
  11. main()
  12. {
  13.          rs232_init();
  14.          while(1)
  15.          {
  16.                  if(flag==1)
  17.                  {
  18.                          ES=0;
  19.                          for(i=0;i<6;i++)
  20.                          {
  21.                                  SBUF=table[i];
  22.                                  while(!TI);
  23.                                  TI=0;
  24.                          }
  25.                          for(j=0;j<N;j++)                        //发送接收数组
  26.                                                  {
  27.                                                          SBUF=table1[j];
  28.                                  while(!TI);
  29.                                  TI=0;
  30.                                                 }
  31.                          j=0;                                           //清零接收计数器
  32.                          ES=1;
  33.                          flag=0;
  34.                  }               
  35.          }
  36. }
  37. void rs232_init()
  38. {
  39.          TMOD=0x20;
  40.          TH1=0xfd;
  41.          TL1=0xfd;
  42.          TR1=1;
  43.          SM0=0;
  44.          SM1=1;
  45.                  REN=1;                                                        //先设定号工作方式,在打开允许接收
  46.          EA=1;
  47.          ES=1;        
  48. }
  49. void ser()interrupt 4
  50. {                 
  51.                 RI=0;
  52.                 table1[j++]=SBUF;                                //存数据到接收缓存
  53.                 if(j==N)                                                //数组满时,允许发送
  54.                 flag=1;
  55. }

复制代码

非常非常感谢你!我想了一天了也没想通

谢谢,我也受益。

谢谢,我也受益。

嗯,高手如云,一起学习,谢谢了

一起学习啊,O(∩_∩)O谢谢

楼上的高手,请问一下,用串口怎样显示从DS18B20读出的温度值呢?谢谢。

一个字节一个字节地接收,不能同时,爱收多少都可以。

用上crc16校验会更好。

谢谢小编分享11111111111111111111

好难懂啊...不过收益匪浅...

收益匪浅..收益匪浅..

你好,我按照您的程序修改了一下,把“i get”的数组重新赋值,把多位数输入进去,为什么输出的数字会不同呢(已转换ascii码)我把num的位数调到3却可以正常输出,6位就不能了

  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. #define N 6                                                        //可一次接收数据量
  5. void rs232_init();
  6. uchar flag,i,d,num;
  7. uint n;                                                      //删除无用变量                           
  8. uchar table[6];
  9. uchar table1[N];                                              //接收缓存数组
  10. uchar j=0;                                                             //接收计数器
  11. //sbit led=P1^0;
  12. main()
  13. {
  14.          rs232_init();
  15.          while(1)
  16.          {
  17.                          //        num++;
  18.                                 n=100000;num=348965;
  19.                                 for(i=0;i<6;i++)
  20.                          {                                                                
  21.                                                     d=(int)(num/n);
  22.                                                         num=(int)(num-n*d);
  23.                                                         d=(char)(d+0x30);
  24.                                                        
  25.                                                         n=n/10;
  26.                             table[i]=d;
  27.                                                   }
  28.                  if(flag==1)
  29.                  {
  30.                          ES=0;
  31.                          for(i=0;i<6;i++)
  32.                          {
  33.                                  SBUF=table[i];
  34.                                  while(!TI);
  35.                                  TI=0;
  36.                          }
  37.                          for(j=0;j<N;j++)                        //发送接收数组
  38.                                                  {
  39.                                                          SBUF=table1[j];
  40.                                  while(!TI);
  41.                                  TI=0;
  42.                                                 }
  43.                          j=0;                                           //清零接收计数器
  44.                          ES=1;
  45.                          flag=0;
  46.                  }               
  47.          }
  48. }
  49. void rs232_init()
  50. {
  51.          TMOD=0x20;
  52.          TH1=0xfd;
  53.          TL1=0xfd;
  54.          TR1=1;
  55.          SM0=0;
  56.          SM1=1;
  57.          REN=1;                                                        //先设定号工作方式,在打开允许接收
  58.          EA=1;
  59.          ES=1;        
  60. }
  61. void ser()interrupt 4
  62. {                 
  63.                 RI=0;
  64.                 table1[j++]=SBUF;                                //存数据到接收缓存
  65.                 if(j==N)                                                //数组满时,允许发送
  66.                 flag=1;
  67. }

复制代码

嗯,高手如云,一起学习,谢谢了

高人啊,你写的这个程序能接收5个字节的数据么

谢谢

想学习都应该建个微信群哈哈

一看小编就知道是个初学者,数据的定义大小不分,建议去看下char,int等的范围

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top