1. 程式人生 > >STM32開發 -- 4G模組開發詳解(4)

STM32開發 -- 4G模組開發詳解(4)

前面用了三篇來講基礎知識,根據這些東西可以簡單的實現4G模組的通訊了。但是離專案要求還遠遠不夠的。接下來看一下,程式碼的邏輯架構。

一、4G模組連線伺服器

前面有講到AT指令的操作,那它們該怎麼使用呢?

1、聯網階段

首先將4G連線TCP伺服器這個過程,分為幾個階段。

#define PowerOff                        ((u8)0)
#define PowerOn                         ((u8)1)
#define CheckPowPinStatus               ((u8)2)
#define CheckStartString                ((u8)3)
#define CheckSimCard ((u8)4) #define SimCardOK ((u8)5) #define ResgisterNetwork ((u8)6) #define InitCommand ((u8)7) #define Tcp_linkOK ((u8)8) #define Model_Updata ((u8)9)

2、講解各個階段

這裡需要了解一個關鍵字return。

返回型別規定了 return後面所加的量的型別,如果返回型別宣告為void,則不需要返回值
作用:一個空的 return 句子,其作用是使函式立即結束。

PS:
之前理解錯了,應該是等於某個階段的值,然後結束函式。下次跳過之前的階段,直接進入某個階段。

下面開始講解各個階段:

  • 進入PowerOff 階段
    先給4G模組供電、然後PWRKEY引腳,先低電平,延時500ms,然後再高電平,進入開機狀態。

  • 進入PowerOn階段
    首先使能USART1中斷,讓其可以接收資料。
    通過STATUS引腳確認是否為開機狀態。

    如果為關機狀態,傳送ATE0,先確認一下。
    如果AT指令傳送失敗,則結束函式,下次直接CheckSimCard階段。
    如果傳送成功,則重新配置PWRKEY引腳,先低電平,延時500ms,然後再高電平。讓其進入開機狀態。結束函式,下次直接進入CheckPowPinStatus階段。

    如果是開機狀態則,則進入CheckSimCard 階段。

  • 進入CheckPowPinStatus階段
    通過STATUS引腳確認是否為開機狀態。
    如果開機狀態進入CheckStartString階段

    如果關機狀態,則返回PowerOn階段

  • 進入CheckStartString階段
    4G模組首次上電會上傳:
    RDY
    +CFUN: 1
    +CPIN: READY
    SMS Ready

    檢查是否有接收到 RDY
    如果有接收到字串RDY,則關閉回顯(ATE0),結束函式,下次直接進入CheckSimCard階段。

    如果沒有接收到字串RDY,關閉回顯(ATE0),如果關閉回顯失敗,則結束函式,下次直接進入PowerOn階段。如果關閉回顯成功,則進入CheckSimCard階段。

    PS:
    感覺這裡反了,接收到RDY,才應該直接進入CheckSimCard階段才對吧。

  • 進入CheckSimCard階段
    傳送ATI指令,顯示模組資訊
    傳送ATE0指令,關閉回顯
    傳送AT+CPIN? 指令,查詢SIM卡的狀態
    如果傳送成功,再發送AT+CICCID指令,讀取SIM卡的CICCID。進入InitCommand階段。

    如果傳送失敗,4G模組斷電,重新進入PowerOff階段。

  • 進入InitCommand階段
    關閉回顯(ATE0),如果失敗則結束函式,下次直接進入PowerOn階段。

    如果成功,傳送AT+CGATT?,查詢是否附著網路,0是分離,1是附著。
    如果為網路附著,則進行接下來的連線TCP伺服器操作。

    如果為網路分離,先發送AT+CSQ指令,查詢訊號。
    如果傳送失敗,則結束函式,下次直接進入PowerOn階段。

    而且檢查網路是否附著這個過程,只能檢查50次。如果大於50次。
    再發送AT+CGATT=1指令,配置網路為附著狀態。然後結束函式,下次直接進PowerOn階段。

    連線伺服器階段:
    傳送AT+NETOPEN指令,開啟封包網路。如果傳送失敗了,結束函式。

    傳送AT+CIPOPEN=0,”TCP”,”211.152.x.xxx”,10102,0 指令,建立與TCP伺服器的連線。
    如果傳送失敗,再發送AT+CIPCLOSE=0指令,關閉0號link。如果關閉失敗,則結束函式,下次直接進PowerOn階段。
    接著傳送AT+NETCLOSE指令,關閉網路。如果出現+NETCLOSE:ONGOING,結束函式,4G模組斷電,重新進入PowerOff階段。

    再者進入InitCommand階段次數也是有限制的,超過20次還連不上TCP伺服器,則結束函式,4G模組斷電,重新進入PowerOff階段。

  • 進入Tcp_linkOK階段
    初始化一些計數變數,定義一些條件判斷變數。進入Tcp_linkOK階段。
    如果超過了Model_Updata階段的值9,則讓其進入PowerOn。
    最後結束函式,不再進行4G聯網配置。

