一文教會你嵌入式網(wǎng)絡(luò)模塊的聯(lián)網(wǎng)操作
作者:良知猶存
轉(zhuǎn)載授權(quán)以及圍觀:歡迎添加微信公眾號:Conscience_Remains
總述
????現(xiàn)在物聯(lián)網(wǎng)的概念越來越突出,軟件云端小米IOT平臺、阿里物聯(lián)網(wǎng)云等等,嵌入式百度手環(huán)開源很久了,此外網(wǎng)上關(guān)于ESP8266接入網(wǎng)關(guān)進(jìn)行遠(yuǎn)程控制的源碼不計其數(shù)。
? ?物聯(lián)網(wǎng)嵌入式端開發(fā)使用中都是各大主流網(wǎng)絡(luò)模塊,其中無線方式通信方式區(qū)分的話,主要分為兩類:一類是Zigbee、WiFi、藍(lán)牙、Z-wave等短距離通信技術(shù);另一類是LPWAN(low-powerWide-AreaNetwork,低功耗廣域網(wǎng)),即廣域網(wǎng)通信技術(shù)。
? ?至于幾種通信模塊使用的技術(shù)區(qū)別,改天可以寫一篇文章進(jìn)行詳細(xì)介紹。不過 今天我來介紹一下,我使用過的一款2G網(wǎng)絡(luò)模塊,在車載行駛中使用,在很惡劣的情況下,依舊可以保證網(wǎng)絡(luò)快速鏈接。因為現(xiàn)在的網(wǎng)絡(luò)模塊都是差不多的,尤其是IOT、LORA以及2G 3G 4G這些通過基站進(jìn)行組網(wǎng)的模塊。
有興趣的朋友可以看看百度手環(huán)的開源資料,后臺回復(fù) find me?加我好友進(jìn)行分享。
一、概念介紹
2G:第二代移動通信技術(shù)加入更多的多址技術(shù),包括TDMA和CDMA,同時2G是數(shù)字通信,因此在抗干擾能力上大大增強(qiáng)。第二代移動通信可以說對接下來的3G和4G奠定了基礎(chǔ),比如分組域的引入,和對空中接口的兼容性改造,使得手機(jī)不再只有語音、短信這樣單一的業(yè)務(wù),還可以更有效率的連入互聯(lián)網(wǎng)(電路域也可以提供internet業(yè)務(wù),只是相對來說分組域更適合internet業(yè)務(wù))。2G主要的制式也是兩個,分別是來自歐洲ETSI組織的GSM(GPRS/EDGE)和來自美洲以高通公司為主力的TIA組織的CDMA IS95/CDMA2000 1x。
百科
????看到這里大家就有疑問了,上面巴拉巴拉一堆介紹中,2G網(wǎng)絡(luò)看上去都是很落后的了,畢竟現(xiàn)在5G都出了。2G都沒人用了,有什么好講的。那我這里就給2G正個名。
????現(xiàn)在網(wǎng)絡(luò)通信技術(shù)發(fā)展的很快,手機(jī)等終端對最新通信技術(shù)的支持也是很及時,但是也是在手機(jī)這塊。要知道手機(jī)現(xiàn)在的售價是很高的,在長時間的快速更新?lián)Q代中,消費(fèi)者也逐漸接受了這些技術(shù)指標(biāo)以及消費(fèi)價格。但是在一些工業(yè)領(lǐng)域,物聯(lián)網(wǎng)產(chǎn)品中,只要很小的帶寬,網(wǎng)絡(luò)覆蓋率廣,流量費(fèi)用足夠低,甚至需要低功耗的模塊。IOT LORA就是現(xiàn)在物聯(lián)網(wǎng)選擇比較多的模塊,但是IOT依舊 也有自己的缺點。
????“NB-IOT實際使用沒有理論宣傳那么好,NB-IOT,功耗低、傳輸距離遠(yuǎn)、系統(tǒng)容量大,這些都是耳熟能詳?shù)暮锰幜?。但是,功耗低:在大部分場景下,NB并不比2G功耗低多少;傳輸距離遠(yuǎn):現(xiàn)在2G網(wǎng)絡(luò)全覆蓋,NB-IOT還在鋪網(wǎng)階段,體現(xiàn)不出來優(yōu)勢;系統(tǒng)容量大:當(dāng)前物聯(lián)網(wǎng)產(chǎn)品遠(yuǎn)遠(yuǎn)沒有把2G網(wǎng)絡(luò)占滿,更體現(xiàn)不出來NB能容納更多設(shè)備的優(yōu)勢了。價格貴:NB-IOT模塊比2G模塊貴3-4倍,算上運(yùn)營商補(bǔ)貼還是要貴不少?!?/p>
????而2G由于通信模塊成本較低,不到4G模塊的三分之一。市面上的共享單車定位和開鎖、POS刷卡支付也采用2G網(wǎng)絡(luò)連接。所以2G網(wǎng)絡(luò)現(xiàn)階段應(yīng)用還是比較廣的,所以我們之前也是采用了2G網(wǎng)絡(luò)模塊進(jìn)行的開發(fā)。
二、模塊情況
????2G模塊比較有名就是上海移遠(yuǎn)公司的M26模塊,出來時間比較長了,但是M26只有GPRS的功能。
所以我們選擇了中移的M6313模塊GPRS和GNSS二合一模塊。相關(guān)的資料現(xiàn)在也是很多了,一般我們用到是AT命令使用手冊,通信流程示例手冊。通信手冊我開發(fā)的時候還沒有,現(xiàn)在中移出了,挺開心的,又解決了開發(fā)者的一些難題。
首先我們開發(fā)使用是也是云,嵌入式端沒有使用現(xiàn)在比較火的MQTT或者CoAP這些協(xié)議,而是直接使用TCP進(jìn)行端口鏈接到服務(wù)器。
因為M6313模塊的功能和M26很像,所以這個TCP鏈接過程是可以沿用的。
三、聯(lián)網(wǎng)狀態(tài)機(jī)分析
??
?下面是當(dāng)初開發(fā)時候的寫一個聯(lián)網(wǎng)狀態(tài)機(jī),最后基本達(dá)到在CSQ在12~24時候,聯(lián)網(wǎng)時候可以最快達(dá)到4~5秒。
這個狀態(tài)機(jī)可以實現(xiàn)聯(lián)網(wǎng),設(shè)置模塊自動心跳、切換IP等功能。具體的解釋也都在代碼里面展示了。
static void TCP_Conncect(const char* ipaddr, const * ipport)
{
char* p = NULL;
p = (char*) malloc(100);
if(NULL == p)
{
LOG("malloc p error!\r\n");
}
else
{
memset(p, 0, 100);
sprintf(p, "AT+QIOPEN=\"TCP\",\"%s\",%s",ipaddr, ipport);
mdm_send_cmd_noack((u8*)p);
LOG("%s\r\n", p); //DEBUG
}
free(p);
}
/*
******************************************************************
* @brief 進(jìn)行IP修改時候IP正確性標(biāo)志清零
* @author Conqueror(征服者)
* @version V1.0
* @date 2019-6-10
******************************************************************
*/
u8 IsIPvalid = 0;
static void ChangeIP(void)
{
IsIPvalid = 0;
dprintf("Clear IsIPvalid!\r\n");
}
/*
******************************************************************
* @brief timer.c進(jìn)行調(diào)用此函數(shù)進(jìn)行判斷IP是否正常通訊
* @author Conqueror(征服者)
* @version V1.0
* @date 2019-6-17
******************************************************************
*/
TimTypeDef SecIPTimeManage;
void SecIPManageTimer(void)
{
if(SecIPTimeManage.stat == TON)
{
(SecIPTimeManage.cunt < SecIPTimeManage.des)?(SecIPTimeManage.cunt++):\
(TimerManageInit(&SecIPTimeManage,TOFF,0),IsIPvalid=0);
}
}
/*
******************************************************************
* @brief IP為正確可用的,可以進(jìn)行寫進(jìn)FLASH
* @author Conqueror(征服者)
* @version V1.0
* @date 2019-6-17
******************************************************************
*/
void IPValid(void)
{
if(devParam.secondTcp.addr[0] !=0)
{
IsIPvalid=1;
TimerManageInit(&SecIPTimeManage,TOFF,0);
LOG("IP Valid !\r\n");
}
}
/*
******************************************************************
* @brief 用于第一次連接新的IP地址的時候進(jìn)行發(fā)送測試
* @author Conqueror(征服者)
* @version V1.0
* @date 2019-6-17
******************************************************************
*/
static void TestTCP(void)
{
if(cntMdm == 1 && devParam.secondTcp.addr[0] !=0)
{
M6313SendTestData();/*確認(rèn)IP情況*/
TimerManageInit(&SecIPTimeManage,TON,2000);/*20s判斷*/
}
}
/*
******************************************************************
* @brief 判斷IP是否正確,不正確直接清零
* @author Conqueror(征服者)
* @version V1.0
* @date 2019-6-17
******************************************************************
*/
void IsTCPIPVaild(void)
{
if(gCnt.mdmTotalErr > 3&&mdmInfo.signalIntensity > 10)
{
memset(&devParam.secondTcp,0x00,sizeof(devParam.secondTcp));/*只要新的進(jìn)入則清除之前的數(shù)據(jù)*/
}
if(IsIPvalid == 0 && SecIPTimeManage.stat == TOFF && cntMdm==1\
&& econdTcp.addr[0] !=0)
{
LOG("IPInvalid !\r\n");
mdmFSMPWRRSTInit(); /*斷電重啟*/
memset(&devParam.secondTcp,0x00,sizeof(devParam.secondTcp));/*只要新的進(jìn)入則清除之前的數(shù)據(jù)*/
}
}
void mdmFSMPWRRSTInit(void)
{
MDM_STA = MDM_EXE_PWRRST_ACT; /*設(shè)置mdmComFSM狀態(tài)*/
TBoxInfoType.userInfo.bit.cntMdm = 0; /*網(wǎng)絡(luò)默認(rèn)斷開*/
SysFlag.mdmFSMRunSta = 1; /*啟動MDM_FSM,TCP錯誤處理程序?qū)⒃谝欢〞r間內(nèi)不執(zhí)行*/
gtimer.mdmFSMRun = gtimer.timer; /*MDM_FSM處理,開始時刻*/
dprintf("-mdmFSM_PWRRST_Init\r\n");
}
void STOP_MDM_FSM(void)
{
SysFlag.mdmFSMRunSta = 0; /*MDM_FSM強(qiáng)制結(jié)束*/
gtimer.mdmFSMRun = 0;
}
void mdmComFSM(void)
{
static u8 iTimes = 0; /*發(fā)AT CMD次數(shù)*/
static u8 mdmPwrOnCnt = 0; /*MDM開機(jī)次數(shù)*/
if(MDM_STA != MDM_IDLE_STA) /*FSM運(yùn)行中,刷新*/
{
refreshWorkTimer();
}
switch(MDM_STA)
{
case MDM_IDLE_STA:
break;
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*模塊斷電復(fù)位*/
case MDM_EXE_PWRRST_ACT:
LOG("*%d<-:MDM_PWR_RST[T:%d]\r\n", MDM_EXE_PWROFF_ACT, gtimer.timer);
MDM_PWR_EN_L;
gtimer.mdmFSMTimerout = 0;
MDM_STA = MDM_WAIT_PWRRST_RES;
break;
case MDM_WAIT_PWRRST_RES:
if(gtimer.mdmFSMTimerout > 2000) /*超過10秒*/
{
gtimer.mdmFSMTimerout = 0;
MDM_PWR_EN_H;
????????LOG("MDM_PWR_EN_H!\r\n");
MDM_STA = MDM_EXE_PWRON_ACT;
LOG("MDM_PWR_RST Finish!\r\n");
}
??????break;??
/*模塊關(guān)機(jī)*/
case MDM_EXE_PWROFF_ACT: /*模塊關(guān)機(jī):開機(jī)狀態(tài)模塊的PWRKEY拉低1s關(guān)機(jī)*/
LOG("\r\n*Step:%d,MDM_EXE_PWROFF_ACT,time:%d\r\n", MDM_EXE_PWROFF_ACT, gtimer.timer);
MDM_PWRKEY_EN_H;
gtimer.mdmFSMTimerout = 0;
MDM_STA = MDM_WAIT_PWROFF_RES;
break;
case MDM_WAIT_PWROFF_RES:
if(gtimer.mdmFSMTimerout > 200) /*超過1秒*/
{
gtimer.mdmFSMTimerout = 0;
MDM_PWRKEY_EN_L; /*m6313的PWRKEY處產(chǎn)生高電平*/
MDM_STA = MDM_WAIT_PWROFF_DELAY;
LOG("MDM_PWRKEY_EN_L,PWROFF_time:%d\r\n", gtimer.timer);
}
break;
case MDM_WAIT_PWROFF_DELAY:
if(gtimer.mdmFSMTimerout > 2400) /*12秒等待,模塊關(guān)機(jī)完成*/
{
LOG("MDM_POWER_OFF finish\r\n");
MDM_STA = MDM_EXE_PWRON_ACT;
}
break;
/*模塊開機(jī)*/
case MDM_EXE_PWRON_ACT: /*模塊開機(jī):在關(guān)機(jī)狀態(tài)模塊的PWRKEY拉低2s開機(jī)*/
LOG("\r\n*Step:%d,MDM_EXE_PWRON_ACT,time:%d\r\n", MDM_EXE_PWRON_ACT,gtimer.timer);
M6313ComInit();
MDM_PWRKEY_EN_H;
gtimer.mdmFSMTimerout = 0;
MDM_STA = MDM_WAIT_PWRON_RES;
break;
case MDM_WAIT_PWRON_RES:
if(gtimer.mdmFSMTimerout > 400) /*超過2秒*/
{
MDM_PWRKEY_EN_L; /*PWRKEY開機(jī)流程結(jié)束*/
mdmPwrOnCnt++;
LOG("MDM_POWER_ON,,time:%d\r\n", gtimer.timer);
MDM_STA = MDM_TX_AT_CMD;
}
break;
/*檢查MDM通信*/
case MDM_TX_AT_CMD:
LOG("\r\n*Step:%d,AT\r\n", MDM_TX_AT_CMD);//step 1
LOG("AT-%d-\r\n", iTimes);
??????mdm_send_cmd_noack((u8*)"AT");
iTimes++;
gtimer.mdmFSMTimerout = 0;
MDM_STA = MDM_WAIT_AT_RES;
break;
case MDM_WAIT_AT_RES:
if(!mdm_check_str((u8*)"OK")) /*查詢到OK*/
{
????????LOG("AT-OK-%d-\r\n",?iTimes);
if(mdmPwrOnCnt > 0)
{
MDM_STA = MDM_WAIT_GSM_READY; /*模塊開機(jī),需要一定時間,等待GSM注冊成功*/
gtimer.mdmFSMTimerout = 0;
}
????????else{
MDM_STA = MDM_START_INIT;
}
}
else if(gtimer.mdmFSMTimerout > 400) /*本次等待2秒超時*/
{
if(iTimes < EXE_AT_TIMES)
{
MDM_STA = MDM_TX_AT_CMD; /*繼續(xù)發(fā)送AT*/
LOG("continue-%d- send\"AT\"\r\n", iTimes);
}
else /*iTimes超過次數(shù)*/
{
iTimes = 0;
LOG("AT error,%d times\r\n", EXE_AT_TIMES);
if(mdmPwrOnCnt < EXE_MDM_PWRON_TIMES)
{
MDM_STA = MDM_EXE_PWRON_ACT; //進(jìn)入開機(jī)流程
LOG(".MDM_EXE_PWRON_ACT\r\n");
}
else
{
mdmPwrOnCnt = 0; /*開機(jī)次數(shù)清零*/
MDM_STA = MDM_IDLE_STA;
STOP_MDM_FSM(); /*MDM_FSM結(jié)束*/
gCnt.mdmTotalErr++;
LOG("send \"AT\" %d times error,mdmTotalErr++\r\n", EXE_AT_TIMES);
}
}
}
break;
case MDM_WAIT_GSM_READY: /*等待GSM網(wǎng)絡(luò)注冊成功*/
if(!mdmWaitGSMReady())
{
MDM_STA = MDM_START_INIT; /*GSM注冊成功*/
LOG("MDM_GSM_READY\r\n");
}
else if(gtimer.mdmFSMTimerout > WAIT_GSM_READY_MAX_TIME)
{
MDM_STA = MDM_START_INIT; /*GSM注冊失敗*/
LOG("MDM_GSM_NO_READY\r\n");
}
break;
/*MDM初始化配置*/
case MDM_START_INIT: /*開始初始化*/
LOG("\r\n*Step:%d,MDM_START_INIT\r\n", MDM_START_INIT);
MDM_STA = MDM_TX_ATQINDI_CMD;
break;
case MDM_TX_ATQINDI_CMD://AT+QINDI配置是否緩存接收到的數(shù)據(jù)
LOG("*%d<-:AT+QINDI=2[%d]\r\n", MDM_TX_ATQINDI_CMD, iTimes);
mdm_send_cmd_noack((u8*)"AT+QINDI=2"); //0-不緩存 2-緩存模式
iTimes++;
MDM_STA = MDM_WAIT_ATQINDI_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATQINDI_RES:
if(!mdm_check_result((u8*)"OK"))
{
MDM_STA = MDM_TX_ATCMVERSION_CMD;
LOG("->:OK[%d]\r\n", iTimes);
gCnt.fsmErrCnt = 0;
}
else if(!mdm_check_result((u8*)"ERROR"))
{
MDM_STA = MDM_TX_ATCMVERSION_CMD;
LOG("->:ERROR[%d]\r\n", iTimes);
gCnt.fsmErrCnt = 0;
if(iTimes < 3) //190220
{
MDM_STA = MDM_TX_ATQINDI_CMD;
}
else
{
iTimes = 0;
MDM_STA = MDM_TX_ATCMVERSION_CMD;
LOG("AT+QINDI=2,error 3 times!\r\n");
gCnt.fsmErrCnt++;
}
}
else if(gtimer.mdmFSMTimerout > 400)
{
if(iTimes < 3)
{
MDM_STA = MDM_TX_ATQINDI_CMD;
}
else
{
iTimes = 0;
MDM_STA = MDM_TX_ATCMVERSION_CMD;
LOG("AT+QINDI=2,error 3 times!\r\n");
gCnt.fsmErrCnt++;
}
}
break;
/*查版本*/
case MDM_TX_ATCMVERSION_CMD:
LOG("*<-%d:AT+CMVERSION\r\n", MDM_TX_ATCMVERSION_CMD);
memset(USART1_RX_BUF, 0, sizeof(USART1_RX_BUF));
mdm_send_cmd_noack((u8*)"AT+CMVERSION");
MDM_STA = MDM_WAIT_ATCMVERSION_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATCMVERSION_RES:
if(!mdm_check_str((u8*)"M6313"))
{
char* p = strstr((const char*)USART1_RX_BUF, (const char*)"M6313"); /*USART1_RX_STA被mdm_check_str清0了*/
if(NULL != p)//格式:M6313-MBRH0S02-release-EXT-20181025
{
char* p1 = NULL;
p1 = strchr((const char*)USART1_RX_BUF, '-'); /*第一個'-'內(nèi)容*/
if(NULL !=p1)
{
strncpy(mdmInfo.MDMSoftInfo, p1+1, 8); /*取"MBRH0S02"*/
}
char* p2 = NULL;
p2 = strrchr((const char*)USART1_RX_BUF, '-'); /*最后一個'-'內(nèi)容*/
if((NULL!=p2) && (p2!=p1))
{
strncpy(&mdmInfo.MDMSoftInfo[8], p2+3, 6);/*取"181025"*/
}
mdmInfo.MDMSoftInfo[14] = '\0';
p1 = NULL;
p2 = NULL;
LOG("Copy...\r\n");
}
else
{
LOG("Copy error!\r\n");
}
p = NULL;
????????MDM_STA?=?MDM_TX_ATQITKA_CMD;?????????
LOG("->:M6313...\r\n");
}
else if(gtimer.mdmFSMTimerout > 200)
{
????????MDM_STA?=?MDM_TX_ATQITKA_CMD;???????
LOG("Fault\r\n");
}
break;
/*TCP自動心跳 AT+QITKA=< keepalive >[,
][, ][,< keepcount>]*/ //MDM_AUTO_TICK_EN
case MDM_TX_ATQITKA_CMD:
LOG("*<-%d:AT+QITKA=1,60,300,3\r\n", MDM_TX_ATQITKA_CMD);
mdm_send_cmd_noack((u8*)"AT+QITKA=1,60,300,3");
MDM_STA = MDM_WAIT_ATQITKA_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATQITKA_RES:
if(!mdm_check_str((u8*)"OK"))
{
MDM_STA = MDM_TX_ATQSCLK_CMD;
LOG("->:OK\r\n");
}
else if(gtimer.mdmFSMTimerout > 200)
{
MDM_STA = MDM_TX_ATQSCLK_CMD;
LOG("Fault\r\n");
}
break;
/*設(shè)置慢時鐘*/
case MDM_TX_ATQSCLK_CMD: /*慢時鐘*/
LOG("\r\n*Step:%d,AT+QSCLK\r\n", MDM_TX_ATQSCLK_CMD);
??????mdm_send_cmd_noack((u8*)"AT+QSCLK=1");?/*開啟慢時鐘*///修改?lyn?2018.10.6
MDM_STA = MDM_WAIT_ATQSCLK_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATQSCLK_RES:
if(!mdm_check_str((u8*)"OK"))
{
MDM_STA = MDM_TX1_ATGSN_CMD;
????????LOG("AT+QSCLK=1?ok\r\n");
}
else if(gtimer.mdmFSMTimerout > 200) /*1s超時*/
{
MDM_STA = MDM_TX1_ATGSN_CMD;
????????LOG("AT+QSCLK=1?error\r\n");
}
break;
?????
/*第1次讀取IMEI*/
case MDM_TX1_ATGSN_CMD:
LOG("\r\n*Step:%d,read IMEI\r\n", MDM_TX1_ATGSN_CMD);
mdm_send_cmd_noack((u8*)"AT+GSN"); /*讀取IMEI*/
MDM_STA = MDM_WAIT1_ATGSN_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT1_ATGSN_RES:/*讀取IMEI*/
if(!mdm_check_str((u8*)"OK")) /*查詢到OK*/
{
Str2BCD(USART1_RX_BUF, (u8*)temp1IMEI);
MDM_STA = MDM_TX2_ATGSN_CMD; /*第2次讀取IMEI*/
LOG("-1-get IMEI ok\r\n");
}
else if(gtimer.mdmFSMTimerout > 400) /*2s超時*/
{
MDM_STA = MDM_TX_ATCIMI_CMD;
LOG("-1-get IMEI error\r\n");
}
break;
/*第2次讀取IMEI*/
case MDM_TX2_ATGSN_CMD:
LOG("\r\n*Step:%d,read IMEI\r\n", MDM_TX2_ATGSN_CMD);
mdm_send_cmd_noack((u8*)"AT+GSN"); /*讀取IMEI*/
MDM_STA = MDM_WAIT2_ATGSN_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT2_ATGSN_RES:/*讀取IMEI*/
if(!mdm_check_str((u8*)"OK")) /*查詢到OK*/
{
Str2BCD(USART1_RX_BUF, (u8*)temp2IMEI);
MDM_STA = MDM_TX_ATCIMI_CMD;
LOG("-2-get IMEI ok\r\n");
if(memcmp(&temp1IMEI[0], &temp2IMEI[0], sizeof(temp2IMEI)) == 0) /*兩次結(jié)果相等*/
{
LOG("read 2 times same IMEI\r\n");
LOG("IMEI1:\r\n");
printfHex(temp1IMEI,sizeof(temp1IMEI));
LOG("IMEI2:\r\n");
printfHex(temp2IMEI,sizeof(temp2IMEI));
if(memcmp(&deviceInfo.deviceIMEI[0], &temp2IMEI[0], sizeof(temp2IMEI)) != 0)/*和舊IMEI比較*/
{
memcpy(&deviceInfo.deviceIMEI[0], &temp2IMEI[0], sizeof(temp2IMEI));
writeFlash(); //保存參數(shù)
LOG("updata IMEI ok\r\n");
}
else
{
LOG("old IMEI ok\r\n");
}
memset(temp1IMEI, 0x00, sizeof(temp1IMEI));
memset(temp2IMEI, 0x00, sizeof(temp2IMEI));
}
else
{
LOG("read 2 times different IMEI\r\n");
}
}
else if(gtimer.mdmFSMTimerout > 400) /*2s超時*/
{
MDM_STA = MDM_TX_ATCIMI_CMD;
LOG("-2-get IMEI error\r\n");
}
break;
/*讀取IMSI*/
case MDM_TX_ATCIMI_CMD: /*讀取IMSI*/
LOG("\r\n*Step:%d,read IMSI\r\n", MDM_TX_ATCIMI_CMD);
mdm_send_cmd_noack((u8*)"AT+CIMI");
MDM_STA = MDM_WAIT_ATCIMI_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATCIMI_RES:
if(!mdm_check_str((u8*)"OK")) /*查詢到OK*/
{
char tmpIMSI[8];
Str2BCD(USART1_RX_BUF, (u8*)tmpIMSI); /*TBoxInfoType.deviceInfo.deviceIMSI*/
MDM_STA = MDM_GPRS_INTI;
LOG("get IMSI:\r\n");
printfHex(tmpIMSI,sizeof(tmpIMSI));
if(memcmp(&TBoxInfoType.deviceInfo.deviceIMSI[0], &tmpIMSI[0], sizeof(tmpIMSI)) != 0)/*和舊數(shù)據(jù)比較*/
{
memcpy(&TBoxInfoType.deviceInfo.deviceIMSI[0], &tmpIMSI[0], sizeof(tmpIMSI));
writeFlash(); //保存參數(shù)
LOG("updata IMSI ok\r\n");
}
else
{
LOG("old IMSI ok\r\n");
}
memset(tmpIMSI, 0x00, sizeof(tmpIMSI));
}
else if(gtimer.mdmFSMTimerout > 400) /*2s超時*/
{
MDM_STA = MDM_GPRS_INTI;
LOG("get IMSI error\r\n");
}
break;
/*GPRS配置*/
case MDM_GPRS_INTI:
LOG("\r\n*Step:%d,MDM_GPRS_INTI\r\n", MDM_GPRS_INTI);
MDM_STA = MDM_TX_ATE_CMD;
break;
case MDM_TX_ATE_CMD:/*開關(guān)回顯*/
LOG("\r\n*Step:%d,%s\r\n", MDM_TX_ATE_CMD, ATEx);
mdm_send_cmd_noack((u8*)ATEx); /*開關(guān)回顯*/
MDM_STA = MDM_WAIT_ATE_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATE_RES:
if(!mdm_check_str((u8*)"OK"))
{
MDM_STA = MDM_TX_ATCPIN_CMD;
LOG("%s ok\r\n", ATEx);
}
else if(gtimer.mdmFSMTimerout > 200) /*1s超時*/
{
MDM_STA = MDM_TX_ATCPIN_CMD;
LOG("ATEx error\r\n");
}
break;
case MDM_TX_ATCPIN_CMD: /*非阻塞式,最大等待時長5s*/
LOG("\r\n*Step:%d,AT+CPIN?\r\n", MDM_TX_ATCPIN_CMD);
mdm_send_cmd_noack((u8*)"AT+CPIN?");
MDM_STA = MDM_WAIT_ATCPIN_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATCPIN_RES:
if(!mdm_check_str((u8*)"READY")) /*查詢*/
{
LOG("AT+CPIN? ok\r\n");
}
else if(gtimer.mdmFSMTimerout > WAIT_ATCPIN_MAX_TIME) /*超時,最大5s*/
{
MDM_STA = MDM_TX_ATCCID_CMD; /*next*/
gCnt.mdmTotalErr++;
SIM_Handler();/*SIM卡故障*/
LOG("AT+CPIN? error\r\n");
}
break;
case MDM_TX_ATCCID_CMD: /*查詢SIM卡CCID*/
LOG("\r\n*Step:%d,read CCID\r\n", MDM_TX_ATCCID_CMD);
mdm_send_cmd_noack((u8*)"AT+CCID");
MDM_STA = MDM_WAIT_ATCCID_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATCCID_RES:
if(!mdm_check_str((u8*)"+CCID:")) /*查詢*/
{
char* tempCCID = NULL;
u8 ccidSize = 21;
tempCCID = (char*)malloc(sizeof(char)*ccidSize);
memset(tempCCID, 0x00, ccidSize);
memcpy(tempCCID, &USART1_RX_BUF[10], ccidSize);//保存CCID
tempCCID[20] = '\0'; /*添加結(jié)束符*/
LOG("tmpCCID:%s\r\n", tempCCID);
if(strstr((const char*)tempCCID, (const char*)"OK")== NULL) //無OK
{
if(strstr((const char*)tempCCID, (const char*)"\r\n")== NULL) //無回車換行
{
memcpy(m6313Debug.ccid, tempCCID, ccidSize);//更新CCID
m6313Debug.ccid[20] = '\0'; /*添加結(jié)束符*/
LOG("newCCID:%s\r\n", m6313Debug.ccid);
}
else
{
LOG("error\"OK\",");
LOG("old CCID:%s\r\n", m6313Debug.ccid);
}
}
else
{
LOG("error\"0x0A,0x0D\"\r\n");
LOG("old CCID:%s\r\n", m6313Debug.ccid);
}
free(tempCCID);
MDM_STA = MDM_TX_ATCREG_CMD;
}
else if(gtimer.mdmFSMTimerout > WAIT_ATCCID_MAX_TIME) /*超時,5s*/
{
MDM_STA = MDM_TX_ATCREG_CMD;
LOG("CCID get timeout! ");
LOG("old CCID:%s\r\n", m6313Debug.ccid);
}
break;
case MDM_TX_ATCREG_CMD: /*查詢2G網(wǎng)絡(luò)是否注冊*/
LOG("\r\n*Step:%d,AT+CREG?\r\n", MDM_TX_ATCREG_CMD);
mdm_send_cmd_noack((u8*)"AT+CREG?");
MDM_STA = MDM_WAIT_ATCREG_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATCREG_RES:
if(!mdm_check_str((u8*)",1")) /*查詢,已注冊*/
{
MDM_STA = MDM_TX_ATCSQ_CMD;
LOG("AT+CREG? ok:1\r\n");
}
else if(!mdm_check_str((u8*)",5")) /*查詢,漫游*/
{
MDM_STA = MDM_TX_ATCSQ_CMD;
LOG("AT+CREG? ok:5\r\n");
}
else if(gtimer.mdmFSMTimerout > WAIT_ATCREG_MAX_TIME) /*超時,3s*/
{
USART1_RX_STA=0;
MDM_STA = MDM_TX_ATCSQ_CMD; /*進(jìn)入下一步*/
LOG("AT+CREG? error\r\n");
}
break;
case MDM_TX_ATCSQ_CMD: /*查詢當(dāng)前信號質(zhì)量*/
LOG("\r\n*Step:%d,AT+CSQ\r\n", MDM_TX_ATCSQ_CMD);
mdm_send_cmd_noack((u8*)"AT+CSQ");
MDM_STA = MDM_WAIT_ATCSQ_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATCSQ_RES:
if(!mdm_check_str((u8*)"OK")) /*查詢*/
{
u8 len;
????????mdmInfo.signalIntensity?=?NMEA_Str2num(&USART1_RX_BUF[8],&len);?/*得到MDM的CSQ*/????????????????
MDM_STA = MDM_TX_ATQICLOSE_CMD;
LOG("MDM_CSQ=%d\r\n", mdmInfo.signalIntensity);
}
else if(gtimer.mdmFSMTimerout > 200) /*1s超時*/
??????{
MDM_STA = MDM_TX_ATQICLOSE_CMD;
LOG("get CSQ error.\r\n");
}
break;
/*AT+QICLOSE關(guān)閉TCPUDP連接*/
case MDM_TX_ATQICLOSE_CMD: /*關(guān)閉PDP使用場景*/
LOG("\r\n*Step:%d,AT+QICLOSE\r\n", MDM_TX_ATQICLOSE_CMD);
mdm_send_cmd_noack((u8*)"AT+QICLOSE");
MDM_STA = MDM_WAIT_ATQICLOSE_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATQICLOSE_RES:
if(!mdm_check_str((u8*)"ERROR")) /*關(guān)閉連接失敗*/
{
MDM_STA = MDM_TX_ATQIDEACT_CMD; /*NEXT關(guān)閉PDP*/
LOG("AT+QICLOSE ok:\"ERROR\"\r\n");
}
else if(!mdm_check_str((u8*)"CLOSE OK")) /*關(guān)閉連接成功*/
{
MDM_STA = MDM_TX_ATQIDEACT_CMD; /*NEXT關(guān)閉PDP*/
LOG("AT+QICLOSE ok:\"CLOSE OK\"\r\n");
}
else if(gtimer.mdmFSMTimerout > WAIT_ATQICLOSE_MAX_TIME) /*超時,最大2s*/
{
MDM_STA = MDM_TX_ATQIDEACT_CMD; /*NEXT關(guān)閉PDP*/
LOG("AT+QICLOSE error\r\n");
}
break;
/*AT+QIDEACT關(guān)閉PDP使用場景*/
case MDM_TX_ATQIDEACT_CMD:
LOG("\r\n*Step:%d,AT+QIDEACT\r\n", MDM_TX_ATQIDEACT_CMD);
mdm_send_cmd_noack((u8*)"AT+QIDEACT");
MDM_STA = MDM_WAIT_ATQIDEACT_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATQIDEACT_RES:
if(!mdm_check_str((u8*)"ERROR")) /*查詢*/
{
MDM_STA = MDM_TX_ATQIREGAPP_CMD;
LOG("AT+QIDEACT ok:\"ERROR\"\r\n");
}
else if(!mdm_check_str((u8*)"DEACT OK")) /*查詢*/
{
MDM_STA = MDM_TX_ATQIREGAPP_CMD;
LOG("AT+QIDEACT ok:\"DEACT OK\"\r\n");
}
else if(gtimer.mdmFSMTimerout > WAIT_ATQIDEACT_MAX_TIME) /*超時,最大45s*/
{
MDM_STA = MDM_TX_ATQIREGAPP_CMD;
LOG("AT+QIDEACT error\r\n");
}
break;
case MDM_TX_ATQIREGAPP_CMD: /*設(shè)置GPRS的APN(配置為 SIM卡簽約對應(yīng)的APN)*/
LOG("\r\n*Step:%d,AT+QIREGAPP\r\n", MDM_TX_ATQIREGAPP_CMD);
mdm_send_cmd_noack((u8*)"AT+QIREGAPP=\"CMNET\"");
MDM_STA = MDM_WAIT_ATQIREGAPP_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATQIREGAPP_RES:
if(!mdm_check_str((u8*)"OK")) /*查詢*/
{
MDM_STA = MDM_START_ATQIACT_CMD;
LOG("AT+QIREGAPP ok\r\n");
}
else if(gtimer.mdmFSMTimerout > WAIT_ATQIREGAPP_MAX_TIME) /*超時,3s*/
{
MDM_STA = MDM_START_ATQIACT_CMD; /*NEXT*/
LOG("AT+QIREGAPP error\r\n");
}
break;
case MDM_START_ATQIACT_CMD: /*開始激活PDP*/
LOG("\r\n*Step:%d,MDM_START_ATQIACT_CMD\r\n", MDM_START_ATQIACT_CMD);
iTimes = 0;
MDM_STA = MDM_TX_ATQIACT_CMD;
break;
case MDM_TX_ATQIACT_CMD: /*激活PDP,GPRS網(wǎng)絡(luò)*/
LOG("\r\n*step:%d,AT+QIACT\r\n", MDM_TX_ATQIACT_CMD);
mdm_send_cmd_noack((u8*)"AT+QIACT");
iTimes++;
LOG("AT+QIACT,count-%d-!\r\n", iTimes);
gtimer.mdmFSMTimerout = 0;
MDM_STA = MDM_WAIT_ATQIACT_RES;
break;
case MDM_WAIT_ATQIACT_RES:
if(!mdm_check_str((u8*)"OK")) /*查詢到OK*/
{
MDM_STA = MDM_START_TCP_SETUP;
LOG("AT+QIACT-OK[%d]\r\n", iTimes);
}
else if(gtimer.mdmFSMTimerout > WAIT_ATQIACT_MAX_TIME) /*10秒超時*/
{
if(iTimes < EXE_ATQIACT_TIMES)
{
MDM_STA = MDM_TX_ATQIACT_CMD; /*繼續(xù)激活PDP*/
LOG(".AT+QIACT,Continue-%d-!\r\n", iTimes);
}
else /*iTimes超過次數(shù)*/
{
iTimes = 0;
MDM_STA = MDM_START_TCP_SETUP; /*NEXT*/
LOG("AT+QIACT,%d times PDP active error\r\n", EXE_ATQIACT_TIMES);
}
}
break;
/*建立TCP連接*/
case MDM_START_TCP_SETUP:
LOG("\r\n*Step:%d,MDM_START_TCP_SETUP\r\n", MDM_START_TCP_SETUP);
MDM_STA = MDM_TX_ATQIMUX_CMD;
break;
case MDM_TX_ATQIMUX_CMD: /*配置單路連接*/
LOG("\r\n*Step:%d,AT+QIMUX\r\n", MDM_TX_ATQIMUX_CMD);
mdm_send_cmd_noack((u8*)"AT+QIMUX=0");
MDM_STA = MDM_WAIT_ATQIMUX_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATQIMUX_RES:
if(!mdm_check_str((u8*)"OK")) /*查詢*/
{
MDM_STA = MDM_TX_ATQIMODE_CMD;
LOG("AT+QIMUX ok\r\n");
}
else if(gtimer.mdmFSMTimerout > 200) /*超時,1s*/
{
MDM_STA = MDM_TX_ATQIMODE_CMD; /*NEXT*/
LOG("AT+QIMUX error\r\n");
}
break;
case MDM_TX_ATQIMODE_CMD: /*配置非透傳模式*/
mdm_send_cmd_noack((u8*)"AT+QIMODE=0"); /*非透傳*/
MDM_STA = MDM_WAIT_ATQIMODE_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATQIMODE_RES:
if(!mdm_check_str((u8*)"OK")) /*查詢*/
{
MDM_STA = MDM_TX_ATQIDNSIP_CMD;
LOG("AT+QIMODE ok\r\n");
}
else if(gtimer.mdmFSMTimerout > 200) /*超時,1s*/
{
MDM_STA = MDM_TX_ATQIDNSIP_CMD; /*NEXT*/
LOG("AT+QIMODE error\r\n");
}
break;
case MDM_TX_ATQIDNSIP_CMD: /*使用域名訪問*/
LOG("\r\n*Step:%d,AT+QIDNSIP\r\n", MDM_TX_ATQIDNSIP_CMD);
mdm_send_cmd_noack((u8*)"AT+QIDNSIP=1"); /*非透傳*/
MDM_STA = MDM_WAIT_ATQIDNSIP_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATQIDNSIP_RES:
"OK")) /*查詢*/ (!mdm_check_str((u8*)
{
MDM_STA = MDM_START_ATQIOPEN_CMD; /*NEXT*/
LOG("AT+QIDNSIP ok\r\n");
}
else if(gtimer.mdmFSMTimerout > 400) /*超時2s*/
{
MDM_STA = MDM_START_ATQIOPEN_CMD; /*NEXT*/
LOG("AT+QIDNSIP error\r\n");
}
break;
case MDM_START_ATQIOPEN_CMD: /*開始TCP連接*/
LOG("\r\n*Step:%d,MDM_START_ATQIOPEN_CMD\r\n", MDM_START_ATQIOPEN_CMD);
iTimes = 0;
MDM_STA = MDM_TX_ATQIOPEN_CMD;
break;
case MDM_TX_ATQIOPEN_CMD:
LOG("\r\n*Step:%d,AT+QIOPEN\r\n", MDM_TX_ATQIOPEN_CMD);
if(devParam.secondTcp.addr[0] !=0)/*聯(lián)網(wǎng)IP選擇*/
{
TCP_Conncect(devParam.secondTcp.addr,devParam.secondTcp.port);
}
else{
TCP_Conncect(IPaddr,IPport);}
iTimes++;
LOG("send\"AT+QIOPEN\",count-%d-\r\n", iTimes);
MDM_STA = MDM_WAIT_ATQIOPEN_RES;
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_ATQIOPEN_RES:
if(!mdm_check_str((u8*)"CONNECT OK")) /*查詢CONNECT*/
{
MDM_STA = MDM_WAIT_TCPSEND_CMD; /*TCP建立成功,進(jìn)入空閑狀態(tài)*/
LOG(".get\"CONNECT OK\"\r\n");
}
else if(!mdm_check_str((u8*)"ALREAY CONNECT"))
{
MDM_STA = MDM_WAIT_TCPSEND_CMD; /*TCP建立成功,進(jìn)入空閑狀態(tài)*/
LOG(".get\"ALREAY CONNECT\"\r\n");
}
else if(gtimer.mdmFSMTimerout > WAIT_ATQIOPEN_MAX_TIME) /*超時,30s*/
{
LOG("count-%d-,MDM_FSM timeout!\r\n", iTimes);
if(iTimes < EXE_ATQIOPEN_TIMES)
{
MDM_STA = MDM_TX_ATQIOPEN_CMD; /*繼續(xù)建立TCP*/
LOG(".continue AT+QIOPEN!\r\n");
}
else /*iTimes超過次數(shù)*/
{
iTimes = 0;
MDM_STA = MDM_IDLE_STA; /*中斷*/
STOP_MDM_FSM(); /*MDM_FSM結(jié)束*/
cntMdm = 0; /*MDM連網(wǎng)失敗*/
gCnt.mdmTotalErr++; //MDM錯誤統(tǒng)計
LOG("AT+QIOPEN:%d times exe error,TCP connect fail!\r\n",EXE_ATQIOPEN_TIMES);
}
}
break;
/*進(jìn)行延時發(fā)送任務(wù)*/
case MDM_WAIT_TCPSEND_CMD:
MDM_STA = MDM_WAIT_TCPSEND_RES; /*TCP建立成功,進(jìn)入等待發(fā)送任務(wù)*/
LOG("MDM_FSM:TCP connect suc!\r\n");
gtimer.mdmFSMTimerout = 0;
break;
case MDM_WAIT_TCPSEND_RES:
if(gtimer.mdmFSMTimerout > 400) /*等待兩秒*/
{
MDM_STA = MDM_IDLE_STA; /*TCP建立成功,進(jìn)入空閑狀態(tài)*/
MDM_NET_CONNECT_OK_HANDLE();
STOP_MDM_FSM(); /*MDM_FSM結(jié)束*/
}
break;
default:
break;
}
}
?這就是我分享的2G網(wǎng)絡(luò)模塊聯(lián)網(wǎng)的過程哈,里面代碼是實踐過的,如果大家有什么更好的思路,歡迎分享交流哈。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!