硬件環境
MCU:STM32F103RET6 (調試器:J-Link)
GSM模塊:Ai-Thinker_A6 (安信可)(還需要配一個串口打印工具,當初選這個模塊純粹是因為價格是最便宜的)
-------------------------------------------------------------------------
軟件環境
Keil4
-------------------------------------------------------------------------
開篇廢話
經過兩周時間的編碼、調試,終於實現了GSM模塊通過GPRS連接服務器的功能,並成功移植到了公司自己的項目里面。趁着有點空,我就把整個開發調試的過程記錄下來,給自己做個備忘,也給大家做個參考。
-------------------------------------------------------------------------
時間列表
2天時間完成底層驅動部分函數的編寫。
4天時間完成模塊與服務器的連接,測試實例:獲取服務器的RTC信息。
1天時間移植到公司的項目,純代碼搬運工作。
3天時間測試修復BUG並優化代碼,找BUG的這幾天,有1天只修改了1條代碼,我也是醉了。
-------------------------------------------------------------------------
函數清單和注意事項
(底層驅動部分)
1. IO口初始化:控制 IO 和通訊 IO,控制包括電源控制,復位和低功耗模式,通訊就是串口啦,相信大家應該都很熟悉了。
當然在這個基礎上還可以組合出復位的功能,復位在GPRS連接出錯的時候會用到。
2. 串口初始化:模塊的波特率為115200,8位數據位,1位停止位,沒有校驗位和流控。
串口還需要兩個發送函數,發送一個字節和發送一串字符串的。串口中斷處理函數放到后面說。
3. AT指令操作:發送AT指令
設置GPRS數據長度
發送GPRS數據內容
接收GPRS數據內容
AT指令/GPRS數據解析
4. 串口中斷函數:包含AT指令/GPRS數據解析 和 接收GPRS數據內容,判斷AT指令是否發送成功。
AT指令返回的結束符除了設置GPRS數據長度的是'>',其他都是"\r\n"。但是在判斷接收結束的時候不能只考慮這兩種情況,還有一個情況需要特殊處理,那就是當接收到GPRS數據的時候,完全有可能會出現'\r','\n'對應的十六進制數。解決的辦法就是在接收到"+CIPRCV:xxx,"的時候,附帶判斷接收到的數據長度,"xxx"代表的是GPRS數據長度信息,字符型格式,在這里還需要做一個格式轉換。數據長度的位數根據字符 ','來進行判斷,',' 將AT命令和GPRS數據進行分割。"xxx"換算過來的數值決定了 ',' 后面接收到的數據長度。
由於目前采用的SIM卡模塊內部沒有自帶緩沖區,在GPRS數據接收的時候,需要另外開辟一個存儲空間用於數據的臨時存儲,建議采用環形緩沖區Buffer, 將串口接收到的數據按順序存儲,這個部分在串口中斷函數里面實現。在大循環里面將數據取出處理,並設置相關標志位。我一開始設計的時候只開辟了一個非環形的緩沖區,每次接收到完整的數據,會從緩沖區的0地址重新開始存儲,那么就會導致未及時處理的數據被新的數據沖掉。 不知道有沒有別家的SIM卡模塊是自帶緩沖區的。
(主循環部分)
1. TCP/IP連接流程控制:
step1、"AT\r\n"//檢測模塊串口工作
step2、"AT+CCID\r\n"//檢查是否插卡
step3、"AT+CREG?\r\n"//檢查網絡注冊情況
step4、"AT+CGATT=1\r\n"//附着網絡
step5、"AT+CGDCONT=1,\"IP\",\"CMNET\"\r\n"//設置PDP參數
step6、"AT+CGACT=1,1\r\n"//激活網絡
step7、 "AT+CIPSTART=\"TCP\",\"121.41.xxx.xxx\",port\r\n"//連接TCPIP服務器
我用的這個模塊硬件初始化差不多就要10秒了,在硬件初始化完成后,按照以上七步進行服務器連接,測試下來,連接的成功率還是蠻高的。前面兩步是硬件檢測用的,如果這兩步都測不過,那就需要檢查下硬件是否完整。三到六步如果返回ERROR,可重復發送,直至返回OK,每一步之間可間隔數秒。最后一步如果失敗,需先關閉連接,再重新發起連接。如果第七步一直連接不成功,那么可以通過控制 IO 復位模塊,當然也可以先確認下你的服務器的端口是否打開。
我的經驗是連接和通訊的過程中,如果出現錯誤的情況,復位模塊是最有效和快捷的方式。在確認硬件連接正常的情況下,如果多次發送命令失敗,返回ERROR的話,那你還是乖乖的復位它吧。
另外兩個AT命令也很好用
"AT+CIPCLOSE\r\n"//關閉TCPIP連接
"ATE0\r\n"//關閉回顯,關閉自己發給模塊的串口數據,調試的時候可以不開啟這個功能,方便觀察
2. 數據鏈路層數據處理:實現GPRS數據接收/發送控制,存儲串口中斷接收到的數據,發送GPRS數據長度和GPRS數據內容。
這個函數里面需要注意的是發送GPRS長度和數據的操作,需要在一次操作流程里面完成。我一開始腦殘的將GPRS數據長度和數據發送分開處理,導致設置完數據長度后,發送狀態處於准備好的狀態,此時只要檢測到有數據是需要發送的,便會通過GPRS發送出去,而無法保證是當前數據長度對應的數據幀(我在這里一共開辟了8個數據緩存,但是沒有對發送狀態進行分開判斷)。在設置完數據長度后,需要判斷是否接收到字符'>',大概需要50毫秒的時間。一開始分開發送也是和這個'>'字符的操作有關的,我已經幫大家試過了,連在一起發就好了。
發送完GPRS長度幀后,返回字符'>',接着發送數據幀,在模塊返回"OK"之前,發送的數據都會被發送到服務器,導致通訊出錯。所以在數據發送后,需要等待判斷模塊是否已經發送成功。
3. 超時判斷:檢測GPRS數據是否發送失敗,失敗后可關閉TCP/IP連接,進行重連,如果還是失敗,可復位模塊,重新進行TCP/IP連接流程。
-------------------------------------------------------------------------
小技巧
1、官方的例程里面,在GPRS數據發送完之后,需要發送結束符0x1A,其實是不需要的。
最近一直有朋友問我要代碼,我整理了一下,代碼和資料已經放到資源里面了,有需要的朋友請自行下載。