3、流程圖

這裡寫圖片描述

4、串列埠列印log

ATI

Manufacturer: LYNQ
Model: LYNQ_L506
Revision: L506v03.02bxxxx
SN: P4HC1204020xxx
IMEI: 86569903007xxxx
+GCAP: +CGSM,+MS,+DS

OK

ATE0

OK

AT+CPIN?

+CPIN: READY

OK

AT+CICCID

+CICCID: 898602B5061730010xxx

OK

ATE0

OK

AT+CGATT?

+CGATT: 1

OK

AT+NETOPEN

OK

+NETOPEN:SUCCESS

AT+CIPOPEN=0,”TCP”,”211.152.x.xxx”,10102,0 

OK

+CIPOPEN:SUCCESS,0

二、 建立TCP通訊連線之後

上面有提到,定義一些條件判斷變數:

    GSMcomm.SetupPhase  = Tcp_linkOK;
    GSMcomm.SendCOMStatus = IDLE; //傳送串列埠釋放
    GSMcomm.RequestSendTCP = FALSE;
    GSMcomm.Box_BUpdata    = FALSE;   //預設升級初始化
    GSMcomm.Box_BLoadOK    = FALSE;
    g_LOG_MessageQueue.Lock_LOG = FALSE;
    VoltParaData.CarstatusChange = REQUESTSENDCARDATA;

1、講解各個階段

下面介紹伺服器連線之後的操作:

  • 進入Tcp_linkOK階段
    初始化心跳和車輛狀態計時器
    判斷串列埠狀態是否為空閒
    如果為空閒:

    判斷是否TCP請求傳送
    如果請求傳送:
    判斷是否傳送成功,如果成功。改為不請求傳送。
    判斷髮送的是否為升級指令
    如果是升級指令
    再判斷車輛狀態時不是熄火狀態。
    如果是熄火狀態
    則進入Model_Updata階段
    初始化升級計時時間

    初始化心跳計時

    否則,判斷是否列印日誌資訊
    如果列印日誌
    上傳日誌

    否則,
    判斷,心跳時間是否大於3分鐘
    如果心跳時間大於3分鐘,傳送心跳資料。

    判斷,心跳資料是否傳送成功
    如果傳送成功,則心跳時間重新計時。

    否則,判斷GPS資料計時時間是否大於1小時或者15秒
    如果GPS資料計時時間大於1小時或者15秒
    再判斷,此時所需GPS資料是否為空
    如果不為空,則重新計時心跳時間,傳送GPS資料。
    然後,重新計時GPS資料計時時間。

    否則,判斷車輛狀態計時時間是否大於40秒,和在點火開啟的情況
    如果車輛狀態計時時間大於40秒,騎在點火開啟狀態下
    判斷剩餘電量、剩餘里程、總里程不為0
    則,傳送車輛狀態資料。
    判斷,車輛狀態資料是否傳送成功
    如果傳送成功,則車輛狀態時間和心跳時間重新計時

  • 進入Model_Updata階段
    判斷升級計時時間是否大於60秒
    如果大於60秒
    初始化一些計數變數,定義一些條件判斷變數

GSMcomm.Rx_GET = GSMcomm.Rx_CNT;
GSMcomm.Box_BUpdata = FALSE;  
GSMcomm.Tcp_ReceLen = 0;      
GSMcomm.SetupPhase = Tcp_linkOK;   
GSMcomm.Box_BTUpdata = FALSE;//不能藍芽升級
GSMcomm.Box_BTloadOK = FALSE;

2、流程圖

這裡寫圖片描述

三、傳送資料

前面幾篇有講到了。傳送指令AT+CIPSEND,得到 “>” 後,傳送資料。

首先簡單的瞭解一下幾個訊號量函式

1、訊號量函式

OS_EVENT *OSMboxCreate (void *pmsg)

建立一個訊息郵箱
描述:如果有空閒事件控制塊,此功能將建立一個訊息郵箱。
引數:
    pmsg是指向您希望儲存在郵箱中的郵件的指標。 如果您將此值設定為NULL指標(即(void *)0)然後是郵箱將被視為空。
返回:
    !=(OS_EVENT *)0是指向與之關聯的事件控制時鐘(OS_EVENT)的指標建立郵箱
    * ==(OS_EVENT *)0如果沒有可用的事件控制塊

void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *perr)

