前言

NB模组在广域物联网领域发挥越来越重要的作用,有些NB模组有一个特性:OPENCPU。这个是降低成本和减少布板空间的利器。这里就以移远通信的NB模组——BC26模组来开发OPENCPU应用。

开发环境简介

移远的OPENCPU开发环境是GCC加APP烧录工具;虽然有优势,但是开发上做了限制,有些库和功能不能使用。

这里贴一个工程的早期demo的Git,完成了MQTT的连接上传接收等的URC的处理,一些外设的测试:
https://github.com/JetLinWork/BC26_MQTT_OPENCPU

这边做了OPENCPU的应用开发之后的一点经验和看法。

硬件上:虽然单模组的布板空间有所缩小,但没有想象那么多,因为模组电平是1.8V的域,基本的IO输出和外设交互都需要电平转换,这里占用空间就不少(分立或集成)。电源的驱动上确实低了2G模组很多,现在一个USB就能带起来。

软件上:在windows上开发,使用的是移远提供的SDK和Flash烧录工具。按照开发手册的步骤来就可以进行开发。虽然说是使用FreeRTOS但是开放的OS的API很少,只有信号量和TASK之间的message传输。在编译上限制了 像<string.h>等库的使用,提供了部分替代函数,第三方的C库移植带来了很大的麻烦。貌似触发任务调度的方式只有等待任务间message,其他的好像不行(待确认)。

详细的开发的环境介绍和开发步骤参见Git里面的/doc/下的手册   Quectel_BC26-OpenCPU_User_Guide_V10.pdf  开发手册里面有的内容我这里就不再赘述了。

在SDK里面也提供了很多外设驱动使用的例程。

URC开发

URC ( Unsolicited Result Code )就是不同于AT指令发了一个就会马上回复一个OK/ERR这种,而是一些类似中断不定时出现不知道对应那条AT发送指令的内容,例如MQTT接收到的数据就会以URC数据的方式发送到URC的处理任务。暂时有的URC的处理有TCP/LWM2M/ONENET等有限的API,不过开放了源码,你只需要按照这些例程去开发自己想要的URC接收处理函数就可以了。

关于URC的开发的内容手册里面基本没有提及,但是这个对于功能的开发来说是至关重要的,因为官方提供的功能不可能尽善尽美,总有需要自己去开发的地方。

这里就以开发MQTT组件的URC为例,URC的接收处理源文件为 ril_urc.c。

有一个结构体数组,存储了对应URC的特征字符和对应的处理函数

//片段1
/****************************************************/
/* Definitions for AT URCs and the handler          */
/****************************************************/
const static ST_URC_HDLENTRY m_AtURCHdlEntry[] = {{"\r\n+QIURC:",OnURCHandler_QIURC_DATA},{"\r\n+QLWDATARECV:",OnURCHandler_LwM2M_RECV_DATA},{"\r\n+QLWOBSERVE:",OnURCHandler_LwM2M_OBSERVE},{"\r\n+MIPLEVENT:",OnURCHandler_ONENET_EVENT},{"\r\n+MIPLOBSERVE:",OnURCHandler_ONENET_OBSERVER},{"\r\n+MIPLDISCOVER:",OnURCHandler_ONENET_DISCOVER},{"\r\n+MIPLWRITE:",OnURCHandler_ONENET_WRITE},{"\r\n+MIPLREAD:",OnURCHandler_ONENET_READ},{"\r\n+MIPLEXECUTE:",OnURCHandler_ONENET_EXECUTE},{"\r\n+QIND: \"FOTA\"",OnURCHandler_DFOTA_Hander},{"\r\n+QMTRECV:",OnURCHandler_QMTRECV_Hander},  {"\r\n+QMTOPEN:",OnURCHandler_QMTOPEN_Hander},   {"\r\n+QMTCONN:",OnURCHandler_QMTCONNECT_Hander},    {"\r\n+QMTSUB:",OnURCHandler_QMTSUB_Hander},{"\r\n+QMTSTAT:",OnURCHandler_QMTSTAT_Hander},
};//片段2
/*****************************************************************
* Function:     OnURCHandler
*
* Description:
*               This function is the entrance for Unsolicited Result Code (URC) Handler.
*
* Parameters:
*               strURC:
*                   [IN] a URC string terminated by '\0'.
*
*               reserved:
*                   reserved, can be NULL.
* Return:
*               The function returns "ptrUrc".
*****************************************************************/
void OnURCHandler(const char* strURC, void* reserved)
{s32 i;if (NULL == strURC){return;}// For system URCsfor (i = 0; i < NUM_ELEMS(m_SysURCHdlEntry); i++){if (Ql_strstr(strURC, m_SysURCHdlEntry[i].keyword)){m_SysURCHdlEntry[i].handler(strURC, reserved);return;}}// For AT URCsfor (i = 0; i < NUM_ELEMS(m_AtURCHdlEntry); i++){if (Ql_strstr(strURC, m_AtURCHdlEntry[i].keyword))    //这里处理接收到的指定URC{m_AtURCHdlEntry[i].handler(strURC, reserved);return;}}// For undefined URCsOnURCHandler_Undefined(strURC, reserved);
}

