单片机串口接收数据_单片机串口收发数据 - CSDN
  • 单片机串口接收多字节数据 2017年07月14日 16:52:13Phenixyf阅读数:7123 http://bbs.elecfans.com/jishu_409918_1_1.html 各位大侠看一下,我下面的程序为什么不能接收两个字节的数据呢? #include<reg51.h&...

    单片机串口接收多字节数据

    2017年07月14日 16:52:13 Phenixyf 阅读数:7123

    http://bbs.elecfans.com/jishu_409918_1_1.html

    各位大侠看一下,我下面的程序为什么不能接收两个字节的数据呢?
    #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两个字母呢?

     

    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    首先数据发送是一位一位发送的,串口接收也是一位一位接收的,当接收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. }

    复制代码

     

     

    受此贴启发,Starsky项目中,串口中断接收更改如下成功接收多字节:

    /*    串口接收数据中断服务函数    */
    #pragma vector = 0x14              //设置串口接收中断向量号 = 0X14 = 20
    __interrupt void UART1_RX_RXNE(void)
    {          
      static int cnt=0;


      UART1_SR_RXNE = 1;    //清除中断标志
      
      if(cnt == (COMBUFNUM-1))  //receive data done
      {    
        bufRec[cnt]= UART1_DR;  //last byte
        recCmd = bufRec[1];
        dutyPwm = (int) bufRec[2];
        cnt =0;
      }
      else{
        bufRec[cnt]= UART1_DR;
        cnt++;
      }
    }

    其中bufRec为接收buffer;

    UART1_DR为STM8S003F6 UART接收数据寄存器。

     

    展开全文
  • 单片机串口收发数据

    2015-06-29 14:11:49
    在中断函数中,如果接收数据则RI由硬件置1,这时候把SBUF缓冲区的数据赋值给Buffer,并将RI置0,等待下次接收。同时,将接收到的数据再放入缓冲区,发送给PC机。当发送完毕的时候TI会被硬件置1,这时候需要将TI置0...

    1单个字符的发送与接收

    在中断函数中,如果接收到数据则RI由硬件置1,这时候把SBUF缓冲区的数据赋值给Buffer,并将RI置0,等待下次接收。同时,将接收到的数据再放入缓冲区,发送给PC机。当发送完毕的时候TI会被硬件置1,这时候需要将TI置0,以待下次发送。

    #include <reg52.h>
    #define uint unsigned int
    #define uchar unsigned char
    //定义接收 字符
    uchar Buffer;
    /********************************************************************
                 功能:串口初始化,波特率9600,方式1
    *********************************************************************/        
    void   URATinit( )
    {
    TMOD=0x20;
    SCON=0x50;
    EA=1;
    ES=1;
    TR1=1;
    TH1=0xfd;
    TL1=0xfd;
    }
    /********************************************************************
                 功能:中断函数
    *********************************************************************/        
    void receive() interrupt 4
    {
     if(RI)
     { 
      Buffer=123;
      RI=0;
     }
     SBUF=Buffer;
     while(!TI);
     TI=0;
    }
    //主函数
    void  main()
    {
     URATinit( );
    }

    2 字符串接收

    在中断函数当中用Buffer[]接收收到的数据,同时将Buffer[]再发送给上位机。这里要注意变量i的定义。 如果定义为全局变量则Buffer[0-5]都可以接收到数据,需要对i计数,防止大于5溢出。

    #include <reg52.h>
    #define uint unsigned int
    #define uchar unsigned char
    //定义接收 数组
    uchar Buffer[5]={0};
    uchar i=0,j=0;


    //串口初始化函数
    void   URATinit( )
    {
     TMOD=0x20;
     SCON=0x50;
     EA=1;
     ES=1;
     TR1=1;
     TH1=0xfd;
     TL1=0xfd;
    }
    //中断函数
    void receive() interrupt 4
    {
     if(RI) //PC机向单片机发送命令是否被识别
     { 
      Buffer[i]=SBUF;
      RI=0; //清0准备下一次接收
     }
     SBUF=Buffer[i];
     while(!TI) ;
     TI=0;
     i++;
     if(i>=5){
      i=0;
     }
    }
    //主函数
    void  main()
    {
     URATinit( );
    }

    总结:单片机串口终端是怎么产生的


    你要用软件允许中断,
    即C语言中EA = 1; 允许总中断ES = 1;
    //允许串口中断汇编中可用 SETB EA ;允许总中断SETB ES ;
    允许串口中断当单片机接收到一帧数据后,RI会置1,向CPU申请中断,若之前有中断允许,则产生了中断,进入中断服务程序。
    当然,单片机发送完一帧数据,TI也会置1,同样会产生中断!
    一般我们在发送数据时要关中断,因为一般你不用在发送时不用处理数据;
    接收数据时要开中断,以便你在中断服务程序中将接收到的数据进行存储并处理。 

    不管你有没有允许中断,上位机(此时即给单片机发送信息的机器)只要给单片机发送数据,单片机就会自动接收数据,并把它放在数据缓冲器SBUF中,如果你之前有允许串行口中断,RI就会置1,向单片机CPU申请中断,并进入中断服务程序,做完中断函数后就会自动返回断点。如果你没有允许中断,便不会产生串行中断。其实,别的中断都是某个I/O口电平变化产生。这只是外部中断产生条件,不过,你之前也需要用软件允许外部中断。

    展开全文
  • /******************************串口1的波特率********************************///T1作波特率发生器//在波特率加倍情况下 #define BAUD_57600 256 - (OSC_FREQ/192L)/57600L // 254 FF#define BAUD_28800 ...

    #include "config.h"

    /******************************串口1的波特率********************************/
    //T1作波特率发生器
    //在波特率加倍情况下
    #define BAUD_57600 256 - (OSC_FREQ/192L)/57600L // 254 FF
    #define BAUD_28800 256 - (OSC_FREQ/192L)/28800L // 254 FE
    #define BAUD_19200 256 - (OSC_FREQ/192L)/19200L // 253 FD
    #define BAUD_14400 256 - (OSC_FREQ/192L)/14400L // 252 FC
    #define BAUD_9600 256 - (OSC_FREQ/192L)/9600L // 250 FA

     

    #define SYS_Fosc 11059200L //晶振频率
    uint32_t COMM_BAUD_RATE=9600 ; //串口波特率
    #define OSC_FREQ 11059200 //11059200

    static INT8U Send_buf[10] = {0} ;
    static INT8U Recv_buf[10] = {0} ;


    static INT8U SendDataLen = 0 ;
    static INT8U ResendDataLen = 0 ;
    /************************************************************************
    函 数 名: 串口初始化
    功能描述: STC10L08XE 单片机串口初始化函数
    返回函数: none
    其他说明: none
    **************************************************************************/
    void UartIni(void)
    {
    TMOD = 0x20; // 设置 T1 为波特率发生器
    SCON = 0x50; // 0101,0000 8位数据位, 无奇偶校验

    PCON = 0x00; //PCON=0;

    TH1=256-(SYS_Fosc/COMM_BAUD_RATE/32/12);//设置为9600波特率
    TL1=256-(SYS_Fosc/COMM_BAUD_RATE/32/12);

    TR1 = 1; //定时器1打开
    REN = 1; //串口1接收使能
    ES = 1; //串口1中断使能
    EA = 1;
    }
    //串口接受函数初始化1
    void UartIni1(void)
    {
    SCON = 0x50; //8-bit variable UART
    TMOD = 0x20; //Set Timer1 as 8-bit auto reload mode
    TH1 = TL1 = -(SYS_Fosc/12/32/COMM_BAUD_RATE); //Set auto-reload vaule
    TR1 = 1; //Timer1 start run
    ES = 1; //Enable UART interrupt
    EA = 1; //Open master interrupt switch
    }
    /***********************************************************
    * 名 称:
    * 功 能:
    * 入口参数: 无
    * 出口参数:无
    * 说 明:
    **********************************************************/
    void Uart_Isr() interrupt 4 using 1
    {
    if(RI)
    {

    }

    }
    /************************************************************************
    功能描述: 串口发送一字节数据 sbuf=data
    接受 data=sbuf
    入口参数: DAT:带发送的数据
    返 回 值: none
    其他说明: none
    **************************************************************************/
    void Uart_PutByte(uint8_t DAT)
    {
    ES = 0;
    TI=0;
    DAT=SBUF ;
    while(TI==0);
    TI=0;
    ES = 1;
    }
    ///*****************************************************************************************************
    // - 功能描述: 串口接受一帧数据
    // - 隶属模块: 内部
    // - 参数说明:
    // - 返回说明:
    // - 注:无
    //*****************************************************************************************************/
    void SendCmd(INT8U len )
    {
    INT8U i = 0 ;
    for(i=0; i<len; i++)//数据
    {
    Uart_PutByte(Send_buf[i]) ;
    }
    }

    ///********************************************************************************************
    // - 功能描述:求和校验
    // - 隶属模块:
    // - 参数说明:
    // - 返回说明:
    // - 注: 和校验的思路如下
    // 发送的指令,去掉起始和结束。将中间的6个字节进行累加,最后取反码
    // 接收端就将接收到的一帧数据,去掉起始和结束。将中间的数据累加,再加上接收到的校验
    // 字节。刚好为0.这样就代表接收到的数据完全正确。
    //********************************************************************************************/
    void DoSum( INT8U *Str, INT8U len)
    {
    INT16U xorsum = 0;
    INT8U i;

    for(i=0; i<len; i++)
    {
    xorsum = xorsum + Str[i];
    }
    xorsum = 0 -xorsum;
    *(Str+i) = (INT8U)(xorsum >>8);
    *(Str+i+1) = (INT8U)(xorsum & 0x00ff);
    }


    ///********************************************************************************************
    // - 功能描述: 串口向外发送命令[包括控制和查询]
    // - 隶属模块: 外部
    // - 参数说明: CMD:表示控制指令,请查阅指令表,还包括查询的相关指令
    // feedback:是否需要应答[0:不需要应答,1:需要应答]
    // data:传送的参数
    // - 返回说明:
    // - 注:
    //********************************************************************************************/
    void Uart_SendCMD(INT8U CMD ,INT8U feedback , INT16U dat)
    {
    Send_buf[0] = 0xff; //保留字节
    Send_buf[1] = 0x06; //长度
    Send_buf[2] = CMD; //控制指令
    Send_buf[3] = feedback;//是否需要反馈
    Send_buf[4] = (INT8U)(dat >> 8);//datah
    Send_buf[5] = (INT8U)(dat); //datal
    DoSum(&Send_buf[0],6); //校验
    SendCmd(8); //发送此帧数据
    }


    /************************************************************************
    功能描述: 串口发送字符串数据
    入口参数: *DAT:字符串指针
    返 回 值: none
    其他说明: API 供外部使用,直观!
    **************************************************************************/
    void PrintCom(uint8_t *DAT)
    {
    while(*DAT)
    {
    Uart_PutByte(*DAT++);
    }
    }

    /************************************************************************
    功能描述: 串口发送字符串数据 直接发送 hex 文件 0x0f
    等价于 0f
    入口参数: *DAT:字符串指针
    返 回 值: none
    其他说明: API 供外部使用,直观!
    **************************************************************************/
    void PrintCom1(uint8_t *DAT)
    {

    int i;
    for(i=0;i<12;i++)
    {
    Uart_PutByte(*DAT++); //Uart_PutByte 串口发送一字节数据 sbuf=data
    }
    }

     

    转载于:https://www.cnblogs.com/weiwenjietop/p/9343499.html

    展开全文
  • 在进行串口收发数据过程中一定要注意波特率的问题。 大多数51单片机用的都是11m晶振而只有少部分用的是奇葩的12m(楼主的就是),在12m晶振进行串口通信时切忌要将波特率设置为4800以下,应为12m晶振的波特率在9600...

    在进行串口的收发数据过程中一定要注意波特率的问题。

    大多数51单片机用的都是11m晶振而只有少部分用的是奇葩的12m(楼主的就是),在12m晶振进行串口通信时切忌要将波特率设置为4800以下,应为12m晶振的波特率在9600以上误差很大容易丢失数据,动手能力强的可以折腾一下用定时器输出9600波特率。

    至于,串口中断以及波特率的设置可以参考网上例子忒多。

    在用串口助手进行串口收发数据时都会触发串口中断并且在发送数据时只能够一位一位的发送,也就是SBUF=10是不行的智能一位一位发送也就是每次只能发送(0-9或者一个字符)并且串口调试助手接收到的数据是asii码要进行下转换,发送也要进行一下转换。这只是针对串口调试助手

    话不多说直接上代码:

     

    由于代码不方便公布所以只能上图片需要的可以私聊博主

     

     转载请标明原贴出处:https://blog.csdn.net/zj490044512

    展开全文
  • 单片机串口接收的几种常用的数据处理方法 一、为什么串口接收数据需要处理 我们在做项目的时候经常会用到串口,当我们用串口和别的设备通讯的时候就需要严格遵循通讯协议,然而,仅仅是遵循通讯协议是不够的,因为...
  • 51系列单片机 单片机串口通信接收发送数据程序
  • //------------------串口通信协议-----------------// /* 客户端数据包格式解释(长度恒为15): 例如:A01_fmq_01Off___# A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种) 01-----设备代号 fmq_01...
  • 今天在用51单片机进行串口收发数据的时候遇到了这样一个问题,上位机给单片机的字符数据是什么类型的,单片机又是怎样存储的?串口中断如下/* UART中断服务函数 */ void InterruptUART() interrupt 4 { if (RI) //...
  • 使用两个单片机开发版,串口3.0与3.1交叉互接,两个开发版分别烧写串口接收串口发送的单片机程序观察P0端口输出值的变化 ============接收串口单片机程序=========== #include <reg52.h> #define uchar...
  • STC单片机串口收发学习总结1字符串输出到串口2LED闪烁3LED流水灯4定时器5中断6定时与中断应用示例7数码管8串口9RS232接口 1字符串输出到串口 //////////////////////////////////////////////////////// //单片机...
  • 程序功能:接收上位机发过来的一个字符串,然后把该字符串发送给上位机, 字符串必须以!结尾 **********************/ #include &amp;lt;reg52.h&amp;gt; #define uchar unsigned char #define uint ...
  • 51单片机串口,是个全双工的串口,发送数据的同时,还可以接收数据。 当串行发送完毕后,将在标志位 TI 置 1,同样,当收到了数据后,也会在 RI 置 1。 无论 RI 或 TI 出现了 1,只要串口中断处于开放状态,...
  • 首先定义一个数据帧格式,Header :{ 0xAA 0x55} type:{ 0x01 | 0x02 | 0x03 } length:{ N } body :{____n个字节的数据___ } 数据的格式就是上面的定义 Header 为帧头 标记一个数据帧的开始,type 为类型 用来...
  • 普中单片机 串口 接收数据 控制灯亮灭 简介 1.硬件部分 普中单片机开发板 USB To TTL 2.软件部分 keil软件 串口调试助手 硬件部分 普中单片机开发板 一般的开发板即可 软件部分 /*--------------------------------...
  • 通过串口单片机发送数据,然后 数据 +1 返回串口 2. 功能实现 #include <reg52.h> #define uchar unsigned char #define uint unsigned int sbit beep = P2^3;//蜂鸣器接口 uchar num;//发送暂存变量 ...
  • 单片机串口接收数据

    2019-09-03 04:19:15
    char rx_char() // 由串行端口接收字符进来{while(1){if ( SCON & 0x01 ) == 0x01 ) // 判断数据接收是否准备好{break;}}clrbit ( SCON.0 ); ...
  • 单片机串口数据发送与接收源程序,已调试过啦
  • 用汇编语言编写的51单片机串口和模拟串口收发多个数据程序。单片机自带串口作为串口1,与上位机通讯。用外部中断模拟串口作为串口2,与现场仪表通讯。从单片机初始化到各个单元子程序均有。方便开发者使用。改程序...
  • 随着硬件系统的模块化发展,很多电子产品都做出模块并采用串口进行数据通信。例如:GPRS模块、GPS模块、语音模块、热敏微型打印机、串口摄像头等等。在与这些模块进行数据通信都离不开串口,而对于串口的操作,由于...
  • 转自:http://bbs.ednchina.com/BLOG_ARTICLE_3007162.HTM ... 串口接收程序是基于串口中断的,单片机串口每次接收到一字节数据产生一次中断,然后再读取某个寄存器就可以得到串口接收的数...
1 2 3 4 5 ... 20
收藏数 15,986
精华内容 6,394
关键字:

单片机串口接收数据