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”