例如接收到的URC字符串包含"\r\n+QIURC:"字段,就执行OnURCHandler_QIURC_DATA(const char* strURC, void* reserved);函数处理对应URC;

static void OnURCHandler_QIURC_DATA(const char* strURC, void* reserved)
{/*----------------------------------------------------------------*//* Local Variables                                                *//*----------------------------------------------------------------*/u8* p1 = NULL;s32 ret;u8 strTmp[10];u32 recv_length = *(char*)reserved;p1 = Ql_strstr(strURC, "+QIURC:");p1 += Ql_strlen("+QIURC: ");recv_length -= (Ql_strlen("+QIURC: ") + 2);   // two means head '\r\n'char* param_buffer = (u8*)Ql_MEM_Alloc(SOCKET_RECV_BUFFER_LENGTH);char* param_list[20];/*----------------------------------------------------------------*//* Code Body                                                    *//*----------------------------------------------------------------*/if (p1){extern bool recv_data_format;       u32 param_num = open_socket_push_json_param_parse_cmd(p1, recv_length, param_buffer, param_list, 20); char* prefix = param_list[0];   //  recvQl_memset(strTmp, 0x0,  sizeof(strTmp));ret = QSDK_Get_Str(p1,strTmp,0);if(Ql_memcmp(strTmp,"\"recv\"",Ql_strlen("\"recv\"")) == 0){socket_recv_param.connectID = Ql_atoi(param_list[1]);socket_recv_param.recv_length = Ql_atoi(param_list[2]);if ( param_num == 4){char* recv_buffer = param_list[3];Ql_memset(socket_recv_param.recv_buffer, 0x0, SOCKET_RECV_BUFFER_LENGTH);if ( recv_data_format == 0 ) //text{Ql_memcpy(socket_recv_param.recv_buffer, recv_buffer, socket_recv_param.recv_length);}else if ( recv_data_format == 1 ) //hex{Ql_memcpy(socket_recv_param.recv_buffer, recv_buffer, socket_recv_param.recv_length*2);}socket_recv_param.access_mode = SOCKET_ACCESS_MODE_DIRECT;}else {socket_recv_param.access_mode = SOCKET_ACCESS_MODE_BUFFER;}Ql_OS_SendMessage(URC_RCV_TASK_ID, MSG_ID_URC_INDICATION, URC_SOCKET_RECV_DATA, &socket_recv_param);}else if(Ql_memcmp(strTmp,"\"closed\"",Ql_strlen("\"closed\"")) == 0){Ql_memset(strTmp, 0x0,  sizeof(strTmp));QSDK_Get_Str(p1,strTmp,1);socket_recv_param.connectID = Ql_atoi(strTmp);Ql_OS_SendMessage(URC_RCV_TASK_ID, MSG_ID_URC_INDICATION, URC_SOCKET_CLOSE,socket_recv_param.connectID);}}if ( param_buffer != NULL ){Ql_MEM_Free(param_buffer);param_buffer = NULL;}
}

