就"通過串口收發短消息"專題,本人將同網友交流、探討的部分技術問題整理成如下文字。希望這篇文章能對更多對SMS感興趣的朋友有所幫助。由於本人是業余愛好,時間和金錢都有限,沒有力量將很多型號的手機和模塊一一試驗,可能存在這樣那樣的差錯,希望行內高人批評指正。
我寫了個短信發送程序,使用PDU格式發送,程序在廣州使用一點問題也沒有,在河南卻怎麼也發不出去。不知道為什麼,短信"你好嗎"格式如下:
河南: 0891683108200005F011000D91683170031618F20008A9064F60597D5417
廣州: 0891683108301705F011000D91683170031618F20008A9064F60597D5417
發送短信時要用SIM卡屬地的SMSC號碼。如果是在廣州辦的卡,即使在外地還是要用廣州的SMSC號碼。你的兩個短信內SMSC號碼不同,但用的是同一張SIM卡,不知是否是此原因。
短信中心的號碼可否直接使用SIM卡中的號碼,而不要用戶輸入?我用過的短信軟件好像都是不用輸SMSC號碼的。
有一條"AT+CSCA"指令,可用於設置或查詢服務中心號碼。若手機中已存在此號碼,有兩種解決辦法:
用"AT+CSCA?"指令查詢出來,然後自動將此號碼寫到PDU的SCA中。
PDU的SCA字段只寫一個"00":"08 91 68 31 ..." -> "00"
可用"AT+CSCA=xxxxxxxx"指令設置服務中心號碼。
我在超級終端上,用at+cmgs發送短消息,格式好像沒有錯誤,但總返回"ERROR"。我輸入的就象這樣:
at+cmgs=30
> 0891683108100005F011000D91683118405057F000000006C8329BFD0E01
請問是什麼原因?
"at+cmgs"指令很特殊,回車後還需要輸入數據。此處是"CR",不是"CRLF",注意在超級終端裡直接回車是不是生成了兩個字符(查看設置)。象"at+cmgl"指令,即使最後輸入"CRLF"也是不要緊的。
你的問題出在長度上。長度不是隨便寫的,你的例子中,長度應為21。除去SMSC段(0891683108100005F0),從"11"開始算(即"11000D91683118405057F000000006C8329BFD0E01"),除以2即得。
正確的寫法應該是
at+cmgs=21
> 0891683108100005F011000D91683118405057F000000006C8329BFD0E01
(">"是手機提示,不是輸入的)
我最近在編一個關於短消息的程序,在你的"通過串口收發短消息"中提到"Text Mode是純文本方式,可使用不同的字符集,從技術上說也可用於發送中文短消息,但國內手機基本上不支持,主要用於歐美地區。"是不是說我用AT指令"AT+CMGF=1"或"AT+CMGF=0"對我後來的收發短消息沒什麼影響啊?
Text mode寫起來簡單,直接發原文就行,發送非ASCII碼內容也能發,但需要手機支持才能正確顯示。如法語、德語的很多字符,編碼大於0x80,他們都是用text mode。Text mode靠什麼區分字符編碼方式呢?有專門的字符集設定指令"AT+CSCS"。可以設定為擴充字符集"UCS2"。Siemens TC35/TC37資料上說,它的"AT+CSCS"支持"UCS2"字符集,但我目前沒有機會去親自試驗。正在使用TC35/TC37模塊的朋友不妨試一下。
據我了解,中文短消息方面,在國內賣的各種手機只支持PDU mode,這成了事實上的標准。其實PDU mode真的挺好用,估計以後text mode會萎縮。我們寫的程序,我建議只采用PDU mode,即使是發純英文信息也這樣,編碼倒是可以靈活采取7bit或UCS2,因為7bit能發的長度是UCS2的2倍(僅對純英文而言)。如果發送純數據,不需要手機顯示,可用8bit。
你的smstraffic類中的發送接收大循環中,是不是把所有收到的消息都放入消息隊列後,然後執行刪除程序啊?如果我是並發量很大的話,就是網關有很多短消息等著進入手機,讀完所有短消息後,進行刪除的過程中,因為短消息的排列順序,而導致誤刪除呢(比如說我現在手機裡有1-15條短消息,然後在我刪除第一二條後,第三條自動填補為第一條,而新進來的短消息,16條排在了第三條,而被cancel掉呢?)我試過好象短消息的排列不是每次都一樣啊?(在接收的時候,同一條短消息有時是14條,有時是第15條)這個怎麼解決啊?
手機裡消息都有一個物理序號,讀出的時候帶序號,刪除也要根據序號刪。"物理"二字很關鍵。這個序號相當於ID,無論它前面有沒有刪除、刪除了多少消息,都不會變的。假如原來有1-15,刪除了1和2,又來了一條消息,手機內部的軟件有兩種處理方式:有的放在第1條,有的則放在第16條,我都見過。其實,它願意放到哪個空閒的地方都行。但無論怎樣,不會引起混亂的,因為讀出是什麼序號,就刪除什麼序號的。在執行刪除命令前,消息還是在原來那個地方,不會被後來的覆蓋。
如果說網關有很多短消息等著進入手機,量很大,這種處理方式效率不高,因為AT+CMGL占用很長時間,這段時間手機無法從SMSC接收新消息。采用我說的"實時"接收方法比較好,消息來了直接傳出來,不經過寫入手機的過程。
我用Nokia 8210串口數據線,連上電腦的com1口,用SmsTest運行提示"沒有發現MODEM",跟蹤發現gsmInit()檢測中串口發AT指令沒有回應"OK"。按您的提示我安裝了Nokia modem驅動程序,(WIN2000 server系統)虛擬出com3口的一個8210 MODEM設備,再次調用smsTest還是提示"沒有發現MODEM"。但用串口線,手機能通過LogoManager手機管理軟件進行相應的圖片LOGO,短信發送操作。
Nokia手機本身沒有帶modem功能,用專業術語講就是不具備TA(Terminal Adapter)接口,需要驅動轉換,不管是真的串口,USB還是紅外接口,反正它能虛擬出"標准MODEM"串口來。AT命令只能用標准異步通信。
在我的印象中,Nokia 8210需用紅外線接口同PC通信。估計你裝的那個驅動是IR->COM轉換的,而不是驅動串口數據線的,可能你的電腦沒有紅外接口,所以com3也連不上?
要試(虛擬)串口是否連接正確,很簡單,用windows自帶的"超級終端"在特定虛擬端口連上,敲個"AT"回車,看有沒有反應,正確回答應該是"OK"。
Nokia數據線上跑的是"Nokia語"- Nokia專有協議的數據,不是通用/擴展的AT命令集。LogoManager能聽、能說"Nokia語",所以不需要安裝驅動就能工作。Nokia有一個免費的"Nokia PC Connectivity SDK",可供開發Nokia手機使用。至於LogoManager是不是用的這個開發包,那就不得而知了。
在SmsTest中,發出AT命令,然後接收應答,比如
WriteComm("AT+CMGF=0\r", 10);
ReadComm(ans, 128);
在WriteComm函數後接著就調用ReadComm,是不是太急,這裡的ReadComm函數是讀返回的這個字符串還是其中的單個字符或不完全的字符串?請問超時控制設多少最合適啊?
關於讀串口,程序中是這樣設定超時控制的:
COMMTIMEOUTS timeouts = { // 串口超時控制參數
100, // 讀字符間隔超時