sponsored links

華維微控制器程式設計實戰02-NB-Iot煙感07:NB-IOT 無線通訊程式開發

一、搭建程式的開發環境:

NB-Iot 無線通訊板我們選擇的主控晶片是 我們選擇的是華大半導體的HC32F005C6PA, 這個晶片是基於M0的32位低功耗微控制器。

開發環境我們選擇的是Keil MDK, 這個非常通用,在這裡我就不給大家介紹了。

二、準備工作:

NB-Iot通訊的主要功能是為了將煙感的資料上次到雲平臺。

目前的NB-Iot 的雲平臺主要中國移動的OneNet 和中國電信cwing。今天華維微控制器程式設計主要給大家介紹一下BC26和OneNet平臺的通訊。

為什麼不選擇中國電信平臺? 中國電信也是可以的,只不過中國電信平臺需要企業註冊認證才可以註冊賬號,有點麻煩。

1.我們首先要註冊一個OneNet 賬號,OneNet個體就可以註冊。

開啟網頁,大家在右上腳,註冊賬號,然後再登陸。

我們登入以後需要新建自己的專案, 注意要選擇舊版本。

新建專案如下,可以根據自己的需求 填寫專案名稱,選擇專案標籤。點增加即可。

專案新建完成後如下圖所示:

接下來,我們需要新增產品:

華維微控制器程式設計實戰02-NB-Iot煙感07:NB-IOT 無線通訊程式開發

新增裝置的時候,需要和我們的產品裝置對應 ,每個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?

華維微控制器程式設計實戰02-NB-Iot煙感07:NB-IOT 無線通訊程式開發

+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 struct  stCmdStr
{
    unsigned char  id;                        //   傳送ID號
    unsigned char  const *str;             // 傳送AT指令包
    unsigned char  neddack;                //  是否需要檢驗應答
    unsigned short len;                          //傳送資料長度
    unsigned char  ResenTimes;           //傳送的次數
    unsigned short DelaySetTim;           // 傳送前延時時間
    unsigned short SetInterDelayTim;     //  傳送間隔時間
    unsigned char  Next_SucIdx;           //  下個指標  成功操作後
    unsigned char  Next_FaiIdx;            //  下個指標  失敗操作後
}stCmdStrTy;

stCmdStrTy atCmdInMain;    ////

void SetCmdBuff(unsigned char scmid,stCmdStrTy * cmd)
{
   atCmdBuff[scmid].id = cmd->id;
   atCmdBuff[scmid].str = cmd->str;
   atCmdBuff[scmid].neddack = cmd->neddack;
   atCmdBuff[scmid].len = cmd->len;
   atCmdBuff[scmid].DelaySetTim = cmd->DelaySetTim;
   atCmdBuff[scmid].SetInterDelayTim = cmd->SetInterDelayTim;
   atCmdBuff[scmid].ResenTimes = cmd->ResenTimes;
   atCmdBuff[scmid].Next_FailOverTimID = cmd->Next_FailOverTimID;
}