在郵箱上傳送訊息
說明:此功能等待將郵件傳送到郵箱
引數:
pevent是指向與所需郵箱關聯的事件控制塊的指標
timeout是可選的超時時間(以時鐘週期為單位)。如果非零,那麼你的任務就是等待郵件到達郵箱最多時間由此引數指定。但是,如果指定0,則任務將等待永遠在指定的郵箱或直到訊息到達。
perr是指向錯誤訊息存放位置的指標。可能的錯誤訊息是:
    OS_ERR_NONE呼叫成功,您的任務收到了資訊。
    OS_ERR_TIMEOUT在指定的“超時”內未收到訊息。
    OS_ERR_PEND_ABORT郵箱中的等待已中止。
    OS_ERR_EVENT_TYPE無效的事件型別
    OS_ERR_PEND_ISR如果從ISR和結果中呼叫此函式會導致暫停。
    OS_ERR_PEVENT_NULL如果'pevent'NULL指標
    OS_ERR_PEND_LOCKED如果在排程程式被鎖定時呼叫此函式

返回:
    !=void *0是指向收到的訊息的指標
    ==void *0如果沒有收到訊息,或者如果'pevent'NULL指標或者,
    如果沒有將正確的指標傳遞給事件控制塊。

INT8U OSMboxPost (OS_EVENT *pevent, void *pmsg)

郵寄訊息到郵箱
說明:此功能向郵箱傳送訊息
引數:
pevent是指向與所需郵箱關聯的事件控制塊的指標
pmsg是指向要傳送的訊息的指標。 你不能傳送NULL指標。
返回:OS_ERR_NONE呼叫成功併發送訊息
    OS_ERR_MBOX_FULL如果郵箱已包含訊息。 你只能發一個訊息一次,因此,訊息必須在你之前消耗被允許傳送另一個。
    OS_ERR_EVENT_TYPE如果您嘗試釋出到非郵箱。
    OS_ERR_PEVENT_NULL如果'pevent'NULL指標
    OS_ERR_POST_NULL_PTR如果您嘗試釋出NULL指標

注意:1)HPT意味著最高優先順序任務

OS_EVENT *OSSemCreate (INT16U cnt)

建立一個SEMAPHORE
描述:此函式建立一個訊號量。
引數:
    cnt是訊號量的初始值。 如果值為0,則沒有資源可用(或沒有發生任何事件)。 您將訊號量初始化為a非零值,用於指定可用的資源數量(例如,如果有)10個資源,您將訊號量初始化為10)。
返回:
    !=(void *)0是指向與之關聯的事件控制塊(OS_EVENT)的指標建立訊號量
    ==(void *)0如果沒有可用的事件控制塊

void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *perr)

在SEMHHORE上釋出
描述:此函式等待訊號量。
引數:
    pevent是指向與所需關聯的事件控制塊的指標訊號量。
    timeout是可選的超時時間(以時鐘週期為單位)。如果非零,那麼你的任務就是等待資源達到此引數指定的時間量。但是,如果指定0,則任務將在指定的位置永遠等待訊號量或,直到資源可用(或事件發生)。
    perr是指向錯誤訊息存放位置的指標。可能的錯誤訊息是:
        OS_ERR_NONE呼叫成功,您的任務擁有該資源或者,您正在等待的事件發生。
        OS_ERR_TIMEOUT未在指定範圍內收到訊號量'時間到'。
        OS_ERR_PEND_ABORT訊號量的等待被中止。
        OS_ERR_EVENT_TYPE如果沒有將指標傳遞給訊號量。
        OS_ERR_PEND_ISR如果從ISR和結果中呼叫此函式會導致暫停。
        OS_ERR_PEVENT_NULL如果'pevent'NULL指標。
        OS_ERR_PEND_LOCKED如果在排程程式被鎖定時呼叫此函式
返回:無

INT8U OSSemPost (OS_EVENT *pevent)

張貼在SEMAPHORE上
說明:此功能表示訊號量
引數:
pevent是指向與所需關聯的事件控制塊的指標訊號量。
返回:
    OS_ERR_NONE呼叫成功並且訊號量已發出訊號。
    OS_ERR_SEM_OVF如果訊號量計數超過其限制。 換句話說,你有更頻繁地用訊號通知訊號量,而不是等待它
    OSSemAccept()或OSSemPend()。
    OS_ERR_EVENT_TYPE如果沒有將指標傳遞給訊號量
    OS_ERR_PEVENT_NULL如果'pevent'NULL指標。

2、傳送資料流程

