51单片机UART串口通信:接收PC字符串的实现

        基本思路是触发串口接收中断之后,在串口中断服务函数中处理接收到的字节并将其连接成字符串存入全局变量中。

隐含的额外工作有:

1.区分是发送中断还是接收中断,两者都会进入同一个中断服务子函数;

2.判断已接收到了句末,暂停接收,并通过标志位告知其他函数。

串口初始化省略,网上到处都是,但基本都是做到串口回声为止,教接收数据的少,所以着重讲如何接收字符串。

uart.h中需要添加的用于存放相关数据的全局结构体:

typedef struct
{
	u8 buff[65];    //用于存放接收到的字符串
	u8 flag;        //接收完成中断标志位
	u8 len;         //用于偏移字符串指针,可以理解为长度,如果buff设得很长,对应这里需要改成u16
}REC;

extern REC UART_rec;//设为全局

uart.c中中断服务子函数:


REC UART_rec={0};              //初始化结构体

void UART(void) interrupt 4
{
	u8 temp=0;
	RI=0;//清除接收中断标志
	temp=SBUF;
	if(temp==0||temp=='\r'||temp=='\n'||UART_rec.len>=65||temp=='{')
	{
	  UART_rec.buff[UART_rec.len]='\0';
	  UART_rec.flag=1;	//数据包接收完成标志
	  UART_rec.len=0; 	//为下一个数据包做准备
	}
	else
	{
	 UART_rec.buff[UART_rec.len++]=temp;
	} 

 其中:

if(temp==0||temp=='\r'||temp=='\n'||UART_rec.len>=65||temp=='{')

可以自定义各自接收完毕的标准,包括常规的回车以外还有到达指定长度结束以及MQTT数据包的封装'{',可以用来丢弃封装的开头节省一些字节之类的;

main.c测试:

void main (void)
{
    UART_Config();        //串口初始化,本文不涉及
    printf("Hello!\r\n");

    while(1)
    {
       if(UART_rec.flag)//若接收完成
        {
         printf("接收到了:%s\r\n",UART_rec.buff);
	     UART_rec.flag=0;     //接收标志位清零,准备接收下一字符串  
        }
    }

}

串口助手现象:

接收ASCII:

 接收中文:

接收带空格的句子(顺便测试了超出长度的情况):

不足:

1.必须要有句末的标志,若不发送\r、\n、\r\n结尾将不会结束接收;

2.某些情况下句末标志为\r\n时将会吞掉下一句的开头第一个字节,比如通过串口发送数据到PC之后的下一次接收不能接收以\r\n结尾的数据。评论区可以讨论一下解决方法,也教教我。

如果是STM32可以通过串口空闲中断来判断接收完毕,更稳妥,不会出现这两个问题

物联沃分享整理
物联沃-IOTWORD物联网 » 51单片机UART串口通信:接收PC字符串的实现

发表评论