[51单片机] C51和GSM模块之间串口通讯问题,求算法

[复制链接]
1356|7
 楼主| vincent.liu 发表于 2017-3-12 00:09 | 显示全部楼层 |阅读模式
我们知道要判断串口传过来的是不是某个字符好办, if (SBUF=='1'),就成,

如果要判断一个单词,或者判断GSM模块向C51串口,一段话传完了没有。就不知道怎么好了。。。
比如下面截图所示,有很多个段落,我具体量化一下我的问题。

下面截图显示的是GSM模块传给80C52串口的16进制经转换后的内容。
我的问题在下面几个方面:
1.如何判断GSM模块传回来的某一行中,具有CALL这个单词?
2.每次80C52向GSM模块发送一条指令后,GSM模块都会有回应。它的回应可能不止一句,有时是一句,比如返回OK,有时返回若干行。
我怎么知道GSM模块已经反馈完了呢?



GSM模块图如下:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
xyz549040622 发表于 2017-3-12 07:00 | 显示全部楼层
1.只能挨个判断了,把数据放缓存区中,碰到换行符就是一行到了,再在这行的数据中分割单词,查找你需要的单词。
2.返回OK,应该是有个固定的协议的,比如连续几个固定的字符,比如回车换行符等,找到结束帧就好了。
dirtwillfly 发表于 2017-3-12 10:15 | 显示全部楼层
也可以直接用c标准库里的字符串查找函数,或者自己实现一个函数
Gameparkwing 发表于 2017-3-12 14:40 | 显示全部楼层
本帖最后由 Gameparkwing 于 2017-3-12 15:16 编辑

程序可以分为两部分,读取一行和解析一行。
串口读入的字符保存到 str_from_uart[] 数组中,用变量 p_from_uart 做数量指示。
串口每接收到一个字节,调用一次 RespondReadLine() 函数。

变量 respond_string 和 respond_value 为每一次读取到的返回的数据值。
变量 respond_done 默认为 -1 ,表示无应答内容, respond_done == 0/1/2... 时,读取到一行返回的数据,程序中做相应的处理。

  1. unsigned int p_from_uart;
  2. unsigned char str_from_uart[255];
  3. unsigned char respond_string[16];
  4. unsigned int respond_value;
  5. signed int respond_done;

  6. /* 解析一行应答数据。 */
  7. void RespondParser()
  8. {
  9.     if (strstr(str_from_uart, "+CIEV") != NULL) {                                             // 存在有效应答值。
  10.         sscanf(str_from_uart, "%*[^"]"%[^"]"%*[^0-9]%d", respond_string, &respond_value); // 提取应答值。
  11.         respond_done = 2;                                                                     // 提取到应答数据。
  12.     } else {
  13.         // 判断应答结果, OK 或 ERROR。
  14.         if (strstr(str_from_uart, "OK") != NULL) {
  15.             respond_done = 1;                                                                 // 返回值为 OK 的情况。
  16.         } else if (strstr(str_from_uart, "ERROR") != NULL) {
  17.             respond_done = 0;                                                                 // 返回值为 ERROR 的情况。
  18.         } else {
  19.             respond_done = -1;                                                                // 无内容,不处理。
  20.         }
  21.     }
  22. }

  23. /* 读取一行应答数据。 */
  24. void RespondReadLine()
  25. {
  26.     if (str_from_uart[p_from_uart] == '\n') {                                                 // 遇到换行符,读取一行。
  27.         RespondParser();                                                                      // 解析一行应答数据。
  28.         p_from_uart = 0;                                                                      // 串口接收游标清零。
  29.     } else {
  30.         p_from_uart ++;                                                                       // 串口接收游标递增。
  31.     }
  32. }


lnulibin 发表于 2017-3-12 20:02 | 显示全部楼层
一般有AT命令的模块,比如WIFI转串口模块,语音播放/录制模块.都会有反馈信息.

从你给出的反馈字符截图来看.(当然你可能没有给出所有可能的反馈),只有"CALL"这个单词里面有A这个字母,其它单词中没有字母A,所以,你只要判断接收寄存器中是否为0X41即可.如果是0X41就说明收到了CALL.

当然,如果反馈信息中的其它单词中也有字母A,那这一招就不灵了.呵呵.

如果要搜索反馈信息中某一个单词,假设这个单词是8个字节,你只要构造一个队列数据结构来存放接收的数据即可.注意队列的长度大于8.

每接收到一个字节数据,要把新数据入队,挤出最老的数据.保证最后接收到的8个数据在队列中.搜索队列中有无你要的那个单词.(方法不说了)
ac62 发表于 2017-3-13 10:58 | 显示全部楼层
学习了
 楼主| vincent.liu 发表于 2017-3-13 16:05 | 显示全部楼层
Gameparkwing 发表于 2017-3-12 14:40
程序可以分为两部分,读取一行和解析一行。
串口读入的字符保存到 str_from_uart[] 数组中,用变量 p_from_ ...

谢谢,分数给你,请问如何结贴?
Gameparkwing 发表于 2017-3-15 23:57 | 显示全部楼层
vincent.liu 发表于 2017-3-13 16:05
谢谢,分数给你,请问如何结贴?

我还没发过帖,还真不知道如何结帖。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

63

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部