IAP15W413AS工业自动化控制之【16串口收发字符串】

  • SingleYork
  • LV5工程师
  • |      2017-09-13 10:44:13
  • 浏览量 1871
  • 回复:6
本帖最后由 SingleYork 于 2017-9-16 16:45 编辑 bg1.png

前一讲中,笔者跟大家介绍了如何让单片机实现串口收发单个字符,这一讲笔者要跟大家分享一下,如何让单片机实现串口收发字符串。相信,很多小伙伴对单个字符的收发是很熟悉了,但是对字符串的收发却有点头疼,确实,对字符串的操作,笔者也是花了不少时间才搞明白,那么笔者跟大家一起分享一下学习的成果吧。

首先,我们要明白,比如单片机字符串在存储的时候,其实是有一个特定的结束符'\0'的,也就是说,假设我们要定义一个一维数组Arry存放一个字符串"HelloIcKey!",他实际上在数组里面是按如下方式存放:

Arry = 'H';

Arry = 'e';

Arry = 'l';

Arry = 'l';

Arry = 'o';

Arry = 'I';

Arry = 'c';

Arry = 'K';

Arry = 'e';

Arry = 'y';

Arry = '!';

Arry = '\0';

也就是说,我们想要存储字符串的长度为10,实际上他要占用11个BYTE,这个时候如果我们要定义用来存放字符串的一维数组的时候,这个数组的长度就要特别注意了!应该是Arry = {"HelloIcKey!"};,或者跟笔者一样,直接不指定长度:Arry = {"HelloIcKey!"};

明白了这一点,那就好办了!接下来我们分析一下单片机接收字符串需要注意些什么。如果是接收指定长度的字符串,相信大家都知道该怎么处理,定义一个一维数组用来存放将要接收到的字符串,从数组的0号元素开始存放,直到接收完指定个长度后接收完成。这样比较简单,笔者就不多说了,笔者要跟大家介绍的是接收不定长度的字符串。那么这个不定长度的字符串要怎么处理呢?

我们一般的做法是,在字符串末尾加一个特定的结束符,一般是用“回车符”来作为结束符,当然我们也可以用“空格”来作为结束符,本例中, 笔者通过“回车符”和“空格”两种结束符来做对比进行讲解。为什么要用这两种而不是只介绍一种就好了呢,后面笔者会跟大家解释这个问题。

那么基本的理论知识分析完毕了,我们接下来看下程序部分吧,在串口中断函数中我们写入如下代码:

/********************* UART1中断函数************************/

void UART1_int (void) interrupt UART1_VECTOR

{

  if(RI)

  {

    RI   = 0;



    ReciveData = SBUF;       //将串口收到的数据存放到ReciveData中



    if((ReciveData == '\n')||(ReciveData == ' '))//接收到结束符,接收完成

    {

      Uart1RXFinish = 1;        //将接收完成标志位置1

    }

    else

      RX_CNT ++;  //接收计数加“1”

  }



        if(TI)

        {

                TI           = 0;

                COM1.TX_Busy = 0;

        }

}

逻辑很简单,就是接收到“回车符”或者“空格”的时候,接收完成,然后我们自定义一个发送函数,将接收到的数据发送出去:

/********************* 串口1发送命令************************/

void Uart1_Send(void)

{

  if(Uart1RXFinish)        //收到数据,自动将接收到的数据返回

        {

    if(COM1.TX_Busy == 0)

    {

      COM1.TX_Busy = 1;                                                //标志发送忙

      

      SBUF   = ReciveData;  //将接收到的字符串发送出去,单字节发送

      

      if(COM1.TX_read>RX_CNT)

      {

        RX_CNT        = 0;

        Uart1RXFinish = 0;

        COM1.TX_read  = 0;

      }

    }

        }

}

如果仅仅只是要实现串口收发字符串,那么这样就搞定了!但是,实际应用中我们并不只要完成收发就算完事了!我们可能会需要用字符串作为命令,发送给单片机,然后单片机接收到不同命令后执行相关的动作。比如,我们发送字符串“LED_ON”让单片机板上的LED亮,发送“LED_OFF”让单片机板上的LED灭。那么这个功能要怎么实现呢?

