本文主要讲解移远NBIOT模组BC26 OpenCPU方式对接OneNET,使用的是BC26_OpenCPU_SDK_V1.2:https://github.com/sanjaywu/BC26_OpenCPU_SDK_V1.2。为方便调试,还会涉及到BC26_OpenCPU UART的讲解。
一、实现UART打印调试信息
1、宏定义打印信息的UART端口
这里采用UART0来打印信息,同事UART0也用于发送AT命令和下载程序。
#define APP_DEBUG_PORT UART_PORT0
2、注册UART0和打开UART0端口
注册UART0,并大开UART0端口,让UART0能发送和接收数据。
Ql_UART_Register(APP_DEBUG_PORT, CallBack_UART_Hdlr, NULL); /* CallBack_UART_Hdlr为回调函数 */
Ql_UART_Open(APP_DEBUG_PORT, 115200, FC_NONE); /* 波特率为115200,无流控制 */
3、实现调试打印信息功能
通过宏定义来说实现一个打印调试信息功能。
#define DBG_BUF_LEN 1024
static char DBG_BUFFER[DBG_BUF_LEN];
#define APP_DEBUG(FORMAT,...) \
{\
Ql_memset(DBG_BUFFER, 0, DBG_BUF_LEN); \
Ql_sprintf(DBG_BUFFER,FORMAT,##__VA_ARGS__); \
Ql_UART_Write((Enum_SerialPort)(APP_DEBUG_PORT), (u8*)(DBG_BUFFER), Ql_strlen((const char *)(DBG_BUFFER))); \
}
4、CallBack_UART_Hdlr回调函数的实现
CallBack_UART_Hdlr为回调函数主要实现实时读取串口是否有接收到数据,主要用于AT指令的接受和处理。
static void CallBack_UART_Hdlr(Enum_SerialPort port, Enum_UARTEventType msg, bool level, void* customizedPara)
{
switch (msg)
{
case EVENT_UART_READY_TO_READ:
{
if (APP_DEBUG_PORT == port)
{
s32 totalBytes = ReadSerialPort(port, m_RxBuf_Uart, sizeof(m_RxBuf_Uart));
if (totalBytes <= 0)
{
APP_DEBUG("<-- No data in UART buffer! -->\r\n");
return;
}
else
{
APP_DEBUG ("%s\r\n", m_RxBuf_Uart);
s32 ret;
char* pCh = NULL;
pCh = Ql_strstr((char*)m_RxBuf_Uart, "\r\n");
if (pCh)
{
*(pCh + 0) = '\0';
*(pCh + 1) = '\0';
}
if (Ql_strlen((char*)m_RxBuf_Uart) == 0)
{
return;
}
ret = Ql_RIL_SendATCmd((char*)m_RxBuf_Uart, totalBytes, ATResponse_Handler, NULL, 0);
}
}
break;
}
case EVENT_UART_READY_TO_WRITE:
break;
default:
break;
}
}
二、对接OneNET的实现
1、注册一个对接OneNET定时器
注册一个对接OneNET定时,主要用于实现检查是否注册上网以及ONENET_CREATE、ONENET_ADDOBJ、ONENET_OPEN、ONENET_OBSERVER_RSP、ONENET_DISCOVER_RSP、ONENET_NOTIFY、ONENET_UPDATE等功能。
Ql_Timer_Register(ONENET_TIMER_ID, Callback_Timer_OneNET, NULL);
2、在主线程实时接收内核传来的消息
在主线程里面实时接收内核传来的消息,包括检查RIL层是否就绪,是否接收到URC消息等。
void proc_main_task(s32 taskId)
{
...... /* 省略部分代码,完整具体看GitHub代码 */
// START MESSAGE LOOP OF THIS TASK
while(TRUE)
{
Ql_OS_GetMessage(&msg);
switch(msg.message)
{
case MSG_ID_RIL_READY: /* RIL层就绪 */
{
APP_DEBUG("<-- RIL is ready -->\r\n");
Ql_RIL_Initialize();
Ql_RIL_SendATCmd("AT+CPSMS=0",Ql_strlen("AT+CPSMS=0"),ATResponse_Handler,NULL,0);
APP_DEBUG("<-- Disable PSM -->\r\n");
Ql_SleepDisable();
APP_DEBUG("<-- Disable Sleep -->\r\n");
break;
}
case MSG_ID_URC_INDICATION: /* 接收到URC消息 */
{
...... /* 处理URC消息 */
}
}
}
}
3、关闭PSM和sleep模式
由上面代码可知,在RIL就绪之后,关闭了PSM和Sleep模式,这个是为了不让模组进入睡眠模式,当然这个要看实际的应用情况去选择是关闭还是开启。
Ql_RIL_SendATCmd("AT+CPSMS=0", Ql_strlen("AT+CPSMS=0"), ATResponse_Handler,NULL,0);
APP_DEBUG("<-- Disable PSM -->\r\n");
Ql_SleepDisable();
APP_DEBUG("<-- Disable Sleep -->\r\n");
4、接收处理URC消息,检查SIM卡状态是否就绪
在前面的主线程实时接收内核传来的URC消息中,实时的去接收URC消息,当检查到URC消息是当前卡状态的时候,判断卡是否就绪(是否已经插卡),如果卡就绪就开启OneNET定时器,周期为1秒,模式是循环。
case URC_SIM_CARD_STATE_IND:
{
APP_DEBUG("<-- SIM Card Status:%d -->\r\n", msg.param2);
if(SIM_STAT_READY == msg.param2)
{
Ql_Timer_Start(ONENET_TIMER_ID, ONENET_TIMER_PERIOD, TRUE);
}
break;
}
5、OneNET定时器回调函数的实现
OneNET定时器主要实现检查模组是否注册上网以及实现模组对接OneNET的功能。
static void Callback_Timer_OneNET(u32 timerId