妹子你男票掉了 发表于 2022-7-19 05:31:20

华维单片机编程实战02-NB-Iot烟感07:NB-IOT 无线通讯程序开发

一、搭建程序的开发环境:

NB-Iot 无线通讯板我们选择的主控芯片是 我们选择的是华大半导体的HC32F005C6PA, 这个芯片是基于M0的32位低功耗单片机。
开发环境我们选择的是Keil MDK, 这个非常通用,在这里我就不给大家介绍了。
二、准备工作:

NB-Iot通讯的主要功能是为了将烟感的数据上次到云平台。
目前的NB-Iot 的云平台主要中国移动的OneNet 和中国电信cwing。今天华维单片机编程主要给大家介绍一下BC26和OneNet平台的通讯。
为什么不选择中国电信平台? 中国电信也是可以的,只不过中国电信平台需要企业注册认证才可以注册账号,有点麻烦。
1.我们首先要注册一个OneNet 账号,OneNet个体就可以注册。
打开网页,大家在右上脚,注册账号,然后再登陆。
我们登录以后需要新建自己的项目, 注意要选择旧版本。
新建项目如下,可以根据自己的需求 填写项目名称,选择项目标签。点增加即可。
项目新建完成后如下图所示:
接下来,我们需要添加产品:
添加设备的时候,需要和我们的产品设备对应 ,每个NB-IOT 模块都一个对应的IMEI号。IMSI是设备安装的SIM卡的卡号 也是15位。
以上就是我们平台准备的工作,接下来,我们就开始我们程序的开发
三、产品NB-Iot 通讯指令流程