void NBIOT_SysteMode_ListInit(void)
{
    atCmdInMain.id = NB_MODE_RESET;    ///確認模組AT指令收發是否正常。 返回OK 表示正常
    atCmdInMain.str = &NBIOT_BC95_At_Com[NBIOM_ATCOM_RESET][0];
    atCmdInMain.neddack = TRUE;
    atCmdInMain.len=Fun_GetStrLen((unsigned char *)NBIOT_BC95_At_Com[NBIOM_ATCOM_RESET]);
    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[NBIOT_ATCOM_AT][0];
    atCmdInMain.neddack = TRUE;
    atCmdInMain.len=Fun_GetStrLen((unsigned char *)NBIOT_BC95_At_Com[NBIOT_ATCOM_AT]);
    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[SystemModeIdx].str,atCmdBuff[SystemModeIdx].len);//傳送資料
            InterTimer = atCmdBuff[SystemModeIdx].SetInterDelayTim;  ///間隔時間
            if(atCmdBuff[SystemModeIdx].neddack)//判斷本次傳送是否需要等待應答
            {
                satCmdStatu = ATSTATUCHECK; //checkack 檢測應答
            }
            else
            {
                SystemModeIdx = atCmdBuff[SystemModeIdx].Next_SucIdx;////指標Next
                SentReDelayT = atCmdBuff[SystemModeIdx].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[SystemModeIdx].Next_SucIdx;
              SentReDelayT = atCmdBuff[SystemModeIdx].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[SystemModeIdx].ResenTimes)// 重發計數超
        {
            if(NB_MODE_WAIT_SLEEP == atCmdBuff[SystemModeIdx].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[SystemModeIdx].Next_FailOverTimID;
              SentReDelayT = atCmdBuff[SystemModeIdx].DelaySetTim;
            }
        }
        else
        {
            satCmdStatu = ATSTATUCHECK;// 傳送完後檢測應答
        }
        satCmdWaitCnt = 0;
        satCmdWaitCnt = 0;
        satCmdAck = ATNULL;
        UART1_SendStrLen((unsigned char *)atCmdBuff[SystemModeIdx].str,atCmdBuff[SystemModeIdx].len);
    }
    break;
  }
}
xxxxxxxxxxbr typedef struct  stCmdStrbr{br    unsigned char  id;                        //   傳送ID號 br    unsigned char  const *str;             // 傳送AT指令包 br    unsigned char  neddack;                //  是否需要檢驗應答br    unsigned short len;                          //傳送資料長度br    unsigned char  ResenTimes;           //傳送的次數br    unsigned short DelaySetTim;           // 傳送前延時時間br    unsigned short SetInterDelayTim;     //  傳送間隔時間  br    unsigned char  Next_SucIdx;           //  下個指標  成功操作後br    unsigned char  Next_FaiIdx;            //  下個指標  失敗操作後   br}stCmdStrTy;brbrstCmdStrTy atCmdInMain;    ////brbrvoid SetCmdBuff(unsigned char scmid,stCmdStrTy * cmd)br{              br   atCmdBuff[scmid].id = cmd->id;br   atCmdBuff[scmid].str = cmd->str;br   atCmdBuff[scmid].neddack = cmd->neddack;br   atCmdBuff[scmid].len = cmd->len;br   atCmdBuff[scmid].DelaySetTim = cmd->DelaySetTim;br   atCmdBuff[scmid].SetInterDelayTim = cmd->SetInterDelayTim;  br   atCmdBuff[scmid].ResenTimes = cmd->ResenTimes;br   atCmdBuff[scmid].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[NBIOM_ATCOM_RESET][0];br    atCmdInMain.neddack = TRUE;br    atCmdInMain.len=Fun_GetStrLen((unsigned char *)NBIOT_BC95_At_Com[NBIOM_ATCOM_RESET]);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[NBIOT_ATCOM_AT][0];br    atCmdInMain.neddack = TRUE;br    atCmdInMain.len=Fun_GetStrLen((unsigned char *)NBIOT_BC95_At_Com[NBIOT_ATCOM_AT]);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{br  static unsigned short InterTimer=0; br  switch(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[SystemModeIdx].str,atCmdBuff[SystemModeIdx].len);//傳送資料br      InterTimer = atCmdBuff[SystemModeIdx].SetInterDelayTim;  ///間隔時間br      if(atCmdBuff[SystemModeIdx].neddack)//判斷本次傳送是否需要等待應答br      { br        satCmdStatu = ATSTATUCHECK; //checkack 檢測應答br      }br      elsebr      {br        SystemModeIdx = atCmdBuff[SystemModeIdx].Next_SucIdx;////指標Nextbr        SentReDelayT = atCmdBuff[SystemModeIdx].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[SystemModeIdx].Next_SucIdx;br        SentReDelayT = atCmdBuff[SystemModeIdx].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[SystemModeIdx].ResenTimes)// 重發計數超br        {br            if(NB_MODE_WAIT_SLEEP == atCmdBuff[SystemModeIdx].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[SystemModeIdx].Next_FailOverTimID;br              SentReDelayT = atCmdBuff[SystemModeIdx].DelaySetTim;br            }   br        }br        elsebr        {br            satCmdStatu = ATSTATUCHECK;// 傳送完後檢測應答br        } br        satCmdWaitCnt = 0;br        satCmdWaitCnt = 0;br        satCmdAck = ATNULL;br        UART1_SendStrLen((unsigned char *)atCmdBuff[SystemModeIdx].str,atCmdBuff[SystemModeIdx].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[SystemModeIdx].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)////12  0D  '\r'
            {
              if(idx == 0)
                idx = 0;
              else if((idx > 1) && (idx != 0xff))
                return idx;
              else
                idx = 0xff;
            }
            else
            {
              if(idx != 0xff)
              {
                getbuf[idx ++] = dat;
                if(idx > 59)
                  return 0xff;
              }
            }
          }while(i< len);
      }
    }
    else
    {
      lenx = 0;
      GetDat_Delay = 0;
    }
    return 0xff;
}
xxxxxxxxxxbr void RxThread(void)br{br  if(satCmdAck == ATNULL)br  {br    satCmdAck = (unsigned char)NB_IOT_UartRec((Enum_NbIot_Mode)atCmdBuff[SystemModeIdx].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)////12  0D  '\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[idx ++] = 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}br

Ok,那我們這節課就先講到這裡,到此整個專案就實現功能了,本節課較長,大家可以多看幾遍加深理解,下篇文章我跟大家講解這個產品的一些測試驗證方法及注意問題

華維微控制器程式設計實戰02-NB-Iot煙感07:NB-IOT 無線通訊程式開發

分類: 科學
時間: 2021-12-18

相關文章

中國航空再創新高!神舟十三號發射在即,神州十二號都做了什麼

中國航空再創新高!神舟十三號發射在即,神州十二號都做了什麼
我國近幾年在航天事業上的成就,備受世人矚目,在高速發展的背後離不開科學家的嘔心瀝血.中國現在成為了名副其實的航天大國,在科學家拼搏奉獻的精神下,中國的航天事業必定如火如荼. 近日,中國神舟十二號飛船成 ...

NASA宇航員在太空的340天

NASA宇航員在太空的340天
斯科特·凱利 [編者按]:斯科特·凱利(Scott Kelly)是一名NASA宇航員,同時也是NASA火星計劃中頗具野心的任務之一--雙胞胎實驗計劃的參與者.按照計劃,他要在國際空間站連續生活340天 ...

歡迎來到第二個太空時代!美業餘宇航員遨遊太空後 成功回到地球

歡迎來到第二個太空時代!美業餘宇航員遨遊太空後 成功回到地球
美國四名業餘宇航員在太空呆了三天之後,成功降落在大西洋上. 他們是第一個進入地球軌道的全平民團隊. "靈感4號"機組人員於週三從佛羅里達州乘坐SpaceX太空艙離開,並於週六當地時 ...

宇航員上太空為什麼要帶手槍?帶手槍防誰?手槍在太空中管用嗎?

宇航員上太空為什麼要帶手槍?帶手槍防誰?手槍在太空中管用嗎?
宇航員上太空為什麼會攜帶手槍?中國在發射神舟五號時,航天員楊利偉的行李中出人意料地躺著一把六四式手槍.太空中帶槍啥意思?難道說,宇宙中真的有某種神秘的未知力量?感興趣的朋友可以點贊關注,感謝您的支援. ...

神舟十三號就位!三名航天員即將“出差”6個月

神舟十三號就位!三名航天員即將“出差”6個月
據中國載人航天工程辦公室訊息,北京時間2021年10月7日,神舟十三號載人飛船與長征二號F遙十三運載火箭組合體已轉運至發射區.目前,發射場設施裝置狀態良好,後續將按計劃開展發射前的各項功能檢查.聯合測 ...

美國科技封鎖30年,我國卻要發射神舟十三號,為何中國不怕制裁?

美國科技封鎖30年,我國卻要發射神舟十三號,為何中國不怕制裁?
原本擬定於10月3日發射的神舟十三號載人飛船,任務目前延期到10月中下旬,目前來看,大概會在"日凌期"結束之後,10月17日前後進行發射. 這一次,神舟十三號載人飛船上,將會搭載3 ...

神舟十三號即將出徵 專家揭秘:神舟飛船未來將實現怎樣的美好願景?
央廣網北京10月14日訊息(記者張棉棉 宋康飛)據中央廣播電視總檯中國之聲<新聞縱橫>報道,神舟十三號載人飛船與長征二號F遙十三運載火箭組合體近日已轉運至發射區.目前,發射場設施裝置狀態良 ...

“吉林一號”衛星從太空傳回了這麼多著名商業街的影像!一起中秋雲逛街吧

“吉林一號”衛星從太空傳回了這麼多著名商業街的影像!一起中秋雲逛街吧
2021年中秋佳節將至,"吉林一號"衛星從太空傳回了北京王府井.上海南京路.武漢江漢路.南京新街口.重慶解放碑.成都春熙路.長沙黃興南路.香港銅鑼灣等國內著名商業街的衛星影像.從太 ...

「海報」神舟十二號宇航員“回家”啦

「海報」神舟十二號宇航員“回家”啦
神舟十二號宇航員"回家"啦,迎接中秋!中國空間站建設再次邁向一大步.對我們來說,這真的是航天曆史上的一次"重大突破".--讓世界看到了中國航天技術的大發展,這是 ...

三宇航員三個月太空出差回家
"我回來了,身體好,精神好"三宇航員三個月太空出差回家 未來這是常態,古代嫦娥奔月的神話故事一點點變成現實 1970年4月24日我國第一顆人造衛星唱著"東方紅" ...

神舟十三號船箭組合體轉運至發射區
神舟十三號船箭組合體轉運至發射區 計劃近期擇機實施發射 本報北京10月7日電 (記者餘建斌)神舟十三號船箭組合體7日轉運至發射區,計劃近期擇機實施發射. 據中國載人航天工程辦公室訊息,北京時間2021 ...

神舟十三號蓄勢待發
看看新聞Knews記者 湯銘 2021-10-08 20:26 神箭出閣,蓄勢待發.10月7日,神舟十三號載人飛船與長征二號F遙十三運載火箭組合體已轉運至發射區,請跟我們一起感受神舟十三號船箭組合體垂 ...

神舟十三號轉運,廠房裡另一發火箭搶鏡,後者決定空間站成敗

神舟十三號轉運,廠房裡另一發火箭搶鏡,後者決定空間站成敗
七天長假最後一天神舟十三號載人飛船提前上崗,本月7日,長征2F遙十三/神舟十三號組合體由垂直總裝廠房成功轉運至載人航天發射塔架. 長征2F遙十三/神舟十三號組合體轉運至載人航天發射塔架 目前,發射場設 ...

神舟十三號載人飛行任務新聞釋出會將於10月14日下午召開
據中國載人航天工程辦公室介紹,空間站階段飛行任務總指揮部定於北京時間10月14日15時,在酒泉衛星發射中心召開神舟十三號載人飛行任務新聞釋出會,通報此次任務有關情況. 點連結,關注直播 直播預告 | ...

唯一一次宇航員在太空死亡,肺部炸裂、體液蒸發、40秒內窒息而亡

唯一一次宇航員在太空死亡,肺部炸裂、體液蒸發、40秒內窒息而亡
在遠古人類把極高的天空稱為太空.對於太空的高度以多少為界限,並沒有準確的資料.如果按定性的角度,地球稠密的大氣層以外的空間都可以稱為太空. 人類如果直接暴露在太空之中,會發生什麼呢?在近80年的航天史 ...

飛碟汽車循跡神舟十二號,上演“太空漫步”

飛碟汽車循跡神舟十二號,上演“太空漫步”
9月17日13時14分,神舟十二號飛船返回艙在內蒙古東風著陸場順利著陸,宇航員聶海勝.劉伯明.唐洪波在空間站生活了3個月以後,終於重返地球. 在這世紀歡慶之時,地球上也有一群被稱為"飛碟體驗 ...

天上一天地下一年?宇航員在太空3個月,會經歷多少次日出日落?

天上一天地下一年?宇航員在太空3個月,會經歷多少次日出日落?
看過<西遊記>的人,一定會對其中的一句話不陌生,那就是天上一天,地下三年.所以一直以來我們都很好奇,我們真的去了天上,地上的時間會飛速地流逝嗎?這是一個困擾了我們很多年的問題. 因為當時我 ...

第十四屆全運會獎牌榜(更新於二十三號早八點)

第十四屆全運會獎牌榜(更新於二十三號早八點)
北京時間9月22日,全運會第七個比賽日結束,當天一共產生23金,目前最新的金牌榜已經更新,山東單日奪2金以34金繼續排名第一,廣東奪4金以33金排名第二,江蘇爆發狂攬5金,以29金排名第三,浙江穩住第 ...

十月十三號海鮮價格
肥螃蟹-35 全部二母 通貨螃蟹-30 通貨螃蟹-25 大蝦20 缺氧大蝦-18 小長腿-18 大鮁魚-8 當地鮁魚-----8.5 長脖魚--5 新鮮墨魚12 小骨眼-7 大骨眼魚-25 大通骨眼魚 ...

9月20日,天舟三號貨運飛船出征太空

9月20日,天舟三號貨運飛船出征太空
#太空劇場Live# 9月20日,號稱太空快遞的#天舟三號#貨運飛船出征太空,為神舟十三號載人飛船的發射提供前置保障 ,9月20日15:10直播開始,鎖定直播地球app ,檢視發射直播現場