其实,只要我们能正确接收到字符串了,要实现上述功能也就不难了!这里我们需要用到字符串比较函数,笔者这里自己重定义了一个字符串比较函数:

//对比字符串str1和str2

//*str1:字符串1指针

//*str2:字符串2指针

//返回值:0,相等;1,不相等;



u8 Str_Cmp(u8 *str1,u8 *str2)

{

        while(1)

        {

                if(*str1!=*str2)return 1; //不相等

                if(*str1=='\0')break;     //对比完成了.

                str1++;

                str2++;

        }

        return 0;//两个字符串相等

}

笔者这里通过将接收到的字符串跟设定的字符串比较,如果不相等,则让OUT00亮,OUT01灭;如果相等,则让OUT00灭,OUT01亮。

/*将接收到的字符串跟设定的字符串做对比,执行相应的动作*/

      if(Str_Cmp(Arry,RxArry)==1) //若两个字符串不相等

      {

        OUT00 = ON;

        OUT01 = OFF;

      }

      else                        //若两个字符串相等

      {

        OUT00 = OFF;

        OUT01 = ON;

      }

本例中以字符串“HelloIcKey!”为例,我们应该都知道,发送字符串的时候,都是以ASCII的形式发送。那么我们先来看下“空格”跟“回车符”的ASCII码:

从上面两张图我们可以看到,“空格”的十六进制ASCII码是0x20占用一个字节,“回车符”的十六进制ASCII码是0x0D,0x0A,占用两个字节,说到这里,大家应该可以理解笔者为什么要用这两种方式来做对比了。

首先,如果是加入“空格”作为结束符的话,我们利用串口监控软件可以看到发送的数据如下,末尾多了一个0x20,即为“空格”ASCII码的十六进制:

如果是加入“回车”作为结束符的话,我们利用串口监控软件可以看到发送的数据如下,末尾多了一个0x0D,0x0A,即为“回车”ASCII码的十六进制:

所以,在这两种方式下,我们用于存放接收数据的一维数组里面存放的可能就是这样的数据:

1、用“空格”作为结束符时,ReciveData = {"HelloIcKey! + 0x20"}(这里只是形象说明一下,实际这种语法是不对的);

2、用“回车”作为结束符时,ReciveData = {"HelloIcKey! + 0x0D + 0x0A"}(这里只是形象说明一下,实际这种语法是不对的);

这样就会导致接收到的数据长度也不一样,我们实际设定好的要用来做对比的字符串是Arry = {"HelloIcKey!"},前面说了,字符串存储的时候是会有一个结束符'\0'的,那么就相当于Arry = {"HelloIcKey! + '\0'};由于这两种方式下接收到的数据长度不一样,那么就会影响到我们发送时的数据,如果我们要在发送字符串的后面加上结束符'\n'的话,就得分两种情况了:

 if(ReciveData == '\n')//若是收到回车符0x0D 0x0A

        RxArry = '\0';    //给新的字符串加入结束符

      

      if(ReciveData == ' ') //若是收到空格

        RxArry = '\0';      //给新的字符串加入结束符

不多说,我们将程序下载到板子中,来看下实验现象吧:

添加“空格”结束符

添加“回车”结束符

从上面两个结果中,我们可以看到,字符串的收发是OK的,那么接下来我们再看下字符串对比的结果:

正确的字符串

OUT00亮,OUT01灭

错误的字符串

OUT00灭,OUT01亮

从上面的结果我们可以看到,字符串对比也是OK的,好了,有关单片机收发字符串的知识就简单分享到这里了,由于笔者能力有限,欢迎大家提问一起交流,完整代码详见附件!

源代码:

  • 0
  • 收藏
  • 举报
  • 分享
我来回复

登录后可评论,请 登录注册

所有回答 数量:2
Sourcelink 2017-09-15
大佬就是厉害
0   回复
举报
发布
7943603 回复 2017-09-15
:$,请叫我小兵。
0   回复
举报
7943603 2017-09-13
Arry = {"HelloIcKey!"} 这个直接写成*array ="HelloIcKey!"就可以啦,然后指针指向之,发送。 p=*array++; send(*p); 即可。
0   回复
举报
发布
x
收藏成功!点击 我的收藏 查看收藏的全部帖子