0x05 LiteOS_Lab仓库组件详解--AT(下)
AT框架关闭打印调试信息函数
该函数用于关闭AT打印调试信息,如果关闭了AT框架在收到数据时就不会进行相应的打印了。
1. int at_debugclose(void)
2. {
3. //for the debug
4. g_at_cb.rxdebugmode = en_at_debug_none; //本质上就是修改了结构体中的成员变量
5. g_at_cb.txdebugmode = en_at_debug_none;
6.
7. return 0;
8. }
发送AT指令函数
调函该函数可以将长度为cmdlen的cmd字符串指针指向的指令发送出去,并查看返回信息中是否含有index字符串指针指向的关键字,如果需要处理返回信息还可以传入长度为respbuflen的内存地址指针respbuf来接收返回信息,等待超时时间为timeout。
1. int at_command(const void *cmd,size_t cmdlen,const char *index,void *respbuf,\
2. size_t respbuflen,uint32_t timeout)
3. {
4. int ret = -1;
5. if(NULL == cmd)
6. {
7. return ret;
8. }
9. /* 如果需要判断回复信息中是否包含index关键词 */
10. if(NULL != index)
11. {
12. /* 创建一个命令结构体,用于发送和接收数据,并同步(信号量/互斥锁) */
13. ret = __cmd_create(cmd,cmdlen,index,respbuf,respbuflen,timeout);
14. if(0 == ret)
15. {
16. /* 调用底层发送函数将命令结构体中的数据发出 */
17. ret = __cmd_send(cmd,cmdlen,timeout);
18. if(0 == ret)
19. {
20. /* 通过挂起等待信号量获取回复 */
21. if(osal_semp_pend(g_at_cb.cmd.respsync,timeout))
22. {
23. ret = g_at_cb.cmd.respdatalen;//返回回复值的大小
24. }
25. else
26. {
27. ret = -1;
28. }
29. }
30. else
31. {
32. ret = -1;
33. }
34.
35. (void) __cmd_clear(); //清空命令结构体
36. }
37.
38. }
39. else //如果不需要处理回复,直接调用底层发送函数发送即可
40. {
41. ret = __cmd_send(cmd,cmdlen,timeout);
42. }
43.
44. return ret;
45. }
AT框架中的接收任务
在初始化AT框架时,就会创建一个接收任务。
例1:我们调用at_command函数发送完一帧数据时,并需要回复和处理回复,发送之后我们通过信号量的方式让当前任务(含有发送指令的这个任务)挂起,等待信号量,接收任务中会帮我们去查询和读取回复,只要收到回复,接受任务就会释放信号量,让刚才挂起的任务恢复,来处理回复数据。
例2:有的信息是异步的,例如nbiot设备收到了一条udp服务器下发的信息,正好我们之前通过at_oobregister函数注册了关键词处理函数,这时接收任务就会判断它收到的数据中是否含有index关键词(我们之前注册的“+NSONMI:”),它就会自动调用相应的处理函数帮我们处理数据。
1. static int __rcv_task_entry(void *args)
2. {
3. bool_t matchret;
4. int oobret;
5. int rcvlen = 0;
6.
7. g_at_cb.devhandle = los_dev_open(g_at_cb.devname,O_RDWR); //以读写方式开启设备
8. if(NULL == g_at_cb.devhandle) //检查设备操作句柄是否正确
9. {
10. LINK_LOG_DEBUG("%s:open %s err\n\r",__FUNCTION__,g_at_cb.devname);
11. return 0;
12. }
13.
14. while(NULL != g_at_cb.devhandle)
15. {
16. //streammode可能一帧数据分作分为多次下发,只要没有处理完一帧数据(rcvlen == 0),就一直累加
17. if (1 == g_at_cb.streammode) //in stream mode, we need to save previous frames in buffer
18. {
19. if(rcvlen == 0) //为接收缓存区清空一块大小为CONFIG_AT_RECVMAXLEN的内存
20. {
21. (void)memset(g_at_cb.rcvbuf,0,CONFIG_AT_RECVMAXLEN);
22. }
23. rcvlen += __resp_rcv(g_at_cb.rcvbuf+ rcvlen,CONFIG_AT_RECVMAXLEN,cn_osal_timeout_forever);
24. if( rcvlen > 0) //如果收到了数据,开始处理数据
25. {
26. matchret = __cmd_match(g_at_cb.rcvbuf,rcvlen); //判断接收到的数据中是否有cmd结构体中的index
27. if(0 != matchret)
28. {
29. oobret = __oob_match(g_at_cb.rcvbuf,rcvlen);//判断接收到的数据中是否有oob结构体中的index
30. if(oobret != -1)
31. {
32. rcvlen = 0;
33. }
34. }
35. else
36. {
37. rcvlen = 0;
38. }
39. }
40. }
41. else //一帧数据一定是一次下发完毕的
42. {
43. (void) memset(g_at_cb.rcvbuf,0,CONFIG_AT_RECVMAXLEN);
44. rcvlen = __resp_rcv(g_at_cb.rcvbuf,CONFIG_AT_RECVMAXLEN,cn_osal_timeout_forever);
45. if(rcvlen > 0)
46. {
47. matchret = __cmd_match(g_at_cb.rcvbuf,rcvlen);
48. if(0 != matchret)
49. {
50. (void) __oob_match(g_at_cb.rcvbuf,rcvlen);
51. }
52. }
53. }
54. }
55.
56. return 0;
57. }
- 点赞
- 收藏
- 关注作者
评论(0)