• 主要解决51单片机串口通讯中的数据出错,或数据保存在SBUF中影响接下来的数据接收

    在51单片机中,我们使用上下位机时,我们通常会发送一串字符串,将它作为信号发给单片机处理。

    因为串口通信时,发送信息是以一个个字符的形式发送过来的,所以接收的就是一个个字符,通常我们是一个字符数组保存,在进行下一步处理,同时字符数组长度固定有限,但是如果上位机发送的字符不满足我们想要处理的数据时,其接收的数据多出的部分就有可能保存在SBUF中, 影响接下来的数据接收,以至于接下来的数据不满足我们的要求。或是发送数据少于数组长度时,也会出错。

    在这里我的解决办法(以下以STC12C5A60S2芯片为例):

    void serial_port_one_init()
    {                       //根据自己单片机设置;

        //22.1184M   波特率: 115200
        SCON = 0x50; 
        BRT = 0xFA;
        AUXR |= 0x04;
        AUXR |= 0x01;
        AUXR |= 0x10;
       ES      =   1;    
       EA      =   1;    
    }                   

    #define Data_SIZE 10 //数据长度   9位数据 +  /r/n  -  /n =10位

    char RevBuf[Data_SIZE];      //数据接收缓冲区
    char temp[Data_SIZE];        //防数据抵消缓冲区
    unsigned char flished_flag=0; //数据接收符合要求标志
    int data_count=0;    //数据长度
    int temp_length;    //数据长度
    int data_flished_count = 0;  //
    char data_flished;           //

    void UART_one_Interrupt_Receive(void) interrupt 4
    {  
        uchar temp;
      if(RI==1)
        {
            RI=0;
            temp=SBUF;
    //        senduart(temp);  //用来测试过数据接收是否正确
            
            if(temp!='\n') //判断是否接收到结束符
            {
                RevBuf[data_count]=temp;// 否,就存到RevBuf【】数组中
                data_count++;
            }
            else
            {
                temp_length=data_count;//是,记录其数据长度
                data_count=0;
            }
            
        }
        
    }             


    void main(void)

    {

        serial_port_one_init();  //串口初始化

       while(1)

        {

              if(Data_SIZE == temp_length)   //判断数据长度是否满足我们的要求。
            {
                for(i=0;i<Wifi_Data_SIZE;i++)
                {
                    temp[i]=RevBuf[i];             // 同时我们将temp【】作为缓冲区,防止数据被冲到
                }
                flished_flag=1;          //数据接收成功标志
            }

          if(1==flished_flag)  //     数据接收完整成功
            {
                
                wifi_flished_flag=0;  //

               //

               //你想要实现的功能

    /*

    switch(temp[1]) //我常把数据第一位或前几位作为指令,后几位作为数据,你也可以把整个发送的数据就作为指令。

    {

    case 'A' :

    //具体操作

    break;

    }

             */

            }

        }

      while(1);

    }

    同时某些特殊情况,我们会将数据写成:数据头+数据  

    分析数据头,实现其代表的功能

    上位机中 要在发送数据的最后加上 ‘/n’这个字符

    用串口工具测试时, 发送数据为:数据+enter键(其代表的是两个字符 /r /n)



    展开全文
  • 主要是能接收字符串
  • 最近由于要调试一个SMS发送短信的模块,该模块需要发送一系列AT指令,且需要字符串发送,但是STM32官方给的usart.c中并没有直接发送字符串的函数,因此写了一个发送字符串的函数。 其实发送字符串的本质还是发送一...

    最近由于要调试一个SMS发送短信的模块,该模块需要发送一系列AT指令,且需要字符串发送,但是STM32官方给的usart.c中并没有直接发送字符串的函数,因此写了一个发送字符串的函数。

    其实发送字符串的本质还是发送一个个字符,所以只需在字符串结束标志之前,循环发送字符即可。不罗嗦,上程序。

    //程序功能:利用串口发送一个字符串

    // 参数:USARTx USART编号 可取 USART1、USART2、USART3、USART4、 USART5(STM32F103ZET6)

    str 需要发送的字符串

    #include “stm32f10x.h”

    void Usart_SendString(USART_TypeDef* USARTx,char *str)

    {

    while(*str)

    {

    while(!USART_GetFlagStatus(USARTx,USART_FLAG_TXE)); //判断是否可以发送

    USART_SendData(USARTx,*str);

    while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)); //判断是否发送完成,此句必须有,否则会造

    //成只发送最后一个字符(覆盖)

    str++;

    }

    }

    方法二:
    const u8 TEXT_Buffer[]={“Explorer STM32F4 SPI TEST”};
    #define SIZE sizeof(TEXT_Buffer) ;

    for(i=0;i<SIZE;i++)
    {
    USART2->DR =TEXT_Buffer[i];
    delay_ms(10);
    }

    展开全文
  • 转自:... #include //------------------串口通信协议-----------------// /* 客户端数据包格式解释(长度恒为15): 例如:A01_fmq_01Off___# A--------数据包的开始标记(可以为A到Z,意味

    转自:http://www.cnblogs.com/weifeng727/category/845655.html


    #include<reg52.h>
    
    //------------------串口通信协议-----------------//
    /*
        客户端数据包格式解释(长度恒为15):
        例如:A01_fmq_01Off___#
        A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)
        01-----设备代号
        fmq_01Off___--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部
        #---------数据包的结束标记
    
        服务器端数据包格式解释(长度恒为15):
        例如:A02_SenT010250#
        A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)
        02-----设备代号
        SenT010250--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部
        #---------数据包的结束标记
    */
    char buf_string[16];  //定义数据包长度为15个字符
    #define deviceID_1Bit '0'                //用于串口通信时,定义本地设备ID的第1位
    #define deviceID_2Bit '2'                //用于串口通信时,定义本地设备ID的第2位
    #define datapackage_headflag 'A'        //用于串口通信时,定义数据包头部的验证标记
    
    char DataPackage_DS18B20[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','S','e','n','T','X','X','X','X','X','X','#'};
    char HeartBeat[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','B','e','a','t','X','X','X','X','X','X','#'};
    //----------------------------------------------//
    /*******************************
                串口通信
        MCU:89C52RC        11.0592MHz
    
    //11.0592MHz 0xd0 1200bps
    //12MHz 0xcc 1200bps
    //11.0592MHz 0xfa 9600bps
    //0xf4 11.0592MHz  0xf3 12MHz 4800bps
    //均在SMOD=1的情况下(波特率倍增模式)
    *******************************/
    //串口发送函数
    void PutString(unsigned char *TXStr)  
    {                
        ES=0;     
         while(*TXStr!=0) 
        {                      
            SBUF=*TXStr;
            while(TI==0);
            TI=0;    
            TXStr++;
        }
        ES=1; 
    }                                                     
    //串口接收函数
    bit ReceiveString()    
    {
        char * RecStr=buf_string;
        char num=0;
        unsigned char count=0;
        loop:    
        *RecStr=SBUF;
        count=0;
        RI=0;    
        if(num<14)  //数据包长度为15个字符,尝试连续接收15个字符
        {
            num++;
            RecStr++;    
            while(!RI)
            {
                count++;
                if(count>130)return 0;    //接收数据等待延迟,等待时间太久会导致CPU运算闲置,太短会出现"数据包被分割",默认count=130
            }
            goto loop;
        }
        return 1;
    }
    //定时器1用作波特率发生器
    void Init_USART()  
    {
        SCON=0x50;  //串口方式1,使能接收
        TMOD|=0x20;  //定时器1工作方式2(8位自动重装初值)
        TMOD&=~0x10;
        TH1=0xfa;   //9600bps
        TL1=0xfa;  
        PCON|=0x80;  //SMOD=1
        TR1=1;
        TI=0;
        RI=0;
        //PS=1;   //提高串口中断优先级
        ES=1;  //开启串口中断使能
    }
    //比较指令头部
    bit CompareCMD_head(char CMD_head[])    
    {
        unsigned char CharNum;
        for(CharNum=0;CharNum<4;CharNum++)  //指令长度为10个字符
        {
            if(!(buf_string[CharNum+4]==CMD_head[CharNum]))
            {
                return 0;  //指令头部匹配失败
            }
        }
        return 1;        //指令头部匹配成功
    }
    //比较指令尾部(start:从哪里开始比较,quality:比较多少个字符,CMD_tail[]:要比较的字符串)
    bit CompareCMD_tail(unsigned char start,unsigned char quality,char CMD_tail[]) 
    {
        unsigned char CharNum;
        for(CharNum=0;CharNum<quality;CharNum++)
        {
            if(!(buf_string[start+CharNum]==CMD_tail[CharNum]))
            {
                return 0; 
            }
        }
        return 1;
    }
    bit Deal_UART_RecData()   //处理串口接收数据包函数(成功处理数据包则返回1,否则返回0)
    {
        //PutString(buf_string);
        if(buf_string[0]==datapackage_headflag&&buf_string[14]=='#')  //进行数据包头尾标记验证
        {        
            switch(buf_string[1])        //识别发送者设备ID的第1位数字
            {
                case '0':
                    switch(buf_string[2])        //识别发送者设备ID的第2位数字
                    {
                        case '3':
                            if(CompareCMD_head("Ligt"))    //判断指令头部是否为"Ligt"
                            {
                                //下面是指令尾部分析
                                switch(buf_string[8])
                                {
                                    case '0':
                                        switch(buf_string[9])
                                        {
                                            case '0':            
                                                
                                                return 0;
                                            case '1':
                                                if(CompareCMD_tail(10,3,"Off"))   //A03_Ligt01Off_#
                                                {
                                                    //要执行的代码
                                                    return 1;
                                                }
                                                if(CompareCMD_tail(10,3,"On_"))
                                                {
                                                    
                                                    return 1;
                                                }
                                                return 0;
                                            default:
                                                return 0;
                                        }
                                    case '1':
                                        
                                    default:
                                        return 0;
                                }            
                            }
                            if(CompareCMD_head("SenT"))  
                            {
                                            
                                
                            }
                            if(CompareCMD_head("jdq_"))  
                            {
                                
                                
                            }
                            if(CompareCMD_head("Try!"))  
                            {
                                
                                
                            }
                            return 0;
                        
                        default:
                            return 0;
                    }
                default:
                    return 0;
            }
        }
        return 0;
    }
    /************************
            中断函数
    ************************/
    //串口中断服务函数-----------
    void USART() interrupt 4   //标志位TI和RI需要手动复位,TI和RI置位共用一个中断入口
    {
        if(ReceiveString())    
        {
            //数据包长度正确则执行以下代码
            Deal_UART_RecData();   
        }
        else
        {
            //数据包长度错误则执行以下代码
            //LED1=~LED1;                
        }
        RI=0;  //接收并处理一次数据后把接收中断标志清除一下,拒绝响应在中断接收忙的时候发来的请求
    }
    /***************************
            主函数
    ***************************/
    void main()
    {
        EA=1;
        Init_USART();
        while(1)
        {
            //PutString(buf_string);//空格20H,回车0DH
            
        }
    }


    展开全文
  • 在FPGA中也是比不可少,本专题实现FPGA的串口收发字符串,属于Uart通信,通信方式:串行、异步、全双工的。用verilog实现,包括以下几个模块:串口发送模块、串口接收模块、波特率发生器模块、字符串接收与发送调度...

    1、总体概述

    串口通信是一种常见的通信方式。在FPGA中也是比不可少,本专题实现FPGA的串口收发字符串,属于Uart通信,通信方式:串行、异步、全双工的。用verilog实现,包括以下几个模块:串口发送模块、串口接收模块、波特率发生器模块、字符串接收与发送调度模块(可以独立于串口接收模块,这里的输入数据位并行的,主要是为了将要待发送字符串(来自其他模块)进行数据重组(本次的通信外部设备为HMI,其字符串控制指令具有特定的字符串格式))、按键发送字符模块(包含按键消抖模块),以下从各模块及书写和调试中遇到的问题进行详细说明。本次实例实现FPGA控制HMI屏(串口屏),在屏幕上显示相应的字符串数据。

    NOTE:异步通信指的是通信的发送与接收方使用各自的时钟控制数据的发送和接收过程,具体就是:以字符(一帧数据)为单位进行传输,字符与字符见的间隙是任意的,但字符内部各bit位是一固定时间传送的(即在固定波特率的控制下进行)。通信的传输方向为全双工,指的时数据可以同时双向传输(实际上感觉这一点的作用并不是太大,因为很多时候不需要同时双向,一般是当接收到某个特定数据时,再向外发送某个数据,这已经暗含了非同时的特点,但它一定有特殊的应用场合)。

    2 USART_Send模块

    本次收发模块采用的是10bit为一帧数据的传输方式,串口发送模块的数据输入为8位并行数据(数据收入一个时钟周期就完成,速度很快),故需要将接收到的数据进行重组(即加上起始位0和停止位1),随后在波特率的控制下调度数据移位串行输出。发送模块的输入需要一个发送请求脉冲,用于作为启动波特率发生器的标志(控制移位输出)。

    代码如下:
    主要包括:请求信号到来写入数据、数据移位操作和数据位数计数模块
    <请求信号到来写入数据>

    /*************请求信号到来写入数据****************/
    //请求信号到来,写入数据并置位波特率启动位
    always @ (posedge clk, negedge rst_n)
    begin
    	if (!rst_n)
    		tx_bps_start <= 1'b0;
    	else if (req_send) 	 	 		  	  	 	    	  	 	 //请求信号有效,将输入写入到datain_buf1中
    		tx_bps_start <= 1'b1;                      	 	 //波特率启动标志,直到停止位变为0
    	else if (bit_cnt == 4'd10)
    		tx_bps_start <= 1'b0;
    end
    
    always @ (posedge clk, negedge rst_n)
    begin
    	if (!rst_n)
    		datain_buf1 <= {(PORT_WID + 1){1'b0}};
    	else if (req_send)
    		datain_buf1 <= {1'b1, datain[7 : 0], 1'b0}; 	 	 //10位数据帧格式,0位起始位,9位停止位;
    end
    
    

    <数据移位操作>

    reg 	 	 	 	 	 	 	 dat_flag;
    /*************数据移位操作****************/
    always @ (posedge clk, negedge rst_n)
    begin
    	if (!rst_n)
    	begin
    		datain_buf2 <= {(PORT_WID + 1){1'b0}};
    		dat_flag <= 1'b0;
    	end
    	else if (tx_bps_flag)
    	begin
    		datain_buf2 <= datain_buf1 >> bit_cnt;
    		dat_flag <= 1'b1; 	 	 	 	  	 	 	 	  	 	
    	end
    	else
    		dat_flag <= 1'b0;
    end
    
    assign TXD = tx_buf; 
     
    assign TI = ti_buf;
    always @ (posedge clk, negedge rst_n)
    begin
    	if (!rst_n)
    		ti_buf <= 1'b0;
    	else if (bit_cnt == 4'd10)
    		ti_buf <= 1'b1;
    	else
    		ti_buf <= 1'b0;
    end
    
    always @ (posedge clk, negedge rst_n)
    begin
    	if (!rst_n)
    		tx_buf <= 1'b1;
    	else if (dat_flag) 	  	   	 	 	 		 	 //不是tx_bps_flag一到就赋值给tx_buf,顺延一个周期
    		tx_buf <= datain_buf2[0]; 	 		 	 	    //为了避免datain_buf2初始赋值的影响
    	else if (!tx_bps_start)
    		tx_buf <= 1'b1;
    end
    

    <数据位数计数>

    /*************数据位数计数****************/
    always @ (posedge clk, negedge rst_n)
    begin
    	if (!rst_n)
    		bit_cnt <= {DATA_WID{1'b0}};
    	else if (tx_bps_flag)
    		bit_cnt <= bit_cnt + 1'b1;
    	else if (bit_cnt >= 4'd10)
    		bit_cnt <= {DATA_WID{1'b0}};
    end
    

    在这里,先附上整个串口和发送程序的时序图,以方便理解。

    在这里插入图片描述
    这一节先写到这,主要是串口的发送模块,下一节更新接收模块。
    NOTE:完整代码连接
    https://download.csdn.net/download/huigeyu/11156523
    如有需要,请自行下载!

    展开全文
  • /*******************************************...功能:将整形转换为ascii码字符串 示例:dat = 12345 buffer[10]  转换后  buffer[0] = '1'  buffer[1] = '2'  ...  buffer[4] = '5'  buffer[5] = '\n'

    /************************************************
    功能:将整形转换为ascii码字符串
    示例:dat = 12345   buffer[10]
          转换后
       buffer[0] = '1'
       buffer[1] = '2'
       ...
       buffer[4] = '5'
       buffer[5] = '\n'
    **********************************************/
    void DtoA(unsigned long dat, unsigned char* buffer)
    {
      unsigned long tmp = dat;
      char length = 0;

      while(tmp != 0)//求出数字的实际长度
      {
        tmp = tmp/10;
        length++;
      }
      buffer[length] = '\0';//长度数为字符串截止位
      length--;

      while(length >= 0)//数字的低位放入数组的高位
      {
        tmp = dat%10;
        buffer[length--] = 0x30|tmp;

        dat = dat/10;
      }  
    }

    /****************************************************
    功能:将ascii码字符串(非ascii也可)转换成对应数字

    unsigned char code date[] = "1234567";     ->   返回 1234567
    unsigned char code date_neg[] = "-1234567";      ->   返回 -1234567
    ****************************************************/
    long mi(unsigned char dat, unsigned char mi)
    {
      unsigned char i;
      long sum = 1;

      for(i=0; i<mi; i++)
      {
        sum = sum * dat;         
      }

      return sum;
    }

    long AtoD(unsigned char* buffer)
    {
       long dat = 0, tmp = 0,k;
       unsigned char i;
       char j = 0;

       i = strlen(buffer);
       if(buffer[0] == '-')
       {
          j = 1;   
       }
       for(; j<i; j++)
       {
            tmp = buffer[j]&0x0f;//如果原数组中存放的是ascii码,直接将其转换为数字
       k = mi(10,i-j-1);
       tmp = k * tmp;
       dat += tmp;
        }

        if(buffer[0] == '-')
        {
          return -dat;
        }
     
        return dat;
    }

    void SendString(unsigned char* String)
    {
      int i=0;
      while(String[i] != '\0')
      {
        SendData(String[i]);
        i++;
      }
    }
    void SendDig(long dat)
    {
      char buffer[36];
      DtoA(dat, buffer);
      SendString(buffer);
    }

    展开全文
  • 今天在用51单片机进行串口收发数据的时候遇到了这样一个问题,上位机给单片机字符数据是什么类型的,单片机又是怎样存储的?串口中断如下/* UART中断服务函数 */ void InterruptUART() interrupt 4 { if (RI) //...
  • STC15F104单片机模拟串口 接收 比较字符串
  • 之前对串口各模块的设计都做了相关介绍。这里介绍串口屏的相关知识。...一般地,使用单片机或者嵌入式MCU控制串口屏,都会用到串口,同样地,在FPGA中实现也是类似,不过稍微复杂,具体代码设计过程中有以下问题需要...
  • STC单片机串口收发学习总结1字符串输出到串口2LED闪烁3LED流水灯4定时器5中断6定时与中断应用示例7数码管8串口9RS232接口 1字符串输出到串口 //////////////////////////////////////////////////////// //单片机...
  • 51单片机串口程序,字符串16进制发送与接收.docx
  • 51单片机用uart 把接收到的字符串 自动显示在串口调试助手上的代码。
  • 51单片机,串口1和串口2,通讯程序,目前仅是60s2,通过修改配置文件可以达到所有串口通用,传输字节可根据单片机大小进行调节,可传输字符串也可以传输十六进制
  • 双串口同时工作,该函数方便你进行串口调试
  • 分为:单个字符接收,字符串接收;十进制发送与接收,十六进制发送与接收。 字符串发送与十六进制发送,参考:http://blog.csdn.net/wityy/article/details/8234739 程序皆由PC串口工具发送,由单片机接收,并返回...
  • 【串口收发实验】从串口助手发送一个字符或者一个字符串到开发板,开发板又将收到的字符或者字符串回送到串口助手上。
  • BEEP BIT P2.3 LCDEN BIT P3.4 LED BIT P1.0 ORG 0000H LJMP MAIN MAIN: MOV TMOD,#20H MOV TH1,#0FDH MOV TL1,#0FDH SETB TR1 MOV SCON,#40H ANL PCON,#7FH MOV DPTR,#TABLE ...MOV R1,#00H
  • 在MSP430单片机的官方历程中有使用串口中断发送字符以及字符串的程序,但是移植性不高,我专门写了两个函数,用于发送单个字符合字符串,不需要使用中断,供大家参考。/*******************************************...
  • 在进行串口的收发数据过程中一定要注意波特率的问题。 大多数51单片机用的都是11m晶振而只有少部分用的是奇葩的12m(楼主的就是),在12m晶振进行串口通信时切忌要将波特率设置为4800以下,应为12m晶振的波特率在9600...
  • 串口接收中断函数一次只能接收一个字,接收一个字符串并存下常用方法: ①设置标志位:如在末尾加入标志位’\r’,’\n’;前缀+数据+后缀 ②定时判断接收数据的长度,如果在规定时间内,长度没有什么变化,证明已经...
1 2 3 4 5 ... 20
收藏数 2,255
精华内容 902