NB-IOT 是基于运营商的基站通讯的,所有需要准备一张有效的NB-Iot SIM卡。我们选择的是贴片SIM卡,可以直接使用。
我们先研究一下NB-IOT 的初始化过程。(参考BC26软件开发相关资料)
1.NB-Iot的初始化指令:
获取模块的IMEI号
指令: AT + CGSN = 1;
OneNet平台注册需要
490154203237511 就是模块的IMEI序号,平台注册要用。
程序处理:
如果串口发送了 AT + CGSN = 1;NB模块没有回复,就需要确定是否模块开机失败?或者模块硬件有故障等。(如果模块没有回复, 需要尝试发送3次,连续3次失败表示他获取失败)
如果获取到了有效值,则执行下一条指令
获取产品SIM卡的IMSI OneNet平台注册需要
指令: AT+CIMI
460001357924680 SIM卡的IMSI序号
程序处理:
获取失败: 表示检测SIM卡失败,设备异常,通过提示灯报故障,
获取成功:执行下一条指令
查询信号值
指令: AT+CSQ
从指令可以获取 当前的CSQ值为22,表示为有效值。CSQ的其他取值的含义。
0 -113 dBm 或以下
1 -111 dBm
2~30 -109 至-53 dBm
31 -51 dBm 或以上
程序初始化过程中,我们需要判断CSQ的值 需要大于10,且小于32.才能有效,负责后期会严重影响产品的稳定性,需要提示生产者 产看是否天线没有安装好,或其他问题。
程序处理:
CSQ异常: 表示检测SIM卡失败,设备异常,通过提示灯报故障,
CSQ的值有效:执行下一条指令
注意:CSQ 的值需要系统每隔2秒,连续循环查询20次,等待模块入网。
查询模块网络是否已经注册。
指令: AT+CEREG?
本条指令说明:
+CEREG: 1,1
第一个1,表示允许上报网络注册状态,如果=0,表示禁止上报网络注册状态 URC
第二个1,表示EPS 注册状态。其他取值说明。
0 未注册,MT 当前未搜索网络
1 已注册,归属网络
2 未注册,但 MT 当前正在尝试附着或搜索网络以进行注册
3 注册被拒绝
4 未知(例如:超出 E-UTRAN 覆盖范围)
5 已注册,漫游状态
程序处理:
发送 AT+CEREG?,模块需要回复+CEREG: 1,1,或+CEREG: 0,1 表示网络已注册。
回复失败:循环等待查询20,间隔2秒。 超时提示故障,需要查询模块的硬件故障
回复成功: 执行下一条指令。
查询 PDP 上下文激活状态
指令:AT+CGATT?
+CGATT:0:
0 去附着或未附着
1 附着
程序处理:
发送 AT+CGATT?模块需要回复+CGATT:1
回复失败:循环等待查询20,间隔2秒。 超时提示故障,需要查询模块的硬件故障
回复成功: 执行下一条指令。
查询工作频段
指令: AT+QBAND?
+QBAND:5 的有效值:1、3、5、8、20 等;
我们的是中国移动,取值需要是8.
程序处理:
发送 AT+CGATT?模块需要回复+QBAND:8
回复失败:执行AT+QBAND = 8 来设置网络
回复成功: 执行下一条指令。
2. NB-Iot注册网络:
网络注册,需要用户,根据NB模块的IMEI 和IMSI 再OneNet 平台上注册,再执行本段程序代码,否则会失败。
注册流程如下:
详细说明:
AT+MIPLCREATE指令
功能:创建 OneNET 通信套件实例
程序开发说明:
本条指令的响应时间最大为5秒,只能发送一次,等待5秒超时。
返回值: +MIPLCREATE:0
获取失败:需要执行AT+MIPLCLOSE=0 关闭实例,再执行AT+MIPLDELETE=0 删除实例,再执行AT+MIPLCREATE。
获取成功:执行下条指令。
AT+MIPLADDOBJ=0,3311,1,”1″,4,2指令 (重要)
功能: 添加 LwM2M 对象
说明: NB-IOT 是基于LwM2M 协议开发的,需要增加LwM2M才可以和平台通讯
指令说明:
(参数说明:省略,有疑问的 请找无际单片机编程。
程序开发说明:
本条指令的响应时间最大为5秒,只能发送一次,等待5秒超时。
返回值:OK
获取失败:需要执行AT+MIPLCLOSE=0 关闭实例,再执行AT+MIPLDELETE=0 删除实例,再从AT+MIPLCREATE开始执行。 本条指令一般不会出错。
获取成功:执行下条指令。
AT+MIPLOPEN=0,86400 指令(重要)
功能说明: 发送注册请求
指令说明:86400 设置设备的生命周期,实际生命周期为<lifetime> × 0.9。范围:
15~268435455,若设置为 0,则表示 3600 秒;单位:秒。
返回值:
+MIPLEVENT: 0,1 //开始连接到 Bootstrap 服务器。
+MIPLEVENT: 0,2 //成功连接到 Bootstrap 服务器。
+MIPLEVENT: 0,4 //成功连接到 OneNET 平台。
+MIPLEVENT: 0,6 //成功注册到 OneNET 平台。
如果返回:+MIPLEVENT: 0,3 表示OneNet 平台没有注册本设备
程序处理:
获取失败: 获取到 +MIPLEVENT: 0,4 表示注册到平台,否则注册失败,执行AT+MIPLCLOSE=0 关闭实例,再执行AT+MIPLDELETE=0 删除实例,再从AT+MIPLCREATE开始执行。
获取成功:执行下一条指令
AT+MIPLOBSERVE: 0,69234,1,3311,0,-1 指令(重要)
功能说明:响应订阅请求
指令说明:
返回值:
+MIPLDISCOVER: 0,26384,3311 //接收到发现资源请求。
程序处理:
本条指令的响应时间最大为5秒,只能发送一次,等待5秒超时。 获取到数据后,需要获取msgid的值,下条指令需要该值。
获取失败:因网络稳定型问题,会导致本条指令运行失败或错误。
如果失败,需要执行AT+MIPLCLOSE=0 关闭实例,再执行AT+MIPLDELETE=0 删除实例,再从AT+MIPLCREATE开始执行。
获取成功:执行下一条指令
AT+MIPLDISCOVERRSP=0,26384,1,19,”5850;5851;5706;5805″ 指令(重要)
功能说明:该命令用于响应来自 OneNET 平台的发现资源请求。
指令说明:
程序响应: OK
程序处理:
本条指令的响应时间最大为5秒,只能发送一次,等待5秒超时。 msgid的值需要从上一条指令获取。
获取失败:因网络稳定型问题,会导致本条指令运行失败或错误。
如果失败,需要执行AT+MIPLCLOSE=0 关闭实例,再执行AT+MIPLDELETE=0 删除实例,再从AT+MIPLCREATE开始执行。
获取成功:表示设备再OneNet平台注册成功。 需要获取。
3. NB-Iot上传数据。
指令说明:
程序处理:
如果发送成功:则返回OK。
返回失败: 需要先确定指令的数据格式是否正常。 如果正常则需要检测设备的网络是否异常,如果异常需要执行AT+MIPLCLOSE=0 关闭实例,再执行AT+MIPLDELETE=0 删除实例,再从AT+MIPLCREATE开始重新注册网络。
返回正常: 设备进入休眠,或等待处理其他数据。
4更新设备生命周期,如果确实这条指令,会导致设备离线。
AT+MIPLOPEN=0,86400 设置设备的生命周期为86400秒,也就是说,再设备工作86400之前需要更新设备的生命周期,才能确保产品持续在线,否则会离线。
返回值:+MIPLEVENT: 0,11 //更新结果。
程序开发说明:
本条指令的响应时间最大为5秒,只能发送一次,等待5秒超时。负责就需要执行AT+MIPLCLOSE=0 关闭实例….
因为网络问题,执行本条指令需要等待5秒时间。需要再设备的生命周期结束前执行本条指令。
四、程序开发:

上面我们了解了NB-Iot的通讯流程和相关指令,下面我们开始程序的相关开发,再这里我给大家做个简单的介绍,因为产品的选择的单片机和平台都不一样。
程序开发逻辑:
单片机控制NB-Iot模块的PowerKey脚位拉低800毫秒开机,详细请参考BC26的硬件设计。
见上图,单片机控制MCU_PKEY 拉高500ms
开始NB-Iot 的指令控制:
AT + CGSN = 1;
AT+CIMI
AT+CSQ
…..
以上已介绍。
备注:每条指令的超时时间,执行次数都不一样,都需要等待正确的回复才能执行下一条指令。
在这里大家需要做一个结构体数组:代码如下:
typedef structstCmdStr{    unsigned charid;                            //   发送ID号   unsigned charconst *str;             // 发送AT指令包   unsigned charneddack;                //是否需要检验应答    unsigned short len;                        //发送数据长度    unsigned charResenTimes;         //发送的次数    unsigned short DelaySetTim;         // 发送前延时时间    unsigned short SetInterDelayTim;   //发送间隔时间      unsigned charNext_SucIdx;         //下个指针成功操作后    unsigned charNext_FaiIdx;            //下个指针失败操作后   }stCmdStrTy;stCmdStrTy atCmdInMain;    ////void SetCmdBuff(unsigned char scmid,stCmdStrTy * cmd){                                          atCmdBuff.id = cmd->id;   atCmdBuff.str = cmd->str;   atCmdBuff.neddack = cmd->neddack;   atCmdBuff.len = cmd->len;   atCmdBuff.DelaySetTim = cmd->DelaySetTim;   atCmdBuff.SetInterDelayTim = cmd->SetInterDelayTim;   atCmdBuff.ResenTimes = cmd->ResenTimes;   atCmdBuff.Next_FailOverTimID = cmd->Next_FailOverTimID;   }void NBIOT_SysteMode_ListInit(void){    atCmdInMain.id = NB_MODE_RESET;    ///确认模块AT指令收发是否正常。 返回OK 表示正常    atCmdInMain.str = &NBIOT_BC95_At_Com;    atCmdInMain.neddack = TRUE;    atCmdInMain.len=Fun_GetStrLen((unsigned char *)NBIOT_BC95_At_Com);    atCmdInMain.DelaySetTim = 0;    atCmdInMain.SetInterDelayTim = 6000;    atCmdInMain.ResenTimes = 3;    atCmdInMain.Next_SucIdx = NB_MODE_AT;    atCmdInMain.Next_FaiIdx = NB_MODE_RESET;    SetCmdBuff(NB_MODE_RESET,&atCmdInMain);    atCmdInMain.id = NB_MODE_AT;    ///确认模块AT指令收发是否正常。 返回OK 表示正常    atCmdInMain.str = &NBIOT_BC95_At_Com;    atCmdInMain.neddack = TRUE;    atCmdInMain.len=Fun_GetStrLen((unsigned char *)NBIOT_BC95_At_Com);    atCmdInMain.DelaySetTim = 0;    atCmdInMain.SetInterDelayTim = 200;    atCmdInMain.ResenTimes = 20;    atCmdInMain.Next_SucIdx = NB_MODE_CGSN;    atCmdInMain.Next_FaiIdx = NB_MODE_RESET;    SetCmdBuff(NB_MODE_AT,&atCmdInMain);.....}void TxThread(void){static unsigned short InterTimer=0;   switch(satCmdStatu){    case ATSTATUSEND:   //tx   数据发送    {                if(SystemModeIdx < NB_MODE_SLEEP)                {                        if(SentReDelayT > 0)////发送数据前延时                        {                            SentReDelayT--;                            return;                               }                         satCmdAck = ATNULL;                        UART1_SendStrLen((unsigned char *)atCmdBuff.str,atCmdBuff.len);//发送数据                        InterTimer = atCmdBuff.SetInterDelayTim;///间隔时间                        if(atCmdBuff.neddack)//判断本次发送是否需要等待应答                        {                                        satCmdStatu = ATSTATUCHECK; //checkack 检测应答                        }                        else                        {                                SystemModeIdx = atCmdBuff.Next_SucIdx;////指针Next                                SentReDelayT = atCmdBuff.DelaySetTim; ////更新发送数据前延时时间                                                        return;                        }                        satCmdWaitCnt = 0;   //间隔时间复位                        satCmdErrorCnt = 0;                // 错误次数清零                        satCmdRepeatCnt = 0;            // 重发次数清零                }                else                {                        //myprintf("NO CMD");                        satCmdStatu = ATSTATUSEND;                        return;                }    }    break;   case ATSTATUCHECK://应答检测    {                 switch(satCmdAck)                {                        case ATNULL: ///if(ATNULL == j ) // 等待                        case ATERROR:// TCP准备好发送数据返回OK                        {////没有回复                                if(satCmdWaitCnt++ > InterTimer)// 等待次数超时                                {                                                                                                          satCmdStatu = ATSTATUREPEAT;// 重发                                        satCmdWaitCnt = 0;                                }                        }                        break;                        case ATATOK:                        {                          satCmdStatu = ATSTATUSEND;                                  satCmdErrorCnt = 0;                                 satCmdRepeatCnt =0;                          atCmdTx =ATTXSENDOK;        //TX 发送Ok                        satCmdAck = ATNULL;                          SystemModeIdx = atCmdBuff.Next_SucIdx;                          SentReDelayT = atCmdBuff.DelaySetTim;                        }                        break;                        case ATRESTR:// TCP准备好发送数据返回OK                        {                          satCmdStatu = ATSTATUSEND;                                  satCmdErrorCnt = 0;                                 satCmdRepeatCnt =0;                          atCmdTx =ATTXSENDOK;        //TX 发送Ok                        }                        break;                        default:                        {                               myprintf("NO Ack\n");                                 //sleep(1);                                satCmdWaitCnt = 0;                                satCmdRepeatCnt=0;                                 satCmdAck = ATNULL;                                satCmdStatu = ATSTATUREPEAT; //其它状态重发                                }                        break;                                        }    }    break;    case ATSTATUREPEAT:    {      satCmdRepeatCnt++;      if(satCmdRepeatCnt >= atCmdBuff.ResenTimes)// 重发计数超      {            if(NB_MODE_WAIT_SLEEP == atCmdBuff.Next_FailOverTimID)            {////系统进入延时                SystemSleepTime = TIME_SYSTEM_SLEEP_ERROR;                satCmdStatu = ATSTATUSEND;                      satCmdErrorCnt = 0;                         satCmdRepeatCnt =0;                SystemModeIdx =NB_MODE_RESET;               myprintf("模块进入间隔休眠状态中\r\n");                  satCmdAck = ATNULL;                  return;            }            else            {            satCmdStatu = ATSTATUSEND;// 发送状态复位                SystemModeIdx = atCmdBuff.Next_FailOverTimID;            SentReDelayT = atCmdBuff.DelaySetTim;            }         }      else      {            satCmdStatu = ATSTATUCHECK;// 发送完后检测应答      }                satCmdWaitCnt = 0;      satCmdWaitCnt = 0;      satCmdAck = ATNULL;      UART1_SendStrLen((unsigned char *)atCmdBuff.str,atCmdBuff.len);   }    break;}    }xxxxxxxxxxbr typedef structstCmdStrbr{br    unsigned charid;                        //   发送ID号 br    unsigned charconst *str;             // 发送AT指令包 br    unsigned charneddack;                //是否需要检验应答br    unsigned short len;                        //发送数据长度br    unsigned charResenTimes;         //发送的次数br    unsigned short DelaySetTim;         // 发送前延时时间br    unsigned short SetInterDelayTim;   //发送间隔时间br    unsigned charNext_SucIdx;         //下个指针成功操作后br    unsigned charNext_FaiIdx;            //下个指针失败操作后   br}stCmdStrTy;brbrstCmdStrTy atCmdInMain;    ////brbrvoid SetCmdBuff(unsigned char scmid,stCmdStrTy * cmd)br{            br   atCmdBuff.id = cmd->id;br   atCmdBuff.str = cmd->str;br   atCmdBuff.neddack = cmd->neddack;br   atCmdBuff.len = cmd->len;br   atCmdBuff.DelaySetTim = cmd->DelaySetTim;br   atCmdBuff.SetInterDelayTim = cmd->SetInterDelayTim;br   atCmdBuff.ResenTimes = cmd->ResenTimes;br   atCmdBuff.Next_FailOverTimID = cmd->Next_FailOverTimID;   br}brbrvoid NBIOT_SysteMode_ListInit(void)br{br    atCmdInMain.id = NB_MODE_RESET;    ///确认模块AT指令收发是否正常。 返回OK 表示正常br    atCmdInMain.str = &NBIOT_BC95_At_Com;br    atCmdInMain.neddack = TRUE;br    atCmdInMain.len=Fun_GetStrLen((unsigned char *)NBIOT_BC95_At_Com);br    atCmdInMain.DelaySetTim = 0;br    atCmdInMain.SetInterDelayTim = 6000;br    atCmdInMain.ResenTimes = 3;br    atCmdInMain.Next_SucIdx = NB_MODE_AT;br    atCmdInMain.Next_FaiIdx = NB_MODE_RESET;br    SetCmdBuff(NB_MODE_RESET,&atCmdInMain);brbr    atCmdInMain.id = NB_MODE_AT;    ///确认模块AT指令收发是否正常。 返回OK 表示正常br    atCmdInMain.str = &NBIOT_BC95_At_Com;br    atCmdInMain.neddack = TRUE;br    atCmdInMain.len=Fun_GetStrLen((unsigned char *)NBIOT_BC95_At_Com);br    atCmdInMain.DelaySetTim = 0;br    atCmdInMain.SetInterDelayTim = 200;br    atCmdInMain.ResenTimes = 20;br    atCmdInMain.Next_SucIdx = NB_MODE_CGSN;br    atCmdInMain.Next_FaiIdx = NB_MODE_RESET;br    SetCmdBuff(NB_MODE_AT,&atCmdInMain);br.....br}brvoid TxThread(void)br{brstatic unsigned short InterTimer=0; brswitch(satCmdStatu)br{br    case ATSTATUSEND:   //tx   数据发送br    {br    if(SystemModeIdx < NB_MODE_SLEEP)br    {br      if(SentReDelayT > 0)////发送数据前延时br      {br                            SentReDelayT--;br                            return;br      } br                        satCmdAck = ATNULL;br                        UART1_SendStrLen((unsigned char *)atCmdBuff.str,atCmdBuff.len);//发送数据br      InterTimer = atCmdBuff.SetInterDelayTim;///间隔时间br      if(atCmdBuff.neddack)//判断本次发送是否需要等待应答br      { br      satCmdStatu = ATSTATUCHECK; //checkack 检测应答br      }br      elsebr      {br      SystemModeIdx = atCmdBuff.Next_SucIdx;////指针Nextbr      SentReDelayT = atCmdBuff.DelaySetTim; ////更新发送数据前延时时间      br      return;br      }br      satCmdWaitCnt = 0;   //间隔时间复位br      satCmdErrorCnt = 0;         // 错误次数清零br      satCmdRepeatCnt = 0;            // 重发次数清零br    }br    elsebr    {br      //myprintf("NO CMD");br      satCmdStatu = ATSTATUSEND;br      return;br    }br    }br    break; br    case ATSTATUCHECK://应答检测br    {   switch(satCmdAck)br    {br      case ATNULL: ///if(ATNULL == j ) // 等待br      case ATERROR:// TCP准备好发送数据返回OKbr      {////没有回复br      if(satCmdWaitCnt++ > InterTimer)// 等待次数超时br      {                  br          satCmdStatu = ATSTATUREPEAT;// 重发br          satCmdWaitCnt = 0;br      }br      }br      break;br      case ATATOK:br                        {br      satCmdStatu = ATSTATUSEND;br      satCmdErrorCnt = 0;br      satCmdRepeatCnt =0;br      atCmdTx =ATTXSENDOK;//TX 发送Okbr                        satCmdAck = ATNULL;br      SystemModeIdx = atCmdBuff.Next_SucIdx;br      SentReDelayT = atCmdBuff.DelaySetTim;br                        }br      break;br      case ATRESTR:// TCP准备好发送数据返回OKbr      {br      satCmdStatu = ATSTATUSEND;br      satCmdErrorCnt = 0;br      satCmdRepeatCnt =0;br      atCmdTx =ATTXSENDOK;//TX 发送Okbr      }br      break;br      default:br      {br         myprintf("NO Ack\n"); brbr      //sleep(1);br      satCmdWaitCnt = 0;br      satCmdRepeatCnt=0;br                                 satCmdAck = ATNULL;br      satCmdStatu = ATSTATUREPEAT; //其它状态重发   br      }br      break;      br    }br    }br    break;br    case ATSTATUREPEAT:br    {br      satCmdRepeatCnt++;br      if(satCmdRepeatCnt >= atCmdBuff.ResenTimes)// 重发计数超br      {br            if(NB_MODE_WAIT_SLEEP == atCmdBuff.Next_FailOverTimID)br            {////系统进入延时br                SystemSleepTime = TIME_SYSTEM_SLEEP_ERROR;br                satCmdStatu = ATSTATUSEND;br                satCmdErrorCnt = 0;br                satCmdRepeatCnt =0;br                SystemModeIdx =NB_MODE_RESET;br               myprintf("模块进入间隔休眠状态中\r\n");br                  satCmdAck = ATNULL;br                return;br            }br            elsebr            {br            satCmdStatu = ATSTATUSEND;// 发送状态复位br            SystemModeIdx = atCmdBuff.Next_FailOverTimID;br            SentReDelayT = atCmdBuff.DelaySetTim;br            }   br      }br      elsebr      {br            satCmdStatu = ATSTATUCHECK;// 发送完后检测应答br      } br      satCmdWaitCnt = 0;br      satCmdWaitCnt = 0;br      satCmdAck = ATNULL;br      UART1_SendStrLen((unsigned char *)atCmdBuff.str,atCmdBuff.len); br    }br    break;br}    br}完整程序篇幅太长,这里就不放了,可以找华维单片机编程获取。
NB-Iot 接收程序:
为了防止串口接收数据丢失,我们订了一个256字节的队列,
Queue256 Uart1RxMsg;
串口接收主函数如下,使用到了回调函数:
void RxThread(void){if(satCmdAck == ATNULL){    satCmdAck = (unsigned char)NB_IOT_UartRec((Enum_NbIot_Mode)atCmdBuff.id,Fuc_GetAtRespose);}}串口获取数据解析函数:unsigned char Uart_GetDat(unsigned char *getbuf){    unsigned char i;    unsigned char len,dat,idx;    static unsigned char lenx,GetDat_Delay;    len = QueueDataLen(Uart1RxMsg);    if(len)    {      if(len == lenx)      {///接收数据延时          GetDat_Delay++;       }      else      {///收到了新的数据      lenx = len;      GetDat_Delay = 0;      }       if(GetDat_Delay > 100)      {/////收到数据起,延时120毫秒,开始判断接收到的数据          idx = 0xff;          i = 0;          do          {            i++;            QueueDataOut(Uart1RxMsg,&dat);            if(dat == 0x0A)   /////10   0A '\n'            {            if((idx == 0xff) || (idx < 2))            {                idx = 0;               }            }            else if(dat == 0x0D)////120D'\r'            {            if(idx == 0)                idx = 0;            else if((idx > 1) && (idx != 0xff))               return idx;            else                idx = 0xff;            }                        else            {            if(idx != 0xff)            {                getbuf = dat;               if(idx > 59)                  return 0xff;                              }            }          }while(i< len);       }    }    else    {      lenx = 0;      GetDat_Delay = 0;    }    return 0xff;}xxxxxxxxxxbr void RxThread(void)br{brif(satCmdAck == ATNULL)br{br    satCmdAck = (unsigned char)NB_IOT_UartRec((Enum_NbIot_Mode)atCmdBuff.id,Fuc_GetAtRespose);br}br}br串口获取数据解析函数:brunsigned char Uart_GetDat(unsigned char *getbuf)br{br    unsigned char i;br    unsigned char len,dat,idx;br    static unsigned char lenx,GetDat_Delay;br    len = QueueDataLen(Uart1RxMsg);br    if(len)br    {br      if(len == lenx)br      {///接收数据延时br          GetDat_Delay++; br      }br      elsebr      {///收到了新的数据br      lenx = len;br      GetDat_Delay = 0;br      } br      if(GetDat_Delay > 100)br      {/////收到数据起,延时120毫秒,开始判断接收到的数据br          idx = 0xff;br          i = 0;br          dobr          {br            i++;br            QueueDataOut(Uart1RxMsg,&dat);br            if(dat == 0x0A)   /////10   0A '\n'br            {br            if((idx == 0xff) || (idx < 2))br            {br                idx = 0; br            }br            }br            else if(dat == 0x0D)////120D'\r'br            {br            if(idx == 0)br                idx = 0;br            else if((idx > 1) && (idx != 0xff)) br                return idx;br            elsebr                idx = 0xff;br            }            br            elsebr            {br            if(idx != 0xff)br            {br                getbuf = dat; br                if(idx > 59)br                  return 0xff;                br            }br            }br          }while(i< len); br      }br    }br    elsebr    {br      lenx = 0;br      GetDat_Delay = 0;br    }br    return 0xff;br}brOk,那我们这节课就先讲到这里,到此整个项目就实现功能了,本节课较长,大家可以多看几遍加深理解,下篇文章我跟大家讲解这个产品的一些测试验证方法及注意问题。

声明:以上内容来源于网络,如有侵权请联系我们(123@shiyan.com)删除!
页: [1]
查看完整版本: 华维单片机编程实战02-NB-Iot烟感07:NB-IOT 无线通讯程序开发