版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、<p><b> 前 言</b></p><p> 隨著手機的普及,短信的應用在信息時代已經異軍突起,由其是在企業(yè)中的應用得到了越來越突出的表現。目前開通企業(yè)短信平臺企業(yè)眾多,比如松下電器、上海大眾、天氣預報、奧運2008 、中華美食、九寨溝等等……廣泛的客戶基礎、極強的客戶接受程度、獨特的交流方式、低廉的通信成本,已經使短信成為人們相互溝通的主要手段之一,不少企業(yè)已意識到基于
2、短信的解決方案在企業(yè)應用的潛在價值,短信將象電話一樣,成為企業(yè)內部、企業(yè)與客戶之間信息交流必不可少的手段。</p><p> 目前,主要有三種發(fā)送短信的方式: 1、 網關方式:就是向當地的電信部門申請,不需要額外的設備,適用于大型的通信公司,像華為、傲天、中興、亞信等?! ?、 終端方式:就是借助像GSM MODEM之類的設置(支持AT指令的手機也行),通過數據線連接電腦,來
3、發(fā)送短信,用這種方法比較適用于小型及個人。要實現這種方式必須理解串口通信、AT指令、短信編碼、解碼,這也是本文討論的重點?! ?、 利用一些網站來實現,方式簡單,不過對網站依賴性太高,對網絡的要求也比較高,非常不適于進行項目開發(fā)。</p><p> 在本系統(tǒng)即是采用計算機收發(fā)短信就是直接用計算機控制運行了GSM通信系統(tǒng)的短信終端,因而其收發(fā)短信的原理與手機是本質相同的。</p><
4、;p> 圖0-1終端短信連接示意圖:</p><p> 我們需要利用以TC35模塊為主的硬件組成一個TC35終端設備,并與電腦通過RS-232C串口相連,并自行編制在PC上運行的短信息收發(fā)軟件,就可以組成一個短信收發(fā)系統(tǒng)。并通過VC++開發(fā)平臺開發(fā)一款具有企業(yè)使用功能的短信群發(fā)系統(tǒng)。為了能滿足小型企業(yè)的使用需求,經過考察我們先確定以下系統(tǒng)的基本功:短信管理、自動應答、定時發(fā)送、統(tǒng)計查詢、客戶分組管理、常
5、用短語管理、短信訂閱管理、短信計費管理、手機號碼段管理以及一些拓展功能。</p><p> 第1章 系統(tǒng)組成與功能</p><p><b> 1.1 系統(tǒng)構成</b></p><p> 1.標準RS232串口</p><p> 圖1-1標準RS232串口</p><p> 2. 計算機+
6、(RS232)+GSM通信模塊</p><p> 圖1-2 硬件系統(tǒng)構成 </p><p> 1.2 GSM通信模塊</p><p> 下圖是一款GSM模塊,它就是西門子公司的TC35,它由GSM基帶處理器、電源專用集成電路、射頻電路和閃速存儲器等部分組成,負責處理GSM蜂窩設備中的音頻、數據和信號,內嵌的軟件部分執(zhí)行應用接口和所有GSM協(xié)議棧的功能。TC3
7、5支持中文短信息,工作在EGSM900和GSM1800雙頻段,電源范圍為3.3~5.5V,可傳輸語音和數據信號,消耗功率在EGSM900(4類)和GSM1800(1類)分別為2W和1W,通過接口連接器和天線連接器分別連接SIM卡讀卡器和天線。TC35的數據接口(CMOS電平)通過AT命令可雙向傳輸指令和數據,可選波特率為300bit/s~115kbit/s,自動波特率為1.2k~115kbit/s。它支持文本和PDU格式的,可通過AT命
8、令或關斷信號實現重啟和故障恢復。</p><p> 圖1-3 TC35終端電路圖</p><p><b> 1.3 系統(tǒng)功能</b></p><p><b> 1.短信管理:</b></p><p><b> 發(fā)送短信</b></p><p>
9、 對保戶,可滿足發(fā)送續(xù)保提示;實時關懷;信息發(fā)布。</p><p> 對員工,可滿足內部通知;流程通報;獎勵通告;消息發(fā)布。</p><p> 接收短信:接收投訴、查詢、咨詢等短信;還提供短信的回復、轉發(fā)和刪除功能。</p><p> 2.自動應答:事先設置好相應的應答標志和短信息內容,實時讀取保戶和員工的咨詢信息;保戶和員工通過手機向系統(tǒng)輸入查詢代碼(與應答
10、標志對應的),系統(tǒng)自動向保戶和員工手機發(fā)送相應的應答信息。</p><p> 3.定時發(fā)送:預先編制好短信,設定發(fā)送時間,到了設定的時間系統(tǒng)自動發(fā)出信息。如向保戶和員工發(fā)送生日祝福、節(jié)日問候、續(xù)保通知等等。</p><p> 4.統(tǒng)計查詢:可以按照姓名、手機號進行客戶信息查詢,提供發(fā)送查詢、接收查詢、費用統(tǒng)計等</p><p> 5.客戶分組管理:根據公司的需
11、要和習慣,可對保戶和員工進行基本分類(如對保戶按區(qū)域分內、按險種分內等;對員工按部門或按區(qū)域分內);當員工或保戶發(fā)生變更時,新建、修改或刪除員工或保戶資料。</p><p> 6.常用短語管理:根據員工和保戶的日常需要,公司系統(tǒng)管理員或操作員可按需增加、修改或刪除短語種類;增加、修改或刪除具體的常用短語,以備隨時取用。</p><p> 7.短信訂閱管理:向保戶提供新險種信息定閱短信服
12、務(如"我要訂閱有關小孩的險種信息","煩請訂閱體檢和專家咨詢信息"等);提供處理保戶訂閱信息申請,并編輯制作保戶所訂閱信息,設定時間,定時給保戶發(fā)送。</p><p> 8.短信計費管理:在編輯訂閱短信時,設定短信的費用,系統(tǒng)自動將此短信發(fā)送給客戶?;蛳到y(tǒng)自動統(tǒng)計匯總短信收費資料并將資料存儲,供用戶短信查詢。</p><p> 9.手機號碼段管
13、理:當企業(yè)基于廣泛宣傳的目的,需要進行大規(guī)模短信廣告時,系統(tǒng)支持按手機號碼段進行廣告呼叫。系統(tǒng)提供全國號碼段庫,可自動按號碼段生成群發(fā)號碼,可 從選定的號段中隨機抽取部分號碼發(fā)送,還可以設定過濾掉部分尾號,也可指定部分尾號發(fā)送。</p><p><b> 10.拓展功能</b></p><p> 數據導入:客戶信息及接收者手機號碼可以從現有數據庫文件批量導入,無須
14、費時費力逐個輸入。</p><p> 數據備份:通訊錄和發(fā)送記錄可以方便地導出為Excel或文本格式保存。</p><p> 企業(yè)MIS接口:提供企業(yè)MIS接口,可以和企業(yè)現有系統(tǒng)(如ERP、CRM、OA、財務軟件等)進行無縫集成。</p><p> 第2章 短信編碼方式</p><p><b> 2.1 SMS規(guī)范<
15、/b></p><p> 首先,我們要對由ETSI(European Telecommunications Standards Institute)制訂的SMS規(guī)范有所了解。與我們討論的短消息收發(fā)有關的規(guī)范主要包括GSM 03.38、GSM 03.40和GSM 07.05。前二者著重描述SMS的技術實現(含編碼方式),后者則規(guī)定了SMS的DTE-DCE接口標準(AT命令集)。 一共有三種方式來發(fā)送
16、和接收SMS信息:Block Mode, Text Mode和PDU Mode。Block Mode已是昔日黃花,目前很少用了。Text Mode是純文本方式,可使用不同的字符集,從技術上說也可用于發(fā)送中文短消息,但國內手機基本上不支持,主要用于歐美地區(qū)。PDU Mode被所有手機支持,可以使用任何字符集,這也是手機默認的編碼方式。Text Mode比較簡單,而且不適合做自定義數據傳輸,我們就不討論了。下面介紹的內容,是在PDU Mod
17、e下發(fā)送和接收短消息的實現方法。 PDU串表面上是一串ASCII碼,由‘0’-‘9’、 ‘A’-‘F’這些數字和字母組成。它們是8位字節(jié)的十六進制數,或者BCD碼十進制數</p><p> 例1 發(fā)送:SMSC號碼是+8613800250500,對方號碼是13851872468,消息內容是“Hello!”。從手機發(fā)出的PDU串可以是08 91 68 31 08 20 05 05 F0 11 00 0D
18、 91 68 31 58 81 27 64 F8 00 00 00 06 C8 32 9B FD 0E 01對照規(guī)范,具體分析如表2-1:</p><p> 表2-1 短信編碼方式一</p><p> 例2 接收:SMSC號碼是+8613800250500,對方號碼是13851872468,消息內容是“你好!”。手機接收到的PDU串可以是08 91 68 31 08 20 05 0
19、5 F0 84 0D 91 68 31 58 81 27 64 F8 00 08 30 30 21 80 63 54 80 06 4F 60 59 7D 00 21對照規(guī)范,具體分析如表2-2:</p><p> 表2-2 短信編碼方式二</p><p> 若基本參數的最高位(TP-RP)為0,則沒有回復地址的三個段。從Internet上發(fā)出的短消息常常是這種情形。其中號碼
20、和時間的表示方法,不是按正常順序順著來的,而且要以‘F’將奇數補成偶數。</p><p> 2.2 短信內容的編解碼方式</p><p> 在PDU Mode中,可以采用三種編碼方式來對發(fā)送的內容進行編碼,它們是7-bit、8-bit和UCS2編碼。7-bit編碼用于發(fā)送普通的ASCII字符,它將一串7-bit的字符(最高位為0)編碼成8-bit的數據,每8個字符可“壓縮”成7個;8-
21、bit編碼通常用于發(fā)送數據消息,比如圖片和鈴聲等;而UCS2編碼用于發(fā)送Unicode字符。PDU串的用戶信息(TP-UD)段最大容量是140字節(jié),所以在這三種編碼方式下,可以發(fā)送的短消息的最大字符數分別是160、140和70。這里,將一個英文字母、一個漢字和一個數據字節(jié)都視為一個字符。</p><p> 需要注意的是,PDU串的用戶信息長度(TP-UDL),在各種編碼方式下意義有所不同。7-bit編碼時,指原
22、始短消息的字符個數,而不是編碼后的字節(jié)數。8-bit編碼時,就是字節(jié)數。UCS2編碼時,也是字節(jié)數,等于原始短消息的字符數的兩倍。如果用戶信息(TP-UD)中存在一個頭(基本參數的TP-UDHI為1),在所有編碼方式下,用戶信息長度(TP-UDL)都等于頭長度與編碼后字節(jié)數之和。如果采用GSM 03.42所建議的壓縮算法(TP-DCS的高3位為001),則該長度也是壓縮編碼后字節(jié)數或頭長度與壓縮編碼后字節(jié)數之和。</p>
23、<p> 下面以一個具體的例子說明7-bit編碼的過程。我們對英文短信“Hello!”進行編碼:</p><p> 圖2-1 7-bit編碼示意圖</p><p> 將源串每8個字符分為一組(這個例子中不滿8個)進行編碼,在組內字符間壓縮,但每組之間是沒有什么聯系的。</p><p> 2.3 短信內容的編解碼實現</p><p
24、> 2.3.1 用C實現7-bit編碼和解碼的算法如下:</p><p> // 7-bit編碼</p><p> // pSrc: 源字符串指針</p><p> // pDst: 目標編碼串指針</p><p> // nSrcLength: 源字符串長度</p><p> // 返回: 目標編碼
25、串長度</p><p> int gsmEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength)</p><p><b> {</b></p><p> int nSrc; // 源字符串的計數值</p><p> int n
26、Dst; // 目標編碼串的計數值</p><p> int nChar; // 當前正在處理的組內字符字節(jié)的序號,范圍是0-7</p><p> unsigned char nLeft; // 上一字節(jié)殘余的數據</p><p><b> // 計數值初始化</b></p><p>
27、;<b> nSrc = 0;</b></p><p><b> nDst = 0;</b></p><p> // 將源串每8個字節(jié)分為一組,壓縮成7個字節(jié)</p><p> // 循環(huán)該處理過程,直至源串被處理完</p><p> // 如果分組不到8字節(jié),也能正確處理</p&g
28、t;<p> while(nSrc<nSrcLength)</p><p><b> {</b></p><p> // 取源字符串的計數值的最低3位</p><p> nChar = nSrc & 7;</p><p> // 處理源串的每個字節(jié)</p><p&
29、gt; if(nChar == 0)</p><p><b> {</b></p><p> // 組內第一個字節(jié),只是保存起來,待處理下一個字節(jié)時使用</p><p> nLeft = *pSrc;</p><p><b> }</b></p><p><b
30、> else</b></p><p><b> {</b></p><p> // 組內其它字節(jié),將其右邊部分與殘余數據相加,得到一個目標編碼字節(jié)</p><p> *pDst = (*pSrc << (8-nChar)) | nLeft;</p><p> // 將該字節(jié)剩下的左
31、邊部分,作為殘余數據保存起來</p><p> nLeft = *pSrc >> nChar;</p><p> // 修改目標串的指針和計數值 pDst++;</p><p><b> nDst++; </b></p><p><b> } </b></p>&l
32、t;p> // 修改源串的指針和計數值</p><p> pSrc++; nSrc++;</p><p><b> }</b></p><p> // 返回目標串長度</p><p> return nDst; </p><p><b> }</b><
33、/p><p> // 7-bit解碼</p><p> // pSrc: 源編碼串指針</p><p> // pDst: 目標字符串指針</p><p> // nSrcLength: 源編碼串長度</p><p> // 返回: 目標字符串長度</p><p> int gsmDec
34、ode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength)</p><p><b> {</b></p><p> int nSrc; // 源字符串的計數值</p><p> int nDst; // 目標解碼串的計數值</p>
35、<p> int nByte; // 當前正在處理的組內字節(jié)的序號,范圍是0-6</p><p> unsigned char nLeft; // 上一字節(jié)殘余的數據</p><p><b> // 計數值初始化</b></p><p><b> nSrc = 0;</b></p&
36、gt;<p><b> nDst = 0;</b></p><p> // 組內字節(jié)序號和殘余數據初始化</p><p> nByte = 0;</p><p> nLeft = 0;</p><p> // 將源數據每7個字節(jié)分為一組,解壓縮成8個字節(jié)</p><p>
37、 // 循環(huán)該處理過程,直至源數據被處理完</p><p> // 如果分組不到7字節(jié),也能正確處理</p><p> while(nSrc<nSrcLength)</p><p><b> {</b></p><p> // 將源字節(jié)右邊部分與殘余數據相加,去掉最高位,得到一個目標解碼字節(jié)</p&g
38、t;<p> *pDst = ((*pSrc << nByte) | nLeft) & 0x7f;</p><p> // 將該字節(jié)剩下的左邊部分,作為殘余數據保存起來</p><p> nLeft = *pSrc >> (7-nByte);</p><p> // 修改目標串的指針和計數值</p>
39、<p><b> pDst++;</b></p><p><b> nDst++;</b></p><p> // 修改字節(jié)計數值</p><p><b> nByte++;</b></p><p> // 到了一組的最后一個字節(jié)</p>&
40、lt;p> if(nByte == 7)</p><p><b> {</b></p><p> // 額外得到一個目標解碼字節(jié)</p><p> *pDst = nLeft;</p><p> // 修改目標串的指針和計數值</p><p><b> pDst++;&
41、lt;/b></p><p><b> nDst++;</b></p><p> // 組內字節(jié)序號和殘余數據初始化</p><p> nByte = 0;</p><p> nLeft = 0;</p><p><b> }</b></p>&
42、lt;p> // 修改源串的指針和計數值</p><p><b> pSrc++;</b></p><p><b> nSrc++;</b></p><p><b> }</b></p><p> *pDst = 0;</p><p>
43、 // 返回目標串長度</p><p> return nDst;</p><p><b> }</b></p><p> 需要指出的是,7-bit的字符集與ANSI標準字符集不完全一致,在0x20以下也排布了一些可打印字符,但英文字母、阿拉伯數字和常用符號的位置兩者是一樣的。用上面介紹的算法收發(fā)純英文短消息,一般情況應該是夠用了。如果是
44、法語、德語、西班牙語等,含有 “å”、 “é”這一類字符,則要按上面編碼的輸出去查表,請參閱GSM 03.38的規(guī)定。</p><p> 8-bit編碼其實沒有規(guī)定什么具體的算法,不需要介紹。</p><p> 2.3.2 UCS2編解碼代碼實現</p><p> UCS2編碼是將每個字符(1-2個字節(jié))按照ISO/IEC10646的規(guī)定,
45、轉變?yōu)?6位的Unicode寬字符。在Windows系統(tǒng)中,特別是在2000/XP中,可以簡單地調用API 函數實現編碼和解碼。如果沒有系統(tǒng)的支持,比如用單片機控制手機模塊收發(fā)短消息,只好用查表法解決了。</p><p> Windows環(huán)境下,用C實現UCS2編碼和解碼的算法如下:</p><p><b> // UCS2編碼</b></p>&l
46、t;p> // pSrc: 源字符串指針</p><p> // pDst: 目標編碼串指針</p><p> // nSrcLength: 源字符串長度</p><p> // 返回: 目標編碼串長度</p><p> int gsmEncodeUcs2(const char* pSrc, unsigned char* pD
47、st, int nSrcLength)</p><p><b> {</b></p><p> int nDstLength; // UNICODE寬字符數目</p><p> WCHAR wchar[128]; // UNICODE串緩沖區(qū)</p><p> // 字符串-->UN
48、ICODE串</p><p> nDstLength = ::MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLength, wchar, 128);</p><p> // 高低字節(jié)對調,輸出</p><p> for(int i=0; i<nDstLength; i++)</p><p>&l
49、t;b> {</b></p><p> // 先輸出高位字節(jié)</p><p> *pDst++ = wchar[i] >> 8;</p><p> // 后輸出低位字節(jié)</p><p> *pDst++ = wchar[i] & 0xff;</p><p><b&g
50、t; }</b></p><p> // 返回目標編碼串長度</p><p> return nDstLength * 2;</p><p><b> }</b></p><p><b> // UCS2解碼</b></p><p> // pSrc:
51、 源編碼串指針</p><p> // pDst: 目標字符串指針</p><p> // nSrcLength: 源編碼串長度</p><p> // 返回: 目標字符串長度</p><p> int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLengt
52、h)</p><p><b> {</b></p><p> int nDstLength; // UNICODE寬字符數目</p><p> WCHAR wchar[128]; // UNICODE串緩沖區(qū)</p><p> // 高低字節(jié)對調,拼成UNICODE</p>
53、<p> for(int i=0; i<nSrcLength/2; i++)</p><p><b> {</b></p><p><b> // 先高位字節(jié)</b></p><p> wchar[i] = *pSrc++ << 8;</p><p><b&
54、gt; // 后低位字節(jié)</b></p><p> wchar[i] |= *pSrc++;</p><p><b> }</b></p><p> // UNICODE串-->字符串</p><p> nDstLength = ::WideCharToMultiByte(CP_ACP, 0,
55、 wchar, nSrcLength/2, pDst, 160, NULL, NULL);</p><p> // 輸出字符串加個結束符 </p><p> pDst[nDstLength] = '\0'; </p><p> // 返回目標字符串長度</p><p> return nDstLength;
56、</p><p><b> }</b></p><p> 2.3.3 打印字符串和字節(jié)數據之間相互轉換</p><p> 用以上編碼和解碼模塊,還不能將短消息字符串編碼為PDU串需要的格式,也不能直接將PDU串中的用戶信息解碼為短消息字符串,因為還差一個在可打印字符串和字節(jié)數據之間相互轉換的環(huán)節(jié)。可以循環(huán)調用sscanf和sprintf函
57、數實現這種變換。下面提供不用這些函數的算法,它們也適用于單片機、DSP編程環(huán)境。</p><p> // 可打印字符串轉換為字節(jié)數據</p><p> // 如:"C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}</p><p> // pSrc: 源字符串指針</p&
58、gt;<p> // pDst: 目標數據指針</p><p> // nSrcLength: 源字符串長度</p><p> // 返回: 目標數據長度</p><p> int gsmString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength)</p>
59、<p><b> {</b></p><p> for(int i=0; i<nSrcLength; i+=2)</p><p><b> {</b></p><p><b> // 輸出高4位</b></p><p> if(*pSrc>=
60、39;0' && *pSrc<='9')</p><p><b> {</b></p><p> *pDst = (*pSrc - '0') << 4;</p><p><b> }</b></p><p><b&
61、gt; else</b></p><p><b> {</b></p><p> *pDst = (*pSrc - 'A' + 10) << 4;</p><p><b> }</b></p><p><b> pSrc++;</b&
62、gt;</p><p><b> // 輸出低4位</b></p><p> if(*pSrc>='0' && *pSrc<='9')</p><p><b> {</b></p><p> *pDst |= *pSrc -
63、9;0';</p><p><b> }</b></p><p><b> else</b></p><p><b> {</b></p><p> *pDst |= *pSrc - 'A' + 10;</p><p>&
64、lt;b> }</b></p><p><b> pSrc++;</b></p><p><b> pDst++;</b></p><p><b> }</b></p><p> // 返回目標數據長度</p><p> r
65、eturnnSrcLength / 2;</p><p><b> }</b></p><p> // 字節(jié)數據轉換為可打印字符串</p><p> // 如:{0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01" </p><p>
66、 // pSrc: 源數據指針</p><p> // pDst: 目標字符串指針</p><p> // nSrcLength: 源數據長度</p><p> // 返回: 目標字符串長度</p><p> int gsmBytes2String(const unsigned char* pSrc, char* pDst, int
67、 nSrcLength)</p><p><b> {</b></p><p> const char tab[]="0123456789ABCDEF"; // 0x0-0xf的字符查找表</p><p> for(int i=0; i<nSrcLength; i++)</p><p&g
68、t;<b> {</b></p><p><b> // 輸出低4位</b></p><p> *pDst++ = tab[*pSrc >> 4];</p><p><b> // 輸出高4位</b></p><p> *pDst++ = tab[*pSr
69、c & 0x0f];</p><p><b> pSrc++;</b></p><p><b> }</b></p><p> // 輸出字符串加個結束符</p><p> *pDst = '\0';</p><p> // 返回目標字符串長
70、度</p><p> return nSrcLength * 2;</p><p><b> }</b></p><p> 2.3.4 PDU全串的編碼和解碼</p><p> 在上節(jié)中,我們已經討論了7-bit, 8bit和UCS2這幾種PDU用戶信息的編碼方式,并且給出了實現代碼。現在,重點描述PDU全串的編
71、碼和解碼過程,以及GSM 07.05的AT命令實現方法。這些是底層的核心代碼,為了保證代碼的可移植性,我們盡可能不用MFC的類,必要時用ANSI C標準庫函數。首先,定義如下常量和結構:</p><p> // 用戶信息編碼方式</p><p> #define GSM_7BIT 0</p><p> #define GSM_8BIT
72、 4</p><p> #define GSM_UCS2 8</p><p> // 短消息參數結構,編碼/解碼共用</p><p> // 其中,字符串以0結尾</p><p> typedef struct {</p><p> char SCA[16]; // 短消息服務中
73、心號碼(SMSC地址)</p><p> char TPA[16]; // 目標號碼或回復號碼(TP-DA或TP-RA)</p><p> char TP_PID; // 用戶信息協(xié)議標識(TP-PID)</p><p> char TP_DCS; // 用戶信息編碼方式(TP-DCS)</p><p
74、> char TP_SCTS[16]; // 服務時間戳字符串(TP_SCTS), 接收時用到</p><p> char TP_UD[161]; // 原始用戶信息(編碼前或解碼后的TP-UD)</p><p> char index; // 短消息序號,在讀取時用到</p><p> } SM_PARAM;</p&g
75、t;<p> 以下是PDU全串的編解碼模塊。為簡化編程,有些字段用了固定值。</p><p> // PDU編碼,用于編制、發(fā)送短消息</p><p> // pSrc: 源PDU參數指針</p><p> // pDst: 目標PDU串指針</p><p> // 返回: 目標PDU串長度</p>&l
76、t;p> int gsmEncodePdu(const SM_PARAM* pSrc, char* pDst)</p><p><b> {</b></p><p> int nLength; // 內部用的串長度</p><p> int nDstLength; // 目標PDU串長度&
77、lt;/p><p> unsigned char buf[256]; // 內部用的緩沖區(qū)</p><p> // SMSC地址信息段</p><p> nLength = strlen(pSrc->SCA); // SMSC地址字符串的長度 </p><p> buf[0] = (char)((nLength &am
78、p; 1) == 0 ? nLength : nLength + 1) / 2 + 1; // SMSC地址信息長度</p><p> buf[1] = 0x91; // 固定: 用國際格式號碼</p><p> nDstLength = gsmBytes2String(buf, pDst, 2); // 轉換2個字節(jié)到目標PDU串</p>
79、<p> nDstLength += gsmInvertNumbers(pSrc->SCA, &pDst[nDstLength], nLength); // 轉換SMSC到目標PDU串</p><p> // TPDU段基本參數、目標地址等</p><p> nLength = strlen(pSrc->TPA); // TP-DA地址字
80、符串的長度</p><p> buf[0] = 0x11; // 是發(fā)送短信(TP-MTI=01),TP-VP用相對格式(TP-VPF=10)</p><p> buf[1] = 0; // TP-MR=0</p><p> buf[2] = (char)nLength; // 目標地址數字個數(TP-DA
81、地址字符串真實長度)</p><p> buf[3] = 0x91; // 固定: 用國際格式號碼</p><p> nDstLength += gsmBytes2String(buf, &pDst[nDstLength], 4); // 轉換4個字節(jié)到目標PDU串</p><p> nDstLength += gsmInver
82、tNumbers(pSrc->TPA, &pDst[nDstLength], nLength); // 轉換TP-DA到目標PDU串</p><p> // TPDU段協(xié)議標識、編碼方式、用戶信息等</p><p> nLength = strlen(pSrc->TP_UD); // 用戶信息字符串的長度</p><p> buf[0
83、] = pSrc->TP_PID; // 協(xié)議標識(TP-PID)</p><p> buf[1] = pSrc->TP_DCS; // 用戶信息編碼方式(TP-DCS)</p><p> buf[2] = 0; // 有效期(TP-VP)為5分鐘</p><p> if(pSrc->TP_D
84、CS == GSM_7BIT) </p><p><b> {</b></p><p> // 7-bit編碼方式</p><p> buf[3] = nLength; // 編碼前長度</p><p> nLength = gsmEncode7bit(pSrc->TP_UD,
85、&buf[4], nLength+1) + 4; // 轉換TP-DA到目標PDU串</p><p><b> }</b></p><p> else if(pSrc->TP_DCS == GSM_UCS2)</p><p><b> {</b></p><p> //
86、UCS2編碼方式</p><p> buf[3] = gsmEncodeUcs2(pSrc->TP_UD, &buf[4], nLength); // 轉換TP-DA到目標PDU串</p><p> nLength = buf[3] + 4; // nLength等于該段數據長度</p><p><b> }<
87、/b></p><p><b> else</b></p><p><b> {</b></p><p> // 8-bit編碼方式</p><p> buf[3] = gsmEncode8bit(pSrc->TP_UD, &buf[4], nLength); //
88、 轉換TP-DA到目標PDU串</p><p> nLength = buf[3] + 4; // nLength等于該段數據長度</p><p><b> }</b></p><p> nDstLength += gsmBytes2String(buf, &pDst[nDstLength], nLength);
89、 // 轉換該段數據到目標PDU串</p><p> // 返回目標字符串長度</p><p> return nDstLength;</p><p><b> }</b></p><p> // PDU解碼,用于接收、閱讀短消息</p><p> // pSrc: 源PDU串
90、指針</p><p> // pDst: 目標PDU參數指針</p><p> // 返回: 用戶信息串長度</p><p> int gsmDecodePdu(const char* pSrc, SM_PARAM* pDst)</p><p><b> {</b></p><p> i
91、nt nDstLength; // 目標PDU串長度</p><p> unsigned char tmp; // 內部用的臨時字節(jié)變量</p><p> unsigned char buf[256]; // 內部用的緩沖區(qū)</p><p> // SMSC地址信息段</p><p> gsmStrin
92、g2Bytes(pSrc, &tmp, 2); // 取長度</p><p> tmp = (tmp - 1) * 2; // SMSC號碼串長度</p><p> pSrc += 4; // 指針后移</p><p> gsmSerializeNumbers(pSrc, pDst->SCA, tmp);
93、 // 轉換SMSC號碼到目標PDU串</p><p> pSrc += tmp; // 指針后移</p><p> // TPDU段基本參數、回復地址等</p><p> gsmString2Bytes(pSrc, &tmp, 2); // 取基本參數</p><p> pSrc += 2;
94、 // 指針后移</p><p> if(tmp & 0x80)</p><p><b> {</b></p><p> // 包含回復地址,取回復地址信息</p><p> gsmString2Bytes(pSrc, &tmp, 2); // 取長度</p><p&g
95、t; if(tmp & 1) tmp += 1; // 調整奇偶性</p><p> pSrc += 4; // 指針后移</p><p> gsmSerializeNumbers(pSrc, pDst->TPA, tmp); // 取TP-RA號碼</p><p> pSrc += tmp; //
96、指針后移</p><p><b> }</b></p><p> // TPDU段協(xié)議標識、編碼方式、用戶信息等</p><p> gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_PID, 2); // 取協(xié)議標識(TP-PID)</p><p>
97、 pSrc += 2; // 指針后移</p><p> gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_DCS, 2); // 取編碼方式(TP-DCS)</p><p> pSrc += 2; // 指針后移</p><p> gsmSerializeNumb
98、ers(pSrc, pDst->TP_SCTS, 14); // 服務時間戳字符串(TP_SCTS) </p><p> pSrc += 14; // 指針后移</p><p> gsmString2Bytes(pSrc, &tmp, 2); // 用戶信息長度(TP-UDL)</p><p> pSrc += 2
99、; // 指針后移</p><p> if(pDst->TP_DCS == GSM_7BIT) </p><p><b> {</b></p><p> // 7-bit解碼</p><p> nDstLength = gsmString2Bytes(pSrc, buf, tmp &am
100、p; 7 ? (int)tmp * 7 / 4 + 2 : (int)tmp * 7 / 4); // 格式轉換</p><p> gsmDecode7bit(buf, pDst->TP_UD, nDstLength); // 轉換到TP-DU</p><p> nDstLength = tmp;</p><p><b> }</
101、b></p><p> else if(pDst->TP_DCS == GSM_UCS2)</p><p><b> {</b></p><p><b> // UCS2解碼</b></p><p> nDstLength = gsmString2Bytes(pSrc, buf,
102、 tmp * 2); // 格式轉換</p><p> nDstLength = gsmDecodeUcs2(buf, pDst->TP_UD, nDstLength); // 轉換到TP-DU</p><p><b> }</b></p><p><b> else</b></p&g
103、t;<p><b> {</b></p><p> // 8-bit解碼</p><p> nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2); // 格式轉換</p><p> nDstLength = gsmDecode8bit(buf, pDst->T
104、P_UD, nDstLength); // 轉換到TP-DU</p><p><b> }</b></p><p> // 返回目標字符串長度</p><p> return nDstLength;</p><p><b> }</b></p><p><
105、b> 第3章 AT指令</b></p><p><b> 3.1 AT指令</b></p><p> 3.1.1 TC35模塊的AT指令列表</p><p> 涉及TC35模塊的AT指令很多,但與SMS有關的GSM AT指令如下(from GSM07.05):</p><p> 表3-1相關的
106、GSM AT指令</p><p> 3.1.2 TC35模塊的AT指令分類</p><p> 初始化指令 設置短消息發(fā)送格式AT+CMGF=1<CR>,設置1代表PDU模式,<CR>是回車符號,也就是0x0d,指令正確則模塊返回<CRLF>OK<CRLF>,<CRLF>是回車換行符號。</p><p&g
107、t; 設置/讀取短消息中心 短消息中心號碼由移動運營商提供?! ≡O置短消息中心的指令格式為: AT+CSCA=″+8613800531500″(短消息中心)<CR> 設置正確則模塊返回<CRLF>OK<CRLF>?! ∽x取短消息服務中心則使用命令: AT+CSCA=?<CR> TC35模塊應該返回: <CRLF>+CSCA:″8613800
108、531500″<CRLF>。</p><p> 設置短消息到達自動提示 設置短消息到達自動提示的指令格式為: AT+CNMI=1,1,0,0,1<CR> 設置正確則TC35模塊返回: <CRLF>OK<CRLF>。 設置此命令可使模塊在短消息到達后向串口發(fā)送指令: <CRLF>+CMTI:″SM″,INDEX(信息存
109、儲位置)<CRLF>。</p><p> 3.1.3 通過TC35發(fā)送短消息的方法</p><p> PC上的控制軟件按照PDU的格式發(fā)送和接收數據,短消息的內容可以是中文或者其他字符。在PDU模式,如果發(fā)送短消息,則首先發(fā)送短消息數據的長度: AT+CMGS=<length><CR> 等待TC35模塊返回ASCII字符">
110、;",則可以將PDU數據輸入,PDU數據以<Z>(也就是0x1a)作為結束符。短消息發(fā)送成功,模塊返回: <CRLF>OK<CRLF></p><p><b> 例如:</b></p><p> 我現在以實例來說明這些指令的使用方法:</p><p> 先用RS232數據線將GSM
111、MODEM連接到電腦串口,并將串口的波特率設置為57600,可以開始了。</p><p> 首先測試你的連接及GSM MODEM是否支持AT指令,請在你的串口調試程序中輸入: AT<回車> 屏幕上返回"OK"表明計算機與GSM MODEM連接正常,那樣我們就可以進行其它的AT指令測試了</p><p> 設置短信發(fā)送格式 AT+CMGF=1<回車>
112、屏幕上返回"OK"表明現在短信的發(fā)送方式為PDU方式,如果是設置為TEXT方式,則,AT+CMGF=0<回車></p><p> 發(fā)送短信 發(fā)送內容及手要號仍舊同上面在編碼中的一樣,編碼后,得到要發(fā)送的數據如下:0891683108705505F011000D91683117352446F2000800124F60597D002C00480065006C006C006F0021 我們
113、用如下指令來發(fā)送 AT+CMGS=33<回車> 如果返回">",就把上面編碼數據輸入,并以CTRL+Z結尾,稍等一下,你就可以看到返回OK啦。 說明一下,為什么AT+CMGS=33呢,是這樣得來的: 11000D91683117352446F2000800124F60597D002C00480065006C006C006F0021</p><p> 3.1.4通過TC35
114、接收短消息的方法</p><p> 短消息到來后,串口上會接收到指令<CRLF>+CMTI:″SM″,INDEX(信息存儲位置)<CRLF>PC上的控制軟件通過讀取PDU數據的AT命令AT+CMGR=INDEX<CRLF></p><p> 將TC35模塊中PDU格式的短消息內容讀出。如果用+CMGL代替+CMGR,則可一次性讀出全部短消息。&
115、lt;/p><p> 3.1.5通過TC35刪除短消息的方法</p><p> PC上的控制軟件收到一條短消息并處理后,需要將其在SIM卡上刪除,以防止SIM卡飽和。刪除短消息的指令為:AT+CMGD=INDEX<CR> 刪除后模塊返回<CRLF>OK<CRLF></p><p><b> 3.2程序實例<
116、;/b></p><p> 3.2.1 程序介面及其代碼實現</p><p> 由于本章的宗旨在于講解串口通信,因此,我們屏蔽圖形用戶界面的細節(jié),制作一個簡單的短信收發(fā)軟件,它包含了控制短信終端的所有串口通信內容。實際上,一個理想的短信收發(fā)軟件的界面應類似于Outlook或Foxmail,包含收件箱、發(fā)件箱、已發(fā)送短信箱等內容,但是這些東西都與我們要介紹的串口通信無關,因此,下面
117、的軟件界面雖"敗絮其外",但仍可稱得上"金玉其中":</p><p> 圖3-1 短信發(fā)送與接收主介面</p><p> 1.關于界面上控件的描述如下:</p><p> BEGIN EDITTEXT IDC_SMSCONTENT_EDIT,39,61,242,38,ES_AUTOHSCROLL PUSHBUTTON
118、 "發(fā)送",IDC_SEND_BUTTON,316,80,45,18 GROUPBOX "接收短消息",IDC_STATIC,28,124,361,167 LTEXT "對方手機號",IDC_STATIC,41,35,42,11 EDITTEXT IDC_PHONENUM_EDIT,88,30,192,17,ES_AUTOHSCROLL PUSHBUTTON "
119、;清除",IDC_CLEAR_BUTTON,316,30,45,18 GROUPBOX "發(fā)送短消息",IDC_STATIC,29,19,361,95 LISTBOX IDC_RECVSMS_LIST,43,137,331,127,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "接收",
120、IDC_RECV_BUTTON,77,269,55,16 PUSHBUTTON "清空"</p><p> 2.對話框類的消息映射為:</p><p> BEGIN_MESSAGE_MAP(CSMSControlDlg, CDialog)//{{AFX_MSG_MAP(CSMSControlDlg) ON_WM_SYSCOMMAND() ON_WM_PAIN
121、T() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClearButton) ON_BN_CLICKED(IDC_SEND_BUTTON, OnSendButton) ON_BN_CLICKED(IDC_RECV_BUTTON, OnRecvButton) ON_BN_CLICKED(IDC_DELETEALL_BUTTON, OnDeleteallButto
122、n)//}}AFX_MSG_MAPEND_MESSAGE_MAP()</p><p> 3.下面是對本例程軟件的主要數據結構和核心函數的介紹: 數據結構</p><p> // 用戶信息編碼方式#define GSM_7BIT 0#define GSM_8BIT 4#define GSM_UCS2 8 // 短消息參數結構,編碼/解碼共用// 其中,字符串以0結尾t
123、ypedef struct{ char SCA[16]; // 短消息服務中心號碼(SMSC地址) char TPA[16]; // 目標號碼或回復號碼(TP-DA或TP-RA) char TP_PID; // 用戶信息協(xié)議標識(TP-PID) char TP_DCS; // 用戶信息編碼方式(TP-DCS) char TP_SCTS[16]; // 服務時間戳字符串(TP_SCTS), 接收時用到 char TP_UD[
124、161]; // 原始用戶信息(編碼前或解碼后的TP-UD) char index; // 短消息序號,在讀取時用到} SM_PARAM;</p><p> 3.2.2 短信的發(fā)送、接收及刪除代碼實現</p><p><b> 1.發(fā)送短消息</b></p><p> 發(fā)送按鈕對應的函數為CSMSControlDlg::OnSendB
125、utton,它讀取用戶輸出并根據目標電話號碼和短信息內容形成SM_PARAM(源PDU參數)的內容,接著進行發(fā)送:</p><p> void CSMSControlDlg::OnSendButton() { // TODO: Add your control notification handler code here //獲得用戶輸入 CString desPhoneNum; CString sm
126、sContent; GetDlgItemText(IDC_PHONENUM_EDIT,desPhoneNum); GetDlgItemText(IDC_SMSCONTENT_EDIT,smsContent); //填充SM_PARAM結構體內容 SM_PARAM smParam; smParam = CreateSMPARAMStruct(desPhoneNum,smsContent); //發(fā)送短信息 gsmSend
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 基于單片機的短信收發(fā)系統(tǒng)設計-畢業(yè)設計
- 基于單片機的短信收發(fā)系統(tǒng)設計畢業(yè)設計
- 畢業(yè)設計---基于vb實現短信息收發(fā)功能的信息系統(tǒng)
- 郵件收發(fā)系統(tǒng)畢業(yè)設計
- 基于單片機的短信收發(fā)系統(tǒng)設計
- 基于嵌入式linux的短信收發(fā)系統(tǒng)設計
- 在線郵件收發(fā)系統(tǒng)畢業(yè)設計
- 基于網絡的短信收發(fā)系統(tǒng)的設計與實現.pdf
- 基于特征內容的短信消息過濾系統(tǒng)設計【畢業(yè)設計】
- 畢業(yè)設計---基于android的短信備份
- 基于Web的短信收發(fā)管理系統(tǒng)的設計與實現.pdf
- 基于gsm07.05的短信收發(fā)系統(tǒng)的實現
- 基于java_mail的電子郵件收發(fā)系統(tǒng)畢業(yè)設計
- cdma數字基帶收發(fā)系統(tǒng)的仿真-畢業(yè)設計
- 基于java的電子郵件收發(fā)系統(tǒng)的設計與實現【畢業(yè)設計】
- 基于局域網的信息收發(fā)系統(tǒng)的設計與實現畢業(yè)設計
- 基于cdma短信息的無線通信系統(tǒng)的設計 【畢業(yè)設計】
- gsm短消息收發(fā)系統(tǒng)的設計與實現畢業(yè)設計
- 基于Web服務的工業(yè)車間短信收發(fā)系統(tǒng)的開發(fā).pdf
- 基于SMS的企業(yè)短信收發(fā)系統(tǒng)的研究與實現.pdf
評論
0/150
提交評論