STM32F103 GU906B模組GPRS、簡訊收發、撥號等功能的實現
阿新 • • 發佈:2018-11-03
這個程式搞了我很久,尤其是對如何提高響應速度上,程式流程很簡單,大概就是:
傳送AT指令->等待模組響應->一旦響應了,立即返回,並處理掉。
這個程式不一定只能用在GU906上,程式框架在任何GPRS模組上都能用,只要修改相應的AT指令,按照對應模組的AT指令流程,做下流程上的修改,就沒啥問題,框架很簡單,不像某寶上店家的那些程式碼一樣,那些程式碼反正我是看的頭暈,程式介面我都留著,只要按照相應的流程呼叫介面就好。
下面是模組的程式碼gu906.c檔案
// _ooOoo_ // o8888888o // 88" . "88 // (| -_- |) // O\ = /O // ____/`---'\____ // . ' \\| |// `. // / \\||| : |||// \ // / _||||| -:- |||||- \ // | | \\\ - /// | | // | \_| ''\---/'' | | // \ .-\__ `-` ___/-. / // ___`. .' /--.--\ `. . __ // ."" '< `.___\_<|>_/___.' >'"". // | | : `- \`.;`\ _ /`;.`/ - ` : | | // \ \ `-. \_ __\ /__ _/ .-` / / // ======`-.____`-.___\_____/___.-`____.-'====== // `=---=' // // ............................................. // 佛祖保佑 永無BUG // 佛曰: // 寫字樓裡寫字間,寫字間里程序員; // 程式人員寫程式,又拿程式換酒錢。 // 酒醒只在網上坐,酒醉還來網下眠; // 酒醉酒醒日復日,網上網下年復年。 // 但願老死電腦間,不願鞠躬老闆前; // 賓士寶馬貴者趣,公交自行程式設計師。 // 別人笑我忒瘋癲,我笑自己命太賤; // 不見滿街漂亮妹,哪個歸得程式設計師? ////////////////////////////////////////////////////////// #include <string.h> #include <stdlib.h> #include "stdio.h" #include "delay.h" #include "config.h" #include "usart4.h" #include "gu906.h" #define DEBUG_EN 1 //接收快取 #define MAXRECVBUFF USART4_BUFF #define AT "AT\r\n" //測試命令 #define ATE(x) ((x)?("ATE1\r\n"):("ATE0\r\n")) //開回顯、關回顯 #define ATESIM "AT+ESIMS?\r\n" //檢測卡是否存在 #define ATCNMI "AT+CNMI=2,1\r\n" //設定這組引數來了新資訊儲存起來 #define ATCMGD "AT+CMGD=1,4\r\n" //刪除當前儲存器中全部簡訊 #define ATCMGF "AT+CMGF=1\r\n" //0設定短訊息為PDU模式, 1設定短訊息為txet模式 #define ATCSMP "AT+CSMP=17,167,2,25\r\n" //設定文字模式的引數 #define ATUCS2 "AT+CSCS=\"UCS2\"\r\n" //設定為 UCS2 編碼字符集 #define ATGB2312 "AT+CSCS=\"GB2312\"\r\n" //設定GB2312編碼 #define ATATD "ATD%s;\r\n" //對指定手機撥號 #define ATATH "ATH\r\n" //掛機 #define ATGSM "AT+CSCS=\"GSM\"\r\n" //設定GSM字符集 #define ATCPMS "AT+CPMS=\"SM\",\"SM\",\"SM\"\r\n" //設定簡訊儲存單元為SIM卡 #define ATCSQ "AT+CSQ\r\n" //獲取訊號強度 #define ATCREG "AT+CREG?\r\n" //確保模組以及註冊到GSM網路 #define ATCIICR "AT+CIICR\r\n" //讓模組啟用 GPRS 網路,在需要反覆建立 TCP 連結的場合可提高速度 #define ATCIPSTARTOK "AT+CIPSTART?\r\n" //查詢當前是否有網路連線 #define ATCIPCLOSE "AT+CIPCLOSE=0\r\n" //關閉網路連線 #define ATCIPSCONT(x) ((x)?("AT+CIPSCONT=0,\"%s\",\"%s\",%d,2")\ :("AT+CIPSCONT\r\n")) //儲存設定 #define ATCIPSTART "AT+CIPSTART=\"%s\",\"%s\",%d\r\n" //設定TCP連線的IP和埠 #define ATCIPMUX "AT+CIPMUX=0\r\n" //單鏈接模式 #define ATCIPMODE(x) ((x)?("AT+CIPMODE=1,0\r\n")\ :("AT+CIPMODE=0,0\r\n")) //資料透傳輸模式、非透傳 #define ATCIPCFG(x) ((x)?("AT+CIPCFG=1,50,0\r\n")\ :("AT+CIPCFG=0,50,0\r\n")) //自動啟動連線命令 #define ATCIPPACK(x) ((x)?("AT+CIPPACK=1,\"4C4F47494E3A31303031\"\r\n")\ :("AT+CIPPACK=0,\"0102A0\"\r\n")) //設備註冊包、心跳包設定 #define ATCIPSEND(x) ((x)?("AT+CIPSEND=%d\r\n")\ :("AT+CIPSEND\r\n")) //設定傳送的資料長度 #define ATCGMR "AT+CGMR\r\n" //獲取基站資訊 #define ATCMGS "AT+CMGS=\"%s\"\r\n" //設定需要傳送簡訊的手機號 #define ATCMGR "AT+CMGR=%s\r\n" //設定要讀取的簡訊的位置 #define ATCSTT "AT+CSTT=\"CMNET\"\r\n" //賬號配置 #define ATCIPSCONT_C "AT+CIPSCONT?\r\n" //查詢透傳連線情況 #define GPRSSEND 0x1A #define CLOSEDTU "+++" //關閉透傳 #define OPENDTU "ATO0\r\n" //重新進入透傳 enum order{ //與命令對應的 _AT = 1,_ATE,_ATESIM,_ATCNMI,_ATCMGD,_ATCMGF,_ATCSMP,_ATUCS2, _ATGB2312,_ATATD,_ATATH,_ATGSM,_ATCPMS,_ATCSQ,_ATCREG, _ATCIICR,_ATCIPSTARTOK,_ATCIPCLOSE,_ATCIPSCONT,_ATCIPSTART, _ATCIPMUX,_ATCIPMODE,_ATCIPCFG,_ATCIPPACK,_ATCIPSEND,_ATCGMR, _ATCMGS,_ATCMGR,_GPRSSEND,_ATCSTT,_ATCIPSCONT_C,_CLOSEDTU,_OPENDTU, //額外的資料型別 _GSMSEND,_GSMSENDEND }; struct GprsData{ char *order; int olen; enum order type; }; //GPRS資料儲存位置 static char GPRS_Data[MAXRECVBUFF]={0}; static int GPRS_Dlen = 0; static u8 GPRS_Dtu_ConLock = 0; u8 RestartGprs = 0; //重啟GPRS標誌 #if GU906GSM_EN //簡訊資訊在SIM卡中的位置 static char SIMDataID[5]=""; struct user_simdata sim; #endif /********************************************************* * @function GPRS_ascii_to_hex * @role * @input * @output None * @return ********************************************************/ static int GPRS_ascii_to_hex(u8 *asc_data, u8 *hex_data, int len) { int i; u8 tmp_dat; for(i = 0; i < len; i++) { if ((asc_data[i] >= '0') && (asc_data[i] <= '9')){ tmp_dat = asc_data[i] - '0'; }else if ((asc_data[i] >= 'A') && (asc_data[i] <= 'F')){ // A....F tmp_dat = asc_data[i] - 0x37; } else if((asc_data[i] >= 'a') && (asc_data[i] <= 'f')){ // a....f tmp_dat = asc_data[i] - 0x57; }else return -1; hex_data[i] = tmp_dat; } return 0; } /********************************************************* * @function mypow * @role pow庫函式的實現,計算num的n次冪,其中n為整數 * @input num * @output n * @return 計算結果 ******************************************************* static int mypow(int num,int n) { int powint=1; int i; for(i=1;i<=n;i++) powint*=num; return powint; } */ /********************************************************* * @function FreeStr * @role 刪除字串中的字串,支援16進位制資料,無視結束符 * @input 字串、字串總長度、開始刪除的起始位置、要刪除的長度 * @output None * @return None ********************************************************/ static void FreeStr(char *str, int strsiz, int head, int len) { int i = 0; while(len--) { for(i = head; i < strsiz;i++) { str[i] = str[i+1]; } } } #if GU906GSM_EN /********************************************************* * @function GU906_ParsingSIM * @role 解析SIM卡中的簡訊資料 * @input 卡中的資料 * @output None * @return 成功返回:0,失敗返回:-1 @data +CMGR: "REC READ","18750******",,"2015/03/14 20:02:15+32" 124abcABC OK ********************************************************/ static int GU906_ParsingSIM(char *pinput) { char *p = pinput; int i; #if DEBUG_EN printf("\n分離手機號\n"); #endif if((p = strstr(p,"\",\"")) == 0) return -1; p += 3; memset(sim.phone,0,sizeof(sim.phone)); for (i = 0; (*p != '\"') && (*p != '\0'); ++i,p++){ sim.phone[i] = *p; } sim.phone[i] = '\0'; #if DEBUG_EN printf("sms.phone[%s]\r\n",sim.phone); printf("\n分離裝置型別\n"); #endif p +=2; memset(sim.dev,0,sizeof(sim.dev)); for (i = 0; (*p != ',') && (*p != '\0'); ++i,p++){ sim.dev[i] = *p; } #if DEBUG_EN printf("sms.dev[%s]\r\n",sim.dev); printf("\n分離時間\n"); #endif p += 2; memset(sim.date,0,sizeof(sim.date)); for (i = 0; (*p != '\"') && (*p != '\0'); ++i,p++){ sim.date[i] = *p; } #if DEBUG_EN printf("sms.date[%s]\r\n",sim.date); printf("\n分離資料\n"); #endif p++; memset(sim.data,0,sizeof(sim.data)); while((*p != '\0') && ((*p == '\n') || (*p == '\r')) ) p++; for (i = 0; (*p != '\0') && (*p != '\n') && (*p != '\r'); ++i,p++){ sim.data[i] = *p; } sim.data[i] = '\0'; #if DEBUG_EN printf("sms.data:[%s]\r\n",sim.data ); #endif return 0; } #endif /********************************************************* * @function GetRecvData * @role 提取字串中跟命令無關的資料,有時在進行命令操作時, 會突然收到簡訊,什麼的,這裡要做的就是處理並過濾掉這些資料。 還有模組突然復位了,這裡也做判斷,並復位CPU。 * @input 資料和資料長度 * @output None * @return None ********************************************************/ static void GetRecvData(char *pBuff, int *pLen) { int rlen = 0; char buff[5]=""; int i = 0; char *p1 = NULL; char *p2 = NULL; if((pBuff == NULL) || (*pLen == 0)) return; if (((p1 = strstr(pBuff, "+IPD,")) != 0) && ((p2 = strchr(pBuff, ':')) != 0)) { p1+=5; for (i = 0; ((p1-pBuff) < *pLen) && (i < 5) && (*p1 != ':'); ++i,++p1) { buff[i] = *p1; } buff[i] = '\0'; rlen = atoi(buff); p2++; GPRS_Dlen = ((rlen >= (*pLen - (p2 - pBuff)))?(*pLen - (p2 - pBuff)):rlen); memcpy(GPRS_Data, p2,GPRS_Dlen); rlen = GPRS_Dlen; p1 = strstr(pBuff, "+IPD,"); p2 = strchr(pBuff, ':'); rlen += ((p2+1)-p1); FreeStr(pBuff, *pLen,p1-pBuff, rlen); if((*pLen -rlen) <=3) *pLen = 0; else *pLen -=rlen; #if DEBUG_EN printf("B[%d][%s]\r\n",*pLen, pBuff); #endif } #if GU906GSM_EN else if (strstr(pBuff, "+CMTI:") && ((p1 = strchr(pBuff, ',')) != 0)){ //+CMTI: "SM",2 有簡訊訊息到來 rlen = 0; p1++; for(i = 0; *p1 != '\r' && *p1 != '\n' && *p1 != '\0' && rlen < sizeof(SIMDataID);i++, p1++){ if(*p1 >= '0' && *p1 <= '9') SIMDataID[rlen++] = *p1; } SIMDataID[rlen] = '\0'; } else if ((p1 = strstr(pBuff, "+CMGR:")) != 0){ //讀取到短訊息 GU906_ParsingSIM(p1); } #endif else if(strstr(pBuff,"[0000]") || strstr(pBuff,"Build Time")) { #if (DEBUG_EN == 1) printf("restart...\r\n\r\n"); #endif RestartGprs = 1; } } /********************************************************* * @function GetFreeBuff * @role 處理掉快取中多餘的資料,同時也起到延時200ms的作用, 讀取資料函式自帶延時10ms,所以這裡num=20, GU906傳送命令不能太快,不然GU906會因為處理不過來,而導致出錯。 * @input None * @output None * @return None ********************************************************/ static void GetFreeBuff(int num) { char buff[MAXRECVBUFF] = {0}; int siz = 0; while(num--) { siz = usart4_Receive(buff,MAXRECVBUFF); if(siz) { GetRecvData(buff, &siz); } } } /********************************************************* * @function SendAT * @role 傳送AT指令並接收 * @input gprs:要傳送的引數 * @output out:返回的引數 * @return 成功返回:_ATOK,失敗返回:_ATERROR ********************************************************/ static s8 SendAT(struct GprsData *gprs, char *out, u32 Delay) { int siz = 0; int i = 0; char *p = gprs->order; u8 dat[2]; u8 csq = 0; s8 ret = _ATERROR; char buff[MAXRECVBUFF] = {0}; RestartGprs = 0; #if (DEBUG_EN == 1) printf("\r\n------------------------------\r\n"); printf("len[%d]\r\n", gprs->olen); for(i = 0; i< gprs->olen; i++,++p) printf("%c", *p); printf("\r\n"); #endif i = 0; p = NULL; GetFreeBuff(10); usart4_Send(gprs->order,gprs->olen); if((gprs->type == _GSMSEND) || (gprs->type == _ATATD)) { ret = _ATOK; goto GU906_SENDATRET; } while(1) { for(i = 0;i<sizeof(buff);i++) buff[i]=0; siz = 0; i = 0; while(siz == 0) { siz = usart4_Receive(buff,MAXRECVBUFF); if(siz){ #if (DEBUG_EN == 1) printf("\r\nrecv:\r\n"); printf("[%s]\r\n",buff); #endif GetRecvData(buff, &siz); } if(i++ > Delay) { ret = _ATOTIME; goto GU906_SENDATRET; } } if(RestartGprs){ ret = _ATERROR; goto GU906_SENDATRET; } switch(gprs->type) { case _AT: case _ATE: case _ATCNMI: case _ATCMGD: case _ATCMGF: case _ATCSMP: case _ATUCS2: case _ATATH : case _ATGSM : case _ATCSTT: case _ATCIICR: case _ATCIPCFG: case _ATCIPPACK: case _ATCIPSCONT: case _OPENDTU: case _CLOSEDTU: case _ATGB2312: if(strstr(buff, "OK")){ ret = _ATOK; goto GU906_SENDATRET; }else if(strstr(buff, "ERROR") || strstr(buff,"NO CARRIER")) { GetFreeBuff(100); ret = _ATERROR; goto GU906_SENDATRET; } break; case _ATCPMS: if(strstr(buff, "OK") && strstr(buff, "+CPMS:")){ ret = _ATOK; goto GU906_SENDATRET; }else if(strstr(buff, "ERROR")){ ret = _ATERROR; goto GU906_SENDATRET; } break; case _ATESIM: ret = _ATERROR; if(strstr(buff, "OK")) { if((p = strstr(buff, "+ESIMS: ")) != 0) { p += 8; if(1 == (*p -'0')) ret = _ATOK; } goto GU906_SENDATRET; } break; case _ATCMGS: if(strstr(buff, ">")){ GetFreeBuff(1); ret = _ATOK; goto GU906_SENDATRET; } break; case _ATCSQ: if(strstr(buff, "OK")) { if((p = strstr(buff, "+CSQ:")) != 0) { GPRS_ascii_to_hex((u8 *)(p+6), dat, 2); csq = dat[0]*10 + dat[1]; #if DEBUG_EN printf("訊號:[%d]\r\n", csq); #endif if (csq < 99 && csq >= GPRSCSQ){ //網路訊號要大於GPRSCSQ(18) ret = _ATOK; goto GU906_SENDATRET; } else { ret = _ATERROR; goto GU906_SENDATRET; } } } else{ ret = _ATERROR; goto GU906_SENDATRET; } break; case _ATCIPSTARTOK: if(strstr(buff, "OK")) { if (strstr(buff, "+CIPSTART:")) { ret = _ATOK; goto GU906_SENDATRET; } ret = _ATERROR; goto GU906_SENDATRET; }else if(strstr(buff, "ERROR")) { ret = _ATERROR; goto GU906_SENDATRET; } break; case _ATCREG: if(strstr(buff, "OK")) { if ((p = strstr(buff, "+CREG: ")) != 0) { p += 7; if(('0' == *p) || ('5' == *p)) { ret = _ATOK; goto GU906_SENDATRET; } } ret = _ATERROR; goto GU906_SENDATRET; }else if(strstr(buff, "ERROR")) { ret = _ATERROR; goto GU906_SENDATRET; } break; case _ATCIPSEND: if (strstr(buff, ">")) { ret = _ATOK; goto GU906_SENDATRET; } else if (strstr(buff, "ERROR")){ ret = _ATERROR; goto GU906_SENDATRET; } break; case _ATCIPMUX: if(strstr(buff, "+CIPMUX: 0") && strstr(buff, "OK")) { ret = _ATOK; goto GU906_SENDATRET; }else if (strstr(buff, "ERROR")){ ret = _ATERROR; goto GU906_SENDATRET; } break; case _ATCIPMODE: if(strstr(buff, "+CIPMODE: ") && strstr(buff, "OK")) { ret = _ATOK; goto GU906_SENDATRET; }else if (strstr(buff, "ERROR")){ ret = _ATERROR; goto GU906_SENDATRET; } break; case _GPRSSEND: if(strstr(buff, "SEND OK")) { ret = _ATOK; goto GU906_SENDATRET; } break; case _ATCMGR: GetRecvData(buff, &siz); ret = _ATOK; goto GU906_SENDATRET; //break; case _ATCIPCLOSE: if (strstr(buff, "CLOSE OK") || strstr(buff, "+CME ERROR:")) { ret = _ATOK; goto GU906_SENDATRET; } else if(strstr(buff, "ERROR")){ ret = _ATERROR; goto GU906_SENDATRET; } break; case _ATCIPSTART: if(!GPRS_Dtu_ConLock) { if(strstr(buff, "CONNECT OK")){ ret = _ATOK; goto GU906_SENDATRET; } else if(strstr(buff, "RECONNECTING") || strstr(buff, "ERROR") || strstr(buff, "CONNECT FAIL")){ GetFreeBuff(100); ret = _ATERROR; goto GU906_SENDATRET; } } else if(strstr(buff, "OK")){ ret = _ATOK; goto GU906_SENDATRET; } else if(strstr(buff, "ERROR")){ ret = _ATERROR; goto GU906_SENDATRET; } break; case _GSMSENDEND: GetFreeBuff(100); ret = _ATOK; goto GU906_SENDATRET; //忽略返回資訊 /* if(strstr(buff, "+CMGS:")) { if(strstr(buff, "OK")) return _ATOK; lock = 1; } else if(lock && strstr(buff, "OK")) { return _ATOK; }else return _ATOK; //忽略返回資訊 break; */ case _ATCIPSCONT_C: if(strstr(buff,"OK")) { printf("Line:%d\r\n",__LINE__); if(0 != (p = strstr(buff,"+CIPMODE: "))) { p += 10; printf("Line:%d\r\n",__LINE__); if(1 == (*p -'0')) { printf("Line:%d\r\n",__LINE__); if(0 != (p = strstr(buff,"+CIPSTART: "))) { printf("Line:%d\r\n",__LINE__); if(strstr(buff,"218.66.59.201") && strstr(buff,"8888")) { printf("DTU OK\r\n"); GPRS_Dtu_ConLock = 1; ret = _ATOK; goto GU906_SENDATRET; } } } } GPRS_Dtu_ConLock = 0; ret = _ATOK; goto GU906_SENDATRET; }else if(strstr(buff, "ERROR")){ ret = _ATERROR; goto GU906_SENDATRET; } break; default: break; } } GU906_SENDATRET: return ret; } /********************************************************* * @function GU906_ExecuteOrder * @role 執行命令 * @input None * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ static s8 GU906_ExecuteOrder(char *Order, u32 len, enum order type, u32 num) { u32 i = 0; u32 delay_time = 1000; s8 ret = _ATOTIME; struct GprsData gprs; if(type == _ATCIPSTART) delay_time = 4000; if(type == _GPRSSEND) delay_time = 10; gprs.order = Order; gprs.olen = len; gprs.type = type; while((ret = SendAT(&gprs, NULL, delay_time)) != _ATOK) { if(ret == _ATERROR) { if(++i >= num) return _ATERROR; delay_s(1); }else return _ATOTIME; } return _ATOK; } /********************************************************* * @function GU906_init * @role GSM初始化 * @input None * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ s8 GU906_init(void) { s8 ret = _ATOTIME; // 開回顯:ATE1 關回顯:ATE0 if(_ATOK != (ret = GU906_ExecuteOrder(ATE(0), strlen(ATE(0)), _ATE, 2))) return ret; // 查詢卡是否存在 if(_ATOK != (ret = GU906_ExecuteOrder(ATESIM, strlen(ATESIM), _ATESIM, 10))) return ret; #if GU906GSM_EN // 設定簡訊模式為text模式 if(_ATOK != (ret = GU906_ExecuteOrder(ATCMGF, strlen(ATCMGF), _ATCMGF, 2))) return ret; // 設定簡訊儲存單元為SIM卡 if(_ATOK != (ret = GU906_ExecuteOrder(ATCPMS, strlen(ATCPMS), _ATCPMS, 2))) return ret; // 設定這組引數來了新資訊儲存起來 if(_ATOK != (ret = GU906_ExecuteOrder(ATCNMI, strlen(ATCNMI), _ATCNMI, 2))) return ret; #endif //刪除SIM卡中的所有簡訊 if(_ATOK != (ret = GU906_ExecuteOrder(ATCMGD, strlen(ATCMGD), _ATCMGD, 2))) return ret; //查詢訊號強度 訊號強度大於等於18才行 while(_ATOK != (ret = GU906_ExecuteOrder(ATCSQ, strlen(ATCSQ), _ATCSQ, 60))) { if(ret == _ATOTIME) return ret; } return _ATOK; } /********************************************************* * @function GU906_Module_State * @role 判斷GU906的狀態 * @input None * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ s8 GU906_Module_State(void) { return GU906_ExecuteOrder(AT, strlen(AT), _AT, 0); } /********************************************************* * @function GU906_TCP_Socket * @role 進行TCP連線 * @input IP地址與埠 * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ s8 GU906_TCP_Socket(struct Gprs_Config *GprsCon) { char cipstart[100] = {0}; s8 ret = _ATOTIME; if(GprsCon->server_ip == NULL || !GprsCon->server_port) return ret; if(!strlen((char *)GprsCon->server_ip)) return ret; //確保模組以及註冊到GSM網路 if(_ATOK != (ret = GU906_ExecuteOrder(ATCREG, strlen(ATCREG), _ATCREG, 2))) return ret; //讓模組啟用 GPRS 網路,在需要反覆建立 TCP 連結的場合可提高速度 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIICR, strlen(ATCIICR), _ATCIICR, 2))) return ret; //查詢當前是否有網路連線 while(_ATOK == GU906_ExecuteOrder(ATCIPSTARTOK, strlen(ATCIPSTARTOK), _ATCIPSTARTOK, 0)) { //關閉網路連線 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPCLOSE, strlen(ATCIPCLOSE), _ATCIPCLOSE, 2))) return ret; //儲存設定 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPSCONT(0), strlen(ATCIPSCONT(0)), _ATCIPSCONT, 2))) return ret; } //單鏈接模式 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPMUX, strlen(ATCIPMUX), _ATCIPMUX, 2))) return ret; //非資料透傳輸模式 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPMODE(0), strlen(ATCIPMODE(0)), _ATCIPMODE, 2))) return ret; //自動啟動連線命令 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPCFG(0), strlen(ATCIPCFG(0)), _ATCIPCFG, 2))) return ret; //心跳包設定 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPPACK(0), strlen(ATCIPPACK(0)), _ATCIPPACK, 2))) return ret; //連線到伺服器 //cipstart=(char *)mymalloc(100); //if(cipstart==NULL) return -1; sprintf(cipstart, ATCIPSTART,"TCP", GprsCon->server_ip, GprsCon->server_port); ret = GU906_ExecuteOrder(cipstart, strlen(cipstart), _ATCIPSTART, 3); //myfree(cipstart); return ret; } /********************************************************* * @function GU906_DTU_Socket * @role 設定透傳模式 * @input IP地址與埠 * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ s8 GU906_DTU_Socket(struct Gprs_Config *GprsCon) { char atorder[100] = ""; s8 ret = _ATOTIME; if(GprsCon->server_ip == NULL || !GprsCon->server_port) return ret; if(!strlen((char *)GprsCon->server_ip)) return ret; //atorder=(char *)mymalloc(100); //if(atorder==NULL) return -1; //查詢資料透設定情況 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPSCONT_C, strlen(ATCIPSCONT_C), _ATCIPSCONT_C, 2))) goto GU906_DTU_SOCKETEND; if(!GPRS_Dtu_ConLock) { //設定賬號 if(_ATOK != (ret = GU906_ExecuteOrder(ATCSTT, strlen(ATCSTT), _ATCSTT, 2))) goto GU906_DTU_SOCKETEND; //透傳引數設定 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPCFG(1), strlen(ATCIPCFG(1)), _ATCIPCFG, 2))) goto GU906_DTU_SOCKETEND; //設定心跳 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPPACK(0), strlen(ATCIPPACK(0)), _ATCIPPACK, 2))) goto GU906_DTU_SOCKETEND; //設定設備註冊包 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPPACK(1), strlen(ATCIPPACK(1)), _ATCIPPACK, 2))) goto GU906_DTU_SOCKETEND; //單鏈接模式 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPMUX, strlen(ATCIPMUX), _ATCIPMUX, 2))) goto GU906_DTU_SOCKETEND; //資料透傳輸模式 if(_ATOK != (ret = GU906_ExecuteOrder(ATCIPMODE(1), strlen(ATCIPMODE(1)), _ATCIPMODE, 2))) goto GU906_DTU_SOCKETEND; //儲存設定 sprintf(atorder, ATCIPSCONT(1),"TCP", GprsCon->server_ip, GprsCon->server_port); if(_ATOK != (ret = GU906_ExecuteOrder(atorder, strlen(atorder), _ATCIPSCONT, 2))) goto GU906_DTU_SOCKETEND; GPRS_Dtu_ConLock = 1; } //建立資料透連線 sprintf(atorder, ATCIPSTART, "TCP", GprsCon->server_ip, GprsCon->server_port); if(_ATOK != (ret = GU906_ExecuteOrder(atorder, strlen(atorder), _ATCIPSTART, 2))) goto GU906_DTU_SOCKETEND; GU906_DTU_SOCKETEND: //myfree(atorder); return ret; } /********************************************************* * @function GU906_DtuOrAT * @role 透傳模式與AT模式轉換 * @input None * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ s8 GU906_DtuOrAT(u8 type) { s8 ret = _ATERROR; if(type) { while(!GPRS_Dtu_ConLock) { //開啟透傳 delay_s(2); if(_ATOK != (ret = GU906_ExecuteOrder(OPENDTU, strlen(OPENDTU), _OPENDTU, 0))) goto GU906_DTUOFFONEND; GPRS_Dtu_ConLock = 1; } } else { while(GPRS_Dtu_ConLock) { //關閉透傳 delay_s(2); if(_ATOK != (ret = GU906_ExecuteOrder(CLOSEDTU, strlen(CLOSEDTU), _CLOSEDTU, 0))) { delay_s(1); if(_ATOK != (GU906_Module_State())) goto GU906_DTUOFFONEND; } GPRS_Dtu_ConLock = 0; } } GU906_DTUOFFONEND: return ret; } /********************************************************* * @function GU906_GPRS_write * @role gprs傳送資料 * @input 要傳送的資料與資料長度 * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ s8 GU906_GPRS_write(char* pdat, int len) { char atorder[20] = ""; s8 ret = -1; if(strlen(pdat) == 0) return 0; //atorder = (char *)mymalloc(20); //if(atorder == NULL) return -1; if(!GPRS_Dtu_ConLock)//非資料透模式 { //設定資料長度 sprintf(atorder, ATCIPSEND(1), len); if(_ATOK != (ret = GU906_ExecuteOrder(atorder, strlen(atorder), _ATCIPSEND, 0))) goto GU906_GPRS_WRITERET; //傳送資料 if(_ATOK != (ret = GU906_ExecuteOrder(pdat, len, _GPRSSEND, 0))) goto GU906_GPRS_WRITERET; } else { //傳送資料 usart4_Send(pdat, len); ret = _ATOK; } GU906_GPRS_WRITERET: //myfree(atorder); return ret; } /********************************************************* * @function GU906_GPRS_read * @role 查詢是否接收到資料 * @input 輸出快取大小 * @output 接收到的資料 * @return 接收到的資料長度 ********************************************************/ u32 GU906_GPRS_read(char *pout, int len) { int i = 0; if(!GPRS_Dtu_ConLock) { GPRSREAD: if(GPRS_Dlen){ for(i = 0;(i < GPRS_Dlen) && (i < (len -1)); i++){ pout[i] = GPRS_Data[i]; } memset(GPRS_Data, 0, sizeof(GPRS_Data)); GPRS_Dlen = 0; return i; }else{ GetFreeBuff(1); if(GPRS_Dlen) goto GPRSREAD; } } else { return usart4_Receive(pout,len); } return 0; } /********************************************************* * @function GU906_make_phone * @role 向指定的手機撥號 * @input 手機號 * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ s8 GU906_make_phone(char *phone) { char mphone[20]=""; sprintf(mphone, ATATD, phone); return GU906_ExecuteOrder(mphone, strlen(mphone), _ATATD, 0); } /********************************************************* * @function GU906_Answer_Phone * @role 等待電話被接聽 * @input 手機號 * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ s8 GU906_Answer_Phone(u32 Delay) { int siz = 0; u32 i = 0; char buff[MAXRECVBUFF] = ""; i = 0; while(1) { siz = 0; siz = usart4_Receive(buff,MAXRECVBUFF); if(siz){ GetRecvData(buff, &siz); if(strstr(buff, "+COLP:") && strstr(buff, "OK")){ return _ATOK; }else if(strstr(buff, "NO CARRIER") || strstr(buff, "+CREG: 1") || strstr(buff, "ERROR")){ return _ATERROR; } } if(i++ > Delay) { return _ATOTIME; } } } /********************************************************* * @function GU906_end_phone * @role 掛機 * @input None * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ s8 GU906_end_phone(void) { return GU906_ExecuteOrder(ATATH, strlen(ATATH), _ATATH, 0); } #if GU906GSM_EN /********************************************************* * @function GU906_Chinese_text * @role 向指定的手機發送中文簡訊 * @input phone 手機號指標,pmsg 短訊息指標 * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ s8 GU906_Chinese_text(char *phone,char* pmsg) { s8 ret = _ATOTIME; char atphone[50] = ""; char end[]={0x1A,0x00}; if(strlen(phone) != 11) return _ATERROR; //atphone = (char *)mymalloc(50); //if(atphone == NULL) return -1; //設定短訊息為txet模式 if(_ATOK != (ret = GU906_ExecuteOrder(ATCMGF, strlen(ATCMGF), _ATCMGF, 2))) goto GU906_CHINESE_TEXTEND; //設定GB2312編碼 if(_ATOK != (ret = GU906_ExecuteOrder(ATGB2312, strlen(ATGB2312), _ATGB2312, 2))) goto GU906_CHINESE_TEXTEND; //設定這組引數來了新資訊儲存起來 if(_ATOK != (ret = GU906_ExecuteOrder(ATCNMI, strlen(ATCNMI), _ATCNMI, 2))) goto GU906_CHINESE_TEXTEND; //設定使用者手機號 sprintf(atphone,ATCMGS,phone); if(_ATOK != (ret = GU906_ExecuteOrder(atphone, strlen(atphone), _ATCMGS, 2))) goto GU906_CHINESE_TEXTEND; //傳送資料 if(_ATOK == (ret = GU906_ExecuteOrder(pmsg, strlen(pmsg), _GSMSEND, 0))) { ret = GU906_ExecuteOrder(end, 1, _GSMSENDEND, 0); } GU906_CHINESE_TEXTEND: //myfree(atphone); return ret; } /********************************************************* * @function GU906_Read_SIM * @role 讀取簡訊資訊 * @input 簡訊在SIM卡中的位置 * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ static s8 GU906_Read_SIM(char *pnum) { s8 ret = _ATOTIME; char cmgr[20]=""; //讀取簡訊的編碼格式為GB2312 if(_ATOK != (ret = GU906_ExecuteOrder(ATGB2312, strlen(ATGB2312), _ATGB2312, 2))) return ret; //讀取短訊息 sprintf(cmgr,ATCMGR,pnum); return GU906_ExecuteOrder(cmgr, strlen(cmgr), _ATCMGR, 2); } /********************************************************* * @function GU906_DeleteSms * @role 刪除SIM卡中的所有簡訊 * @input None * @output None * @return 成功返回:_ATOK,失敗返回:_ATERROR,超時返回:_ATOTIME ********************************************************/ static int GU906_DeleteSms(void) { return GU906_ExecuteOrder(ATCMGD, strlen(ATCMGD), _ATCMGD, 2); } /********************************************************* * @function GU906_Read_UserSMS * @role 查詢並讀取簡訊資料 * @input None * @output None * @return 0,接收到新資料,-1,未接收到新資料 ********************************************************/ s8 GU906_Read_UserSMS(void) { SMSREAD: if(strlen(SIMDataID)){ #if DEBUG_EN printf("SIMDataID[%s]\r\n",SIMDataID); #endif GU906_Read_SIM(SIMDataID); GU906_DeleteSms(); memset(SIMDataID,0,sizeof(SIMDataID)); return 0; }else{ GetFreeBuff(1); if(strlen(SIMDataID)) goto SMSREAD; } return -1; } #endif
gu906.檔案如下
#ifndef _GU906_H_ #define _GU906_H_ #include "sys.h" #define GU906GSM_EN 1 //是否開啟簡訊功能 #define GPRSCSQ 18 //訊號強度,在使用GPRS功能時,最低要求訊號強度不得低於18 #define _ATOK 0 //執行成功 #define _ATERROR -1 //執行錯誤 #define _ATOTIME -2 //執行超時 #define _LINKNOT -3 //掉線了 struct Gprs_Config{ u8 *server_ip; //伺服器IP u32 server_port; //伺服器埠 }; #if GU906GSM_EN //根據實際記憶體情況而定 struct user_simdata{ char phone[15]; //使用者手機號 char dev[50]; //使用者使用的裝置 char date[50]; //接收時間 char data[200]; //接收的資料 }; extern struct user_simdata sim; s8 GU906_Read_UserSMS(void); s8 GU906_Chinese_text(char *phone,char* pmsg); #endif s8 GU906_init(void); s8 GU906_Module_State(void); s8 GU906_TCP_Socket(struct Gprs_Config *GprsCon); s8 GU906_DTU_Socket(struct Gprs_Config *GprsCon); s8 GU906_GPRS_write(char* pdat, int len); u32 GU906_GPRS_read(char *pout, int len); s8 GU906_make_phone(char *phone); s8 GU906_Answer_Phone(u32 Delay); s8 GU906_end_phone(void); s8 GU906_DtuOrAT(u8 type); #endif
main.c
#include <string.h> #include <stdlib.h> #include "stdio.h" #include "delay.h" #include "GU906.h" #include "config.h" #include "usart1.h" #include "usart4.h" int main(void) { u32 ret = 0; char buff[200]=""; struct Gprs_Config GprsCon; delay_init(); usart4_Configuration(115200); //GU900預設通訊波特率是115200 usart1_Configuration(115200); //除錯輸出埠波特率設定 delay_s(5); //剛上電 要等待10秒,等待GU906模組初始化完成 printf("\r\nBegin...\r\n"); GprsCon.server_ip = (u8 *)"210.66.59.211"; //GPRS通訊時的伺服器IP GprsCon.server_port = atoi("8888"); //GPRS通訊時的伺服器埠 //GSM初始化 while(1) { if(_ATOK == GU906_init()){ printf("GU906 init ok.\r\n\r\n"); break; } printf("init error.\r\n"); delay_s(1); } /*****************************************************************************/ //GU906 GPRS TCP 非透傳模式通訊測試 while(1) { if(_ATOK == GU906_TCP_Socket(&GprsCon)) { printf("socket ok\r\n\r\n"); delay_s(3); while(1) { ret = GU906_GPRS_read(buff, 200); if(ret) { printf("GPRS:[%d][%s]\r\n", ret,buff); if(_ATOK != GU906_GPRS_write((char *)"OK", 2)) { printf("Send Error.\r\n"); } } } } printf("GU906_TCP_Socket ERROR.\r\n"); while(1); } /*******************************************************************************/ /*****************************************************************************/ //GU906 GPRS TCP 透傳模式通訊測試 while(1) { if(_ATOK == GU906_DTU_Socket(&GprsCon)) { printf("socket ok\r\n\r\n"); delay_s(3); while(1) { ret = GU906_GPRS_read(buff, 200); if(ret) { printf("GPRS:[%d][%s]\r\n", ret,buff); if(_ATOK != GU906_GPRS_write((char *)buff, ret)) { printf("Send Error.\r\n"); } if(strstr(buff,"CLOSE")) { GU906_DtuOrAT(0); } if(strstr(buff,"OPEN")) { GU906_DtuOrAT(1); } } } } printf("GU906_TCP_Socket ERROR.\r\n"); while(1); } /*******************************************************************************/ /*****************************************************************************/ //傳送簡訊測試 while(_ATOK != GU906_Chinese_text("18750******", "123abd 測試")) { delay_s(5); } //接收簡訊測試 while(1) { if(0 == GU906_Read_UserSMS()) { printf("------------------------------\r\n"); printf("號碼:%s\r\n",sim.phone); printf("裝置:%s\r\n",sim.dev); printf("時間:%s\r\n",sim.date); printf("資訊:%s\r\n",sim.data); } delay_ms(50); } /******************************************************************************/ /*****************************************************************************/ //打電話測試 if (_ATOK == GU906_make_phone("18750******")) { //等待接聽 while(_ATOTIME == GU906_Answer_Phone(1000)) { printf("make ok\r\n"); GU906_end_phone(); } printf("make ok\r\n"); } else { printf("make error\r\n"); //SoftReset(); } /******************************************************************************/ while(1); }
連結:http://pan.baidu.com/s/1dEQwME9 密碼:9fwz