NBIOT-BC28模塊程序操作接口編寫(基于STM32F103ZET6)
項(xiàng)目最終效果,大家可以根據(jù)API的去實(shí)現(xiàn)自己的業(yè)務(wù)需求。
程序設(shè)計(jì)結(jié)構(gòu)體,存儲(chǔ)獲取模組的相關(guān)信息
typedef struct NETWORK_INFO{//初始化NB模塊的狀態(tài)u8 Init_NB_Status ;//NB模塊的信號(hào)強(qiáng)度u8 signalCSQ ;//IMEI卡號(hào)char IMEI[16];//IMSI卡號(hào)char IMSI[16];//注網(wǎng)標(biāo)志位bool Register_NetWork_Flag ;//服務(wù)器連接標(biāo)志位bool Connect_Server_Flag ;} NETWORK_DEVICE_INFO;extern NETWORK_DEVICE_INFO NBIOT_MODULE_INFO ;
下面實(shí)現(xiàn)操作NB的方法,首先是最核心的NB指令發(fā)送函數(shù),有了這樣一個(gè)函數(shù),后面的應(yīng)用才能寫,這里用的是中斷采集的方式,后續(xù)可以更改成DMA接收,傳輸效率會(huì)更高一些,等下次更新一個(gè)新的版本,附帶完整的測(cè)試工程。
/** 函數(shù)名:NBIOT_Cmd* 描述 :對(duì)NBIOT模塊發(fā)送AT指令* 輸入 :cmd,待發(fā)送的指令* reply1,reply2,期待的響應(yīng),為NULL表不需響應(yīng),兩者為或邏輯關(guān)系* waittime,等待響應(yīng)的時(shí)間* 返回 : 1,指令發(fā)送成功* 0,指令發(fā)送失敗* 調(diào)用 :被外部調(diào)用*/bool NBIOT_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime ){bool status = false ;USART4_RX_STA = 0; //從新開始接收新的數(shù)據(jù)包NB_FramLength = 0 ;memset(RXBuffer, 0, RXBUFFER_LEN); //清空接收緩沖u4_printf("%s\r\n", cmd);if ( ( reply1 == 0 ) && ( reply2 == 0 ) ) //不需要接收數(shù)據(jù)return true;Delay_ms ( waittime ); //延時(shí)RXBuffer[NB_FramLength] = '\0';printf("RXBuffer:%s\n", RXBuffer);if(strstr((char *)RXBuffer, reply2) != NULL){printf("ackerror:%s\n", reply2);return false ;}if(strstr((char *)RXBuffer, reply1) != NULL){printf("acksuccess:%s\n", RXBuffer);//如果匹配到斷連標(biāo)志,就重新建立連接if(strstr((char *)RXBuffer, "+NSOCLI: 1") != NULL){status = NB_Create_TCP("120.78.136.134", 9002);if(false == status){printf("重新創(chuàng)建TCP連接失敗\n");return -1 ;}else{printf("重新創(chuàng)建TCP連接成功\n");}}return true ;}return false ;}
根據(jù)實(shí)現(xiàn)的發(fā)送函數(shù),下面來(lái)實(shí)現(xiàn)驅(qū)動(dòng)NB模塊的接口以及整套初始化流程,可以減少開發(fā)者的負(fù)擔(dān)。
在對(duì)NB模塊的編程中,其實(shí)就是對(duì)串口操作,通常我們會(huì)有一個(gè)與模塊的應(yīng)答指令,尋問(wèn)模塊是否在線,進(jìn)而來(lái)判斷模塊是否硬件是否已經(jīng)連接正確或者模塊是否損壞。
//檢查模組是否在線bool checkNBIOT(void){return NBIOT_Cmd("AT", "OK", NULL, 100);}
當(dāng)發(fā)出AT時(shí),模組應(yīng)給主機(jī)回復(fù)OK作為應(yīng)答,這樣主機(jī)就和模組建立通信。
根據(jù)前面寫過(guò)的一篇文章,我們還要對(duì)BC28做一系列的適配操作,比如,使能自動(dòng)尋網(wǎng)、設(shè)置頻段(電信為5,移動(dòng)為8)、打開優(yōu)碼控制選項(xiàng)第二項(xiàng)、第三項(xiàng)。
//NBIOT基礎(chǔ)配置===>band 5 ==> 電信卡 8===>移動(dòng)卡bool BASE_Config_NBIOT(int band){char buffer[50] = {0};bool status = true ;//設(shè)置頻段sprintf(buffer, "AT+NBAND=%d", band);status = NBIOT_Cmd(buffer, "OK", NULL, 100);//自動(dòng)尋網(wǎng)status = NBIOT_Cmd("AT+NCONFIG=AUTOCONNECT,TRUE", "OK", NULL, 100);//打開優(yōu)碼控制2,3項(xiàng)status = NBIOT_Cmd("AT+NCONFIG=CR_0354_0338_SCRAMBLING,TRUE", "OK", NULL, 100);status = NBIOT_Cmd("AT+NCONFIG=CR_0859_SI_AVOID,TRUE", "OK", NULL, 100);return status ;}
3.1 IMSI 設(shè)備識(shí)別碼
NB模塊或者其它的一些通信模塊,它都會(huì)有一個(gè)獨(dú)有的IMEI號(hào),它是模塊生產(chǎn)廠家指定的一個(gè)設(shè)備識(shí)別碼,通過(guò)指令A(yù)T+CGSN=1來(lái)獲取,功能函數(shù)如下:
bool Get_IMEI(void){bool status = true ;status = NBIOT_Cmd("AT+CGSN=1", "OK", "ERROR", 100);if(status == true){memcpy((char *)NBIOT_MODULE_INFO.IMEI, RXBuffer + 8, 15);return true ;}return false ;}
3.2 IMSI 國(guó)際移動(dòng)用戶識(shí)別碼
通常該碼存儲(chǔ)在SIM卡中,我們可以使用AT+CIMI這條指令來(lái)獲取,這樣可以知道卡到底有沒有插好或者是否存在,功能編寫如下:
//獲取IMSIbool Get_IMSI(void){bool status = true ;status = NBIOT_Cmd("AT+CIMI", "OK", "ERROR", 2000);if(status == true){memcpy((char *)NBIOT_MODULE_INFO.IMSI, RXBuffer + 2, 15);return true ;}return false ;}
模塊注冊(cè)相應(yīng)的運(yùn)行商成功,就會(huì)收到相應(yīng)的標(biāo)志,標(biāo)志已經(jīng)注冊(cè)成功,功能編寫如下:
//獲取入網(wǎng)狀態(tài)bool Get_Enter_Net_Status(void){int status = 0 ;bool cmd_status = false ;char buffer[30] = {0};cmd_status = NBIOT_Cmd("AT+CGATT?", "OK", "ERROR", 5000);memcpy(buffer, RXBuffer + 9, 1);status = atoi(buffer);if(1 == status)return true;elsereturn false ;}
BC28的模組信號(hào)級(jí)別是0-31,返回99則可能模塊還沒有初始化完畢,或者信號(hào)異常。低于10可以認(rèn)為信號(hào)為低,一般別的通信模組(比如4G,WIFI等)如果低于這個(gè)級(jí)別,數(shù)據(jù)可能出現(xiàn)丟包狀態(tài),但NB模塊號(hào)稱只要大于8,即可無(wú)丟損數(shù)據(jù),實(shí)現(xiàn)函數(shù)如下:
//獲取信號(hào)強(qiáng)度int Get_CSQ(void){int signal_value = -1;bool status = true ;char csq_buffer[50] = {0};status = NBIOT_Cmd("AT+CSQ", "+CSQ", NULL, 100);if(status == true){memcpy(csq_buffer, RXBuffer + 7, 2);signal_value = atoi(csq_buffer);return signal_value ;}return 99 ;}
這里一定要注意一點(diǎn),模組刷寫的固件帶ONT版本的,是不能把數(shù)據(jù)傳到私有的服務(wù)器的,只有不帶ONT的才可以,版本可以通過(guò)AT指令的ATI查看。
如果版本是帶ONT,而你又想傳數(shù)據(jù)到自己的后臺(tái),那就請(qǐng)你連接移遠(yuǎn)的FAE,提供最新的固件和固件燒寫工具給你,如圖所示,利用軟件對(duì)NB模組進(jìn)行固件更新。
//創(chuàng)建TCP Socket===>成功返回1,失敗返回0u8 NB_Create_TCP(const char *server_ip, int port){char buffer[50] = {0};bool status = true ;//1.創(chuàng)建一個(gè)TCP Socketstatus = NBIOT_Cmd("AT+NSOCR=STREAM,6,56000,1", "OK", NULL, 2000);//如果創(chuàng)建成功,則連接遠(yuǎn)程服務(wù)器和端口號(hào)if(true == status){sprintf(buffer, "AT+NSOCO=1,%s,%d", server_ip, port);status = NBIOT_Cmd(buffer, "OK", NULL, 2000);if(true == status)return 1 ;elsereturn 0 ;}return 0 ;}//關(guān)閉Socket連接bool Close_Socket(void){bool status = true ;status = NBIOT_Cmd("AT+NSOCL=0", "OK", NULL, 2000);return status ;}
//NBIOT發(fā)送數(shù)據(jù)到后臺(tái)服務(wù)器/*Data_Length:要發(fā)送到后臺(tái)的原始數(shù)據(jù)的長(zhǎng)度hex_data:要發(fā)送到后臺(tái)的,但必須將原始數(shù)據(jù)轉(zhuǎn)換成十六進(jìn)制編碼的數(shù)據(jù)*/bool NB_Send_Data_To_Server(int Data_Length, char *hex_data){bool status = true ;char data_buffer[1024] = {0};sprintf(data_buffer, "AT+NSOSD=1,%d,%s", Data_Length, hex_data);printf("數(shù)據(jù)上傳:\n");printf("%s\n", data_buffer);status = NBIOT_Cmd(data_buffer, "OK", "ERROR", 5000);return status ;}
通常給模組復(fù)位,一般是設(shè)置完參數(shù)后,手冊(cè)要求要進(jìn)行復(fù)位操作,復(fù)位大概需要5s的時(shí)間,模組才會(huì)穩(wěn)定下來(lái),所以Delay_ms(5000)最好不要丟掉,否則其它的指令可能出現(xiàn)設(shè)置失敗的情況。
//復(fù)位NBIOT模組bool NB_RESET(void){bool status = true ;status = NBIOT_Cmd("AT+NRB", "OK", NULL, 10000);return status ;}
/*** 功能:初始化NBIOT* 參數(shù):None* 返回值:初始化結(jié)果,非0為初始化成功,0為失敗*/int initNBIOT(void){bool status_return = false ;while(1){switch(NBIOT_MODULE_INFO.Init_NB_Status){//1、檢查NBIOT模塊是否在線case 0:status_return = checkNBIOT();if(false == checkNBIOT){printf("NB模塊硬件故障..\n");return 0 ;}else{printf("NB模塊正常連接\n");NBIOT_MODULE_INFO.Init_NB_Status = 1 ;}break ;//2、進(jìn)行NBIOT的基礎(chǔ)配置case 1:status_return = BASE_Config_NBIOT(5);if(false == status_return){NBIOT_MODULE_INFO.Init_NB_Status = 0 ;printf("配置自動(dòng)尋網(wǎng)與優(yōu)碼控制第2、3項(xiàng)失敗\n");}else{NBIOT_MODULE_INFO.Init_NB_Status = 2 ;printf("配置自動(dòng)尋網(wǎng)與優(yōu)碼控制第2、3項(xiàng)成功\n");}break ;//3、復(fù)位模組case 2:status_return = NB_RESET();if(false == status_return){printf("模組復(fù)位失敗\n");NBIOT_MODULE_INFO.Init_NB_Status = 0 ;}else{printf("模組復(fù)位成功\n");Delay_ms(2000);NBIOT_MODULE_INFO.Init_NB_Status = 3 ;}break ;//4、獲取NB模組號(hào)case 3:status_return = Get_IMEI();if(false == status_return){printf("沒有模組卡號(hào),模塊故障\n");NBIOT_MODULE_INFO.Init_NB_Status = 0 ;break ;}else{NBIOT_MODULE_INFO.Init_NB_Status = 4 ;printf("模組號(hào):%s\n", NBIOT_MODULE_INFO.IMEI);}break ;//獲取SIM卡卡號(hào),確認(rèn)設(shè)備是否已經(jīng)插卡case 4:status_return = Get_IMSI();if(false == status_return){printf("沒有插SIM卡,模塊無(wú)法連接網(wǎng)絡(luò)\n");NBIOT_MODULE_INFO.Init_NB_Status = 0 ;break ;}else{printf("SIM卡號(hào):%s\n", NBIOT_MODULE_INFO.IMSI);NBIOT_MODULE_INFO.Init_NB_Status = 5 ;}break ;//查看注網(wǎng)狀態(tài)case 5:status_return = Get_Enter_Net_Status();if(false == status_return){printf("入網(wǎng)失敗,請(qǐng)重新復(fù)位模塊\n");NBIOT_MODULE_INFO.Init_NB_Status = 5 ;break ;}else{printf("模組入網(wǎng)成功..\n");NBIOT_MODULE_INFO.Init_NB_Status = 6 ;}break ;//獲取信號(hào)強(qiáng)度case 6:NBIOT_MODULE_INFO.signalCSQ = Get_CSQ();if(99 == NBIOT_MODULE_INFO.signalCSQ){printf("設(shè)備無(wú)信號(hào)....\n");NBIOT_MODULE_INFO.Init_NB_Status = 5 ;}else{printf("信號(hào)級(jí)別:%d\n", NBIOT_MODULE_INFO.signalCSQ);NBIOT_MODULE_INFO.Init_NB_Status = 7 ;}break ;default:break ;}if(7 == NBIOT_MODULE_INFO.Init_NB_Status){break ;}}return 1;}
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!