自己写URC其实也就是依样画葫芦,将所需要的接收字段的特征字符和处理函数写好即可,可以参见给出的Git工程。

OPENCPU执行AT指令

其实OPENCPU的执行AT命令也是极为重要的功能,一下是该函数的片段,调用AT指令其实除了返回的结果有些URC的处理也是其一部分。这个函数相当于是涵盖所有AT手册包含的命令。

/******************************************************************************
* Function:     Ql_RIL_SendATCmd
*
* Description:
*                This function implements sending AT command with the result
*                being returned synchronously.The response of the AT command
*                will be reported to the callback function,you can get the results
*                you want in it.
*
* Parameters:
*                atCmd:
*                     [in]AT command string.
*                atCmdLen:
*                     [in]The length of AT command string.
*                atRsp_callBack:
*                     [in]Callback function for handle the response of the AT command.
*                userData:
*                     [out]Used to transfer the customer's parameter.
*                timeOut:
*                     [in]Timeout for the AT command, unit in ms. If set it to 0,
*                         RIL uses the default timeout time (3min).
*
* Return:
*                RIL_AT_SUCCESS,succeed in executing AT command, and the response is OK.
*                RIL_AT_FAILED, fail to execute AT command, or the response is ERROR.
*                               you may call Ql_RIL_AT_GetErrCode() to get the
*                               specific error code.
*                RIL_AT_TIMEOUT,send AT timeout.
*                RIL_AT_BUSY,   sending AT.
*                RIL_AT_INVALID_PARAM, invalid input parameter.
*                RIL_AT_UNINITIALIZED, RIL is not ready, need to wait for MSG_ID_RIL_READY
*                                      and then call Ql_RIL_Initialize to initialize RIL.
******************************************************************************/
typedef s32 (*Callback_ATResponse)(char* line, u32 len, void* userData);
extern s32 Ql_RIL_SendATCmd(char*  atCmd, u32 atCmdLen, Callback_ATResponse atRsp_callBack, void* userData, u32 timeOut);  

移远NB模组(BC26)OPENCPU开发——MQTT上传接收相关推荐

  1. 移远BC20模组使用LwM2M协议接入华为IoT平台(NB-IoT专栏—进阶篇2)

    目录 1.背景 2.部署华为云 3.华为云与BC20模组进行数据收发实验 1.背景 最近在做一个智慧路灯项目,构思使用STM32结合NB-IoT模组实现数据上传和联动控制,并且可以使用GPS模块上传路 ...

  2. OpenHarmony3.1适配移远EC20模组4G上网功能

    OpenHarmony3.1适配移远EC20模组4G上网功能 一.概述 通过阅读本篇文档,您将学习到如何适配移远EC20模组到OpenHarmony3.1(以下简称OHOS),并添加4G上网功能. 本 ...

  3. 移远BC35-G模组(NB-IoT 通信模组)AT指令测试 UDP 通信过程

    移远BC35-G NB-IoT模组 BC35-G 是一款高性能.低功耗的多频段 LTE Cat NB1 (NB-IoT) 无线通信模块,支持 B1/B3/B8/B5/B20/B28 频段,尺寸仅为23 ...

  4. 移远 EC200S 模组(4G Cat.1 通信模组)AT指令测试 TCP/UDP 通信过程

    移远EC200S 4G Cat.1 模组 EC200S-CN 是移远通信推出的LTE Cat 1 无线通信模块,支持最大下行速率10Mbps 和最大上行速率5Mbps,具有超高的性价比. 同时在封装上 ...

  5. 移远5G模组RM500U-CN在Win11下的短信和通话演示

    关键词:移远  5G  展锐芯片组  RM500U-CN  短信  text  通话  拨号   概述:5G模组主要用于跑数据流量,但其实基础的短信功能也还是支持的.而且,虽然没有音频接口,但是呼入呼 ...

  6. 使用移远EC200N-CN模组PING谷歌

    目录 概述 AT指令 数据处理 提取数据 注意事项 概述 本文记录下使用EC200N-CN模组ping谷歌官网的测试过程.ping谷歌主要是摸底下设备在海外的联网丢包.延迟等情况.其实主要是为了记录下 ...

  7. 移远BC35-G模组通过LWM2M协议接入OneNet教程

    首先平台配置: 1.注册OneNet账号(通过访问OneNet官网进入注册): 2.进入控制台,选择"全部产品服务"--"NB-IoT物联网套件": 3.添加产 ...

  8. 树莓派4+lede+移远5G模组RM500Q

    0. 环境 win10 树莓派4 + lede rm500q // 内核文件夹 // /home/xxjianvm/lede/build_dir/toolchain-aarch64_cortex-a7 ...

  9. 移远RM500Q_5G模组规格书

    Quectel RM500Q是一个5G模块,专门为IoT/eMBB应用程序优化. 采用3GPP Rel. 15LTE技术,它支持5GNSA和SA模式. 设计在一个M.2的形式因素,RM500Q是 兼容 ...

  10. NB模组(BC28/NB86-G)使用域名接入华为云方法

    现象 截止目前(2020-05-21),移远NB模组BC28在使用域名的情况下无法接入华为云平台,利尔达的NB模组NB86-G使用域名接入未测试. 方法 通过AT指令进行域名解析,得到IP后使用IP接 ...

最新文章

  1. MyBatis架构分层
  2. java bio_Java BIO及实现
  3. 京东网络开放之路——自研交换机探索与实践
  4. ASP.NET MVC Display Mode 移动端视图 配置对微信内置浏览器的识别
  5. couchdb 任意命令执行漏洞 cve-2017-12636
  6. SQL SERVER 通用分页存储过程
  7. How to change in the Cocos2d-x project from landscape to portrait both in iOS and Android
  8. error LNK2001: unresolved external symbol _WinMain@16
  9. 基础学习——C语言递归解决分鱼问题
  10. mysql 5.5 1366错误_laravel5.3 在 mysql5.1中运行出错 error: 1366 Incorrect integer
  11. P53:进化了8亿年的抑癌基因
  12. web前端前景近几年怎么样,是否饱和?
  13. HDU 3669 Cross the Wall(斜率DP+预处理)
  14. java 异常哪个包,这个提示包不存在的异常是咋回事
  15. 服务器搭建网站完整教程(宝塔面板+wordpress) 快速搭建网站 一键部署
  16. 关于setTimeout的面试题
  17. 【收藏】韦东山嵌入式Linux课程梳理|随时更新
  18. GB35114—③、证书和密钥要求、基本功能要求及性能要求
  19. iOS 9键盘类型合集
  20. 面向视频领域的边缘计算白皮书

热门文章

  1. 线性回归模型-误差分析
  2. 改进平滑滚动,修改音量调节级数实现音量微调【编译自XDA 适用于大部分设备】
  3. Number of ways to split should evenly divide the split dimension, but got split_dim 3 (size = 4) and
  4. 1.1 PMBOK指南的目的 -- 项目管理知识体系指南(PMBOK指南)(第五版)
  5. 深入理解各种图片格式
  6. 逆糖计划教大家一个轻松控糖的口诀
  7. 普通程序员如何正确学习人工智能方向的知识?
  8. win10商店打不开_win10应用商店的卸载和安装
  9. ecshop mysql 标题表_ECSHOP商城全站自定义TITLE标题设置
  10. ctf:xls加密_加密:爱丽丝和鲍勃的故事