接下來看一下發送資料的流程。

  • 進入Tcp_linkOK階段
    等待終端傳送資料到伺服器郵箱,直到訊息到達
    按照終端傳送到伺服器的通訊協議整合傳送資料
    打印發送資料
    獲取傳送資料個數
    傳送AT+CIPSEND指令

    等待是否返回”>”的訊號量,設定超時時間為30秒,如果大於30秒,則訊號量錯誤碼為等待超時。

    判斷,訊號量錯誤碼是否為無錯誤
    如果有錯誤
    判斷,錯誤碼是否是OS_ERR_PEND_ABORT
    如果不是,則下次進入PowerOn階段
    列印 “SEND ERRO”

    如果無錯誤
    打“>”
    TCP申請傳送時間
    傳送資料

    等待發送狀態郵箱,設定超時時間為65秒。如果大於65秒,則錯誤碼為超時OS_ERR_TIMEOUT
    判斷,資料是否傳送出去
    如果傳送資料不成功
    然後判斷是否接收到資料
    如果接收到
    列印接收到資料

    如果沒有接收到
    將接收資料buf賦0,列印

    下次進入PowerOn階段

    如果有接收訊息
    則,設串列埠狀態為空閒

3、流程圖

這裡寫圖片描述

四、接收資料

上一篇文章有講到:
接收到的不只限於伺服器下發資料,其中也包含上面AT指令的 “>” 和 +CIPSEND:SUCCESS 還有一些未知資料。

自動接收資料,格式如下:

+CIPRXGET: SUCCESS,0,0,15, 
//成功收到資料 0:自動接收模式 0:連線索引 15:接收資料個數

ddddddddddddddf //當前讀取的資料

通過解析,可以得到接收資料長度,和讀取接收資料。

1、接下來看一下接收資料的流程。

  • 進入Tcp_linkOK/Model_Updata階段
    接收資料總長度如果大於250,則讓其等於250
    檢查接收資料裡是否有 “\r\n+CIPRXGET:SUCCESS”
    如果有
    檢查接收資料個數,資料不全返回0xff
    判斷返回是不是0xff
    如果不是
    得到資料長度

    判斷接收資料個數是否大於0
    如果大於0
    判斷是否允許車機升級
    如果是,車機升級

    判斷是否允許藍芽APP升級
    如果是,藍芽APP升級

    判斷接收資料buff,首地址資料是否為通訊協議起始位
    如果是
    判斷資料長度是不是大於等於8
    如果是
    判斷接收資料buff,次地址資料是否為通訊協議訊息標誌位
    如果是
    得到通訊協議指令長度
    根據通訊協議解析接收資料buff,檢視命令標識是否為車機升級指令
    如果是
    進入Model_Updata階段、允許車機升級
    如果升級包前兩位相等,則升級OK,否則不OK。
    如果升級包第一位等於1,則程式設計頁初始化0,初始化剩餘升級包資料。
    得到升級包位元組個數
    列印升級包資訊和當前升級包資訊
    進行車機升級

    如果根據通訊協議解析接收資料buff,檢視命令標識是否為藍芽升級APP指令
    判斷接收資料長度是否大於等於10
    如果大於等於10
    進入Model_Updata階段、允許藍芽APP升級
    得到升級包位元組個數
    列印升級包資訊
    先將升級包寫入到Flash中
    進行藍芽APP升級

    否則,(解析接收資料buff,是其他指令)
    判斷是否接收資料長度大於等於2,且接收資料裡包含“\r\n”
    如果是

    判斷接收資料裡是否包含“\r\n>”
    如果是
    判斷接收資料裡是否包含“\r\n>”
    如果是
    去掉“\r\n>”

    判斷接收資料裡是否包含“\r\n+CIPSEND:SUCCESS”
    如果是
    傳送狀態郵箱
    判斷接收資料裡是否包含“\r\n+CIPSEND:SUCCESS”
    如果是
    判斷接收資料裡是否包含“\r\n”
    如果不是
    結束函式

    去掉“\r\n”

    判斷是否包含空格,去掉空格
    判斷是否包含“\r\n0”,去掉“\r\n0”
    判斷是否包含”\r\nOK\r\n”,去掉”\r\nOK\r\n”
    判斷是否包含”\r\n+SERVER DISCONNECTED:\r\n”
    如果是
    列印 PC CLOSED TCP LINK
    跳轉到 CheckPowPinStatus階段

    判斷是否包含”\r\n+CFUN: 1\r\n”
    如果是
    列印GSM Modem Reset Self….
    跳轉到 PowerOn階段

    判斷是否包含“\r\n”
    如果是
    處理其他未知指令

    如果返回的是0xff
    則,如果接收資料長度小於2
    則結束函式

    判斷是否包含”\r\n”
    如果是
    去掉”\r\n”

2、流程圖

這裡寫圖片描述