打印

GU900E模块实现收发短信,打电话

[复制链接]
1022|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ITshao9|  楼主 | 2016-5-31 11:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
实现了收发短信,并且支持字符短信和PDU格式短信,支持电话拨打与接听
长期工作稳定

//GU900E.C
1.  /*************************************************************************************************************
2.   * 文件名:         GU900E.c
3.   * 功能:          STM32 GU900E底层驱动函数
4.   * 作者:         
5.   * 创建时间:        2016-5-16
6.   * 最后修改时间:  2016-5-16
7.   * 详细:          GSM_CDMA发送短信等
8.                      2014-04-22:添加字节超时与总超时
9.  *************************************************************************************************************/  
10. #include "system.h"  
11. #include "usart.h"  
12. #include "GU900E.h"  
13. #include "delay.h"  
14. #include "string.h"  
15. #include "ucos_ii.h"  
16. #include "unicode_gbk.h"  
17. #include "main.h"  
18.   
19.   
20. //GU900E通信缓冲区  
21. u8  GU900E_Buff[GU900E_BUFF_SIZE];  //缓冲区  
22.   
23.   
24. //调试开关  
25. #define GU900E_DBUG 0  
26. #if GU900E_DBUG  
27.     #include "system.h"  
28.     #define GU900E_debug(format,...)    uart_printf(format,##__VA_ARGS__)  
29. #else  
30.     #define GU900E_debug(format,...)    /\  
31. /  
32. #endif  //GU900E_DBUG  
33.   
34. //所有短信接收缓冲区  
35. //#define PDU_BUFF_SIZE 1024*20         //20KB  可以一次读取50条未读短信  
36. u8  SmsPduBuff[PDU_BUFF_SIZE];          //PDU数据缓冲区  
37.   
38.   
39.   
40. static u8 PhoneNumtoPDUChar(u8 *pNum, char *pChar,u8 NumLen);       //将电话号码字符转换为PDU要求的字符  
41. static u8 ChartoPhoneNum(char *pChar, char *pNum, u8 CharLen);      //将字符转换为电话号码  
42. static u32 StringToUnicodeStr(char *pStr, char *pucode,u32 SrtLen); //将字符串转换为unicode,并存储为16进制样式的字符串  
43. static u32 UnicodeStrToString(u8 *pucode,char *pStr,u32 SrtLen);    //将字符unicode转换为字符串  
44. static u32 GSM_StringToHex(char *pStr, u8 NumDigits);               //将16进制样式字符串转换为16进制整型数(必须保证字符串字母都是大写)  
45. static void GSM_HexToString(u32 HexNum,char *pStr, u8 NumDigits);   //将整型数字转换为16进制样式字符串(字母为大写,不带结束符)  
46. static int gsmDecode7bit(const u8* pSrc, char* pDst, int nSrcLength);//7bit编码解码  
47. static int gsmEncode7bit(const char* pSrc,u8* pDst);  
48. static u16 GSM_GetU2SCharOffset(char *pBuff,u16 CharNum);  
49.   
50.   
51. static PHONE_NUMBER SMSServeNumber;                                 //全局短信中心号码  
52.   
53.   
54.   
55.   
56. /*************************************************************************************************************************
57. * 函数                :   void GU900E_SetSMSServeNumber(char *pSMSServeNumber,u8 NumLen)
58. * 功能                :   设置全局短信中心号码
59. * 参数                :   pSMSServeNumber:短信中心号码,NumLen:短信中心号码长度
60. * 返回                :   无
61. * 依赖                :   无
62. * 作者                :
63. * 时间                :   2016-5-17
64. * 最后修改时间    :   2016-5-17
65. * 说明                :   用于发送短信的时候进行调用
66. *************************************************************************************************************************/  
67. void GU900E_SetSMSServeNumber(char *pSMSServeNumber,u8 NumLen)  
68. {  
69.     u8 i;  
70.      
71.     if(NumLen > PHONE_NUMBER_MAX_LEN) NumLen = PHONE_NUMBER_MAX_LEN; //限制电话号码长度  
72.     for(i = 0;i < NumLen;i ++)  
73.     {  
74.         SMSServeNumber.PhoneNumBuff = pSMSServeNumber;  
75.     }  
76.     SMSServeNumber.PhoneNumLen = NumLen;  
77.     SMSServeNumber.PhoneNumBuff[SMSServeNumber.PhoneNumLen] = '\0';     //添加结束符  
78.     GU900E_debug("设置短信中心号码为:%s\r\n",SMSServeNumber.PhoneNumBuff);  
79. }  
80.   
81.   
82.   
83.   
84. /*************************************************************************************************************************
85. * 函数                :   bool GSM_CheckNotASCII(char *pBuff,u16 Len)
86. * 功能                :   检查字符串中是否含有非ASCII编码
87. * 参数                :   pBuff:字符串缓冲区;Len:长度
88. * 返回                :   FALSE:字符串全部为ASCII编码;TRUE:字符串含有非ASCII编码,一般为汉字编码
89. * 依赖                :   无
90. * 作者                :
91. * 时间                :   2016-5-17
92. * 最后修改时间    :   2016-5-17
93. * 说明                :   用于选择发送短信的模式,选择U2S或者7BIT编码

相关帖子

沙发
ITshao9|  楼主 | 2016-5-31 11:08 | 只看该作者
94.        *************************************************************************************************************************/  
95.        bool GSM_CheckNotASCII(char *pBuff,u16 Len)  
96.        {  
97.            u16 i;  
98.             
99.            for(i = 0;i < Len;i ++)  
100.            {  
101.                if(pBuff[i] >= 0x80)  
102.                    return TRUE;  
103.            }  
104.            return FALSE;  
105.        }  
106.          
107.          
108.          
109.        /*************************************************************************************************************************
110.        * 函数                :   static u16 GSM_GetU2SCharOffset(char *pBuff,u16 CharNum)
111.        * 功能                :   计算指定字符的偏移位置
112.        * 参数                :   pBuff:字符串缓冲区;
113.                                CharNum:字符偏移
114.        * 返回                :   字符串大小
115.        * 依赖                :   无
116.        * 作者                :   H F Y-GU900
117.        * 时间                :   2016-5-17
118.        * 最后修改时间    :   2016-5-17
119.        * 说明                :   计算指定数量的字符(不分中英文)的大小,比如PDU,U2S模式下,短信只能有70个字符,但是不分中英文
120.                                此时英文只占用一个字节,但是中文占用2个字节
121.        *************************************************************************************************************************/  
122.        static u16 GSM_GetU2SCharOffset(char *pBuff,u16 CharNum)  
123.        {  
124.            u16 i;  
125.            u16 cnt = 0;  
126.             
127.          
128.            for(i = 0;i < CharNum;)  
129.            {  
130.                if(pBuff[i] >= 0x80) //中文  
131.                {  
132.                    cnt +=2;  
133.                    i +=2;  
134.                }  
135.                else if(pBuff[i] == 0)  //字符串结束  
136.                {  
137.                    break;  
138.                }  
139.                else                    //ASCII  
140.                {  
141.                    cnt += 1;  
142.                    i ++;  
143.                }  
144.            }  
145.            return cnt;  
146.        }  
147.          
148.          
149.          
150.        /*************************************************************************************************************************
151.        * 函数                :   bool GU900E_WaitSleep(void)
152.        * 功能                :   等待GSM模块空闲,并重新唤醒
153.        * 参数                :   TimeOut:等待超时,时间单位ms
154.        * 返回                :   TRUE:成功;FALSE:超时
155.        * 依赖                :   无
156.        * 作者                :   H F Y-GU900
157.        * 时间                :   2016-5-17
158.        * 最后修改时间    :   2016-5-17
159.        * 说明                :   用于等待操作完成,防止快速操作造成模块不响应
160.        *************************************************************************************************************************/  
161.        bool GU900E_WaitSleep(u32 TimeOut)  
162.        {  
163.            u32 i;  
164.            u32 cnt;  
165.             
166.            TimeOut /= 100;  
167.            TimeOut +=1;  
168.             
169.            GU900E_SetDTR(1);                           //等待模块空闲后进入SLEEP模式  
170.             
171.            for(i = 0;i < TimeOut;i ++)  
172.            {  
173.                GSM_Delay100MS();                       //延时100ms  
174.                GU900E_SendATcom("AT");                 //发送"AT",同步波特率,并且等待应答  
175.                if(AT_RETURN_TIME_OUT == GU900E_GetATResp(GU900E_Buff, &cnt, "OK", 10, 15)) //等待响应,超时150ms  
176.                {  
177.                    break;  
178.                }  
179.            }  
180.            GU900E_SetDTR(0);                           //唤醒  
181.            if(i == TimeOut)   
182.            {  
183.                GU900E_debug("模块进入空闲模式失败!\r\n");  
184.                return FALSE;  
185.            }  
186.            GSM_Delay100MS();                       //延时100ms  
187.             
188.            GU900E_debug("模块进入空闲模式成功!\r\n");  
189.            GU900E_TestAT(10);  
190.            return TRUE;  
191.        }  
192.          
193.          
194.          
195.        /*************************************************************************************************************************
196.        *函数         :   bool GSM_SendSMS(char *pSMS, char *pPhoneNumber)
197.        *功能         :   发送一条短信
198.        *参数         :   pSMS:短信内容缓冲区指针,内容为文本文档,并且字符串需要结束符
199.                            pPhoneNumber:目标电话号码
200.        *返回         :   TRUE:短信发送成功;FALSE:短信发送失败
201.        *依赖         :   底层
202.        *作者         :   H F Y-GU900
203.        *时间         :   2016-5-17
204.        *最后修改时间 :   2016-5-17
205.        *说明         :   需要先调用GU900E_SetSMSServeNumber()设置短信中心号码
206.                            需要使用全局的PDU数据缓冲区
207.                            一定要添加结束符
208.                            当短信长度超过单条短信长度限制后会发送多条短信
209.        ***************************************************************************

使用特权

评论回复
板凳
ITshao9|  楼主 | 2016-5-31 11:10 | 只看该作者
**********************************************/  
210.        #define SMS_MAX_LEN     2048                    //短信最大长度  
211.        bool GSM_SendSMS(char *pSMS, char *pPhoneNumber)  
212.        {  
213.            char SMSBuff[160+1];    //短信最大160B,加上一个结束符  
214.            u8 PDUBuff[512];        //短信PDU数据缓冲区  
215.            u16 SMSLen;             //短信长度  
216.            u16 SMSOffset;          //短信发送偏移位置,用于发送多条短信  
217.            u16 i,j;  
218.             
219.            SMSLen = strlen(pSMS);  //获取要发送的短信长度  
220.            if(SMSLen > SMS_MAX_LEN) SMSLen = SMS_MAX_LEN;   //限制短信最大长度,防止无限发送  
221.             
222.            if(strlen(SMSServeNumber.PhoneNumBuff) == 0)  
223.            {  
224.                GU900E_debug("由于短信中心号码设置失败,导致短信无法发送!\r\n");  
225.                return FALSE;  
226.            }  
227.             
228.            SMSOffset = 0;          //起始偏移为0  
229.            while(1)  
230.            {  
231.                if((SMSLen-SMSOffset) > 160)  
232.                    j = 160;  
233.                else   
234.                    j = SMSLen-SMSOffset;  
235.                for(i = 0;i < j;i ++)  
236.                {  
237.                    SMSBuff[i] = pSMS[SMSOffset + i];   //复制短信到发送缓冲区  
238.                }  
239.                SMSBuff[j] = 0; //添加结束符  
240.                  
241.                if(GSM_CheckNotASCII(SMSBuff,j) == TRUE)    //分割的短信中含有非ASCII编码,那么只能使用U2S编码,只能发送70个字符(包括中英文)  
242.                {  
243.                    SMSOffset += GSM_GetU2SCharOffset(SMSBuff,70);  //第一条短信限制70个字符,返回下一条分割的起始位置  
244.                    SMSBuff[SMSOffset] = 0;  
245.                }  
246.                else  
247.                {  
248.                    SMSOffset += j; //下一条分割的起始位置  
249.                    SMSBuff[SMSOffset] = 0;  
250.                }  
251.                  
252.                //GU900E_WaitSleep(1000);   //等待上一个操作完成  
253.                if(GSM_SendOneSMS(SMSBuff, PDUBuff, SMSServeNumber.PhoneNumBuff, pPhoneNumber) == TRUE)  
254.                {  
255.                    GU900E_debug("发送短信成功!\r\n");  
256.                      
257.                      
258.                }  
259.                else  
260.                {  
261.                    GU900E_debug("发送短信失败!\r\n");  
262.                    return FALSE;  
263.                }  
264.                if(SMSOffset >= SMSLen) break;   //短信发送完成,退出  
265.            }  
266.             
267.            return TRUE;  
268.             
269.        }  
270.          
271.          
272.          
273.        /*************************************************************************************************************************
274.        * 函数            :   void GU900E_HardwareInit(void)
275.        * 功能            :   初始化GU900E相关的硬件
276.        * 参数            :   无
277.        * 返回            :   无
278.        * 依赖            :   无
279.        * 作者            :   H F Y-GU900
280.        * 时间            :   2016-5-16
281.        * 最后修改时间    :   2016-5-16
282.        * 说明            :   主要初始化与GU900E相关的STM32 IO 以及 UART
283.        *************************************************************************************************************************/  
284.        void GU900E_HardwareInit(void)  
285.        {  
286.            GU900E_UartInit();                                  //初始化串口  
287.            GU900E_SetRxBuff(GU900E_Buff, GU900E_BUFF_SIZE);    //设置通信缓冲区  
288.          
289.            //初始化RI,用于指示新短信或者电话  
290.            DeviceClockEnable(DEV_GPIOB,ENABLE);                //使能GPIOB时钟  
291.            GPIOx_Init(GPIOB,BIT14, IN_IPU, IN_IN);             //上拉输入  
292.            GPIOx_Init(GPIOB,BIT12|BIT13|BIT15, OUT_PP, SPEED_10M); //推挽输出  
293.            GU900E_SetDTR(0);                                   //取消SLEEP  
294.            GU900E_SetRESET(1);                                 //复位无效  
295.            GU900E_SetPWR(1);                                   //上电无效  
296.        }  
297.          
298.          
299.          
300.          
301.        /*************************************************************************************************************************
302.        * 函数                :   void GU900E_HardwarePowerUP(void)
303.        * 功能                :   GU900E硬件开机
304.        * 参数                :   无
305.        * 返回                :   无
306.        * 依赖                :   无
307.        * 作者                :   H F Y-GU900
308.        * 时间                :   2016-5-18
309.        * 最后修改时间    :   2016-5-18
310.        * 说明                :   用于GU900E模块开机,拉低PWR
311.        *************************************************************************************************************************/  
312.        void GU900E_HardwarePowerUP(void)  
313.        {  
314.            GU900E_SetPWR(1);   //恢复高电平  
315.            GSM_DelayMS(200);  
316.            GU900E_SetPWR(0);   //拉低750ms开机  
317.            GSM_DelayMS(750);  
318.            GSM_Delay100MS();  
319.            GU900E_SetPWR(1);   //恢复高电平  
320.            GSM_DelaySer(3);    //延时3S等待开机完毕                              
321.        }  
322.          
323.          
324.          
325.        /*************************************************************************************************************************
326.        * 函数                :   void GU900E_HardwarePowerDOWN(void)
327.        * 功能                :   GU900E硬件关机
328.        * 参数                :   无
329.        * 返回                :   无
330.        * 依赖                :   无
331.        * 作者                :   H F Y-GU900
332.        * 时间                :   2016-5-18
333.        * 最后修改时间    :   2016-5-18
334.        * 说明                :   用于GU900E模块关机机,拉低PWR大于1S小于5S
335.        *************************************************************************************************************************/  
336.        void GU900E_HardwarePowerDOWN(void)  
337.        {  
338.            GU900E_SetPWR(1);   //恢复高电平  
339.            GSM_DelayMS(200);  
340.            GU900E_SetPWR(0);   //拉低1500ms关机  
341.            GSM_DelaySer(1);      
342.            GSM_DelayMS(500);  
343.            GU900E_SetPWR(1);   //恢复高电平  
344.            GSM_DelaySer(2);    //延时2S等待注销网络                     
345.        }  
346.          
347.          
348.          
349.          
350.          
351.        /*************************************************************************************************************************
352.        * 函数                :   void GU900E_HardwareReset(void)
353.        * 功能                :   GU900E硬件复位
354.        * 参数                :   无
355.        * 返回                :   无
356.        * 依赖                :   无
357.        * 作者                :   H F Y-GU900
358.        * 时间                :   2016-5-18
359.        * 最后修改时间    :   2016-5-18
360.        * 说明                :   用于GU900E模块硬件复位
361.        *************************************************************************************************************************/  
362.        void GU900E_HardwareReset(void)  
363.        {  
364.            GU900E_SetRESET(1); //恢复高电平  
365.            GSM_Delay100MS();  
366.            GU900E_SetRESET(0); //拉低100mS复位  
367.            GSM_Delay100MS();  
368.            GU900E_SetRESET(1); //恢复高电平  
369.            GSM_DelaySer(2);    //延时2S                    
370.        }  
371.          
372.          
373.        /*************************************************************************************************************************
374.        * 函数            :   bool GU900E_ModuleInit(void)
375.        * 功能            :   初始化GU900E模块
376.        * 参数            :   无
377.        * 返回            :   FALSE:初始化失败;TRUE:初始化成功
378.        * 依赖            :   底层
379.        * 作者            :   H F Y-GU900
380.        * 时间            :   2016-5-16
381.        * 最后修改时间    :   2016-5-16
382.        * 说明            :   主要初始化与GU900E配置,以及初始化网络
383.        *************************************************************************************************************************/  
384.        bool GU900E_ModuleInit(void)  
385.        {  
386.            u32 cnt;  
387.            u8 retry = 5;       //重试次数  
388.             
389.            //检测模块存在  
390.            retry = 5;      //重试次数  
391.            do  
392.            {  
393.                GU900E_SendATcom("AT"); //发送"AT",同步波特率,并且等待应答  
394.                if(AT_RETURN_OK == GU900E_GetATResp(GU900E_Buff, &cnt, "OK", 10, 10))   //等待响应,超时100ms  
395.                {  
396.                    break;  
397.                }  
398.                retry --;  
399.            }while(retry);  
400.            if(retry == 0) return FALSE;  
401.             
402.            //设置关闭回显  
403.            retry = GU900E_RETRY;       //重试次数  
404.            do  
405.            {  
406.                GU900E_SendATcom("ATE 0");  //发送"ATE",关闭回显模式  
407.                if(AT_RETURN_OK == GU900E_GetATResp(GU900E_Buff, &cnt, "OK", 10, 10))   //等待响应,超时100ms  
408.                {  
409.                    GU900E_debug("\r\n关闭AT回显模式成功!\r\n");  
410.                    break;  
411.                }  
412.                  
413.                GU900E_Ready(); //等待就绪  
414.                retry --;  
415.            }while(retry);  
416.            if(retry == 0)  
417.            {  
418.                GU900E_debug("\r\n关闭AT回显模式失败!\r\n");  
419.                return FALSE;  
420.            }  
421.             
422.            //设置短消息格式为PDU格式  
423.            retry = GU900E_RETRY;       //重试次数  
424.            do  
425.            {  
426.                GU900E_SendATcom("AT+CMGF=0");  //发送"AT+CMGF",设置短消息格式为PDU格式  
427.                if(AT_RETURN_OK == GU900E_GetATResp(GU900E_Buff, &cnt, "OK", 10, 10))   //等待响应,超时100ms  
428.                {  
429.                    GU900E_debug("\r\n设置短消息格式为PDU格式成功!\r\n");  
430.                    break;  
431.                }  
432.                  
433.                GU900E_Ready(); //等待就绪  
434.                retry --;  
435.            }while(retry);  
436.            if(retry == 0)  
437.            {  
438.                GU900E_debug("\r\n设置短消息格式为PDU格式失败!\r\n");  
439.                return FALSE;  
440.            }  
441.             
442.            //使能RI引脚提示  
443.            retry = GU900E_RETRY;       //重试次数  
444.            do  
445.            {  
446.                GU900E_SendATcom("AT+CFGRI=1"); //发送"AT+CFGRI",启动RI引脚提示  
447.                if(AT_RETURN_OK == GU900E_GetATResp(GU900E_Buff, &cnt, "OK", 10, 10))   //等待响应,超时100ms  
448.                {  
449.                    GU900E_debug("\r\n启动RI引脚提示成功!\r\n");  
450.                    break;  
451.                }  
452.                GU900E_Ready(); //等待就绪  
453.                retry --;  
454.            }while(retry);  
455.            if(retry == 0)  
456.            {  
457.                GU900E_debug("\r\n启动RI引脚提示失败!\r\n");  
458.                return FALSE;  
459.            }  
460.             
461.            //设置模块sleep模式使能  
462.            retry = GU900E_RETRY;       //重试次数  
463.            do  
464.            {  
465.                GU900E_SendATcom("AT+CSCLK=1"); //发送"AT+CSCLK",启动SLEEP模式  
466.                if(AT_RETURN_OK == GU900E_GetATResp(GU900E_Buff, &cnt, "OK", 10, 10))   //等待响应,超时100ms  
467.                {  
468.                    GU900E_debug("\r\n设置SLEEP成功!\r\n");  
469.                    break;  
470.                }  
471.                  
472.                GU900E_Ready(); //等待就绪  
473.                retry --;  
474.            }while(retry);  
475.            if(retry == 0)  
476.            {  
477.                GU900E_debug("\r\n设置SLEEP失败!\r\n");  
478.                return FALSE;  
479.            }  
480.             
481.            GU900E_SetDTR(1);   //使能SLEEP模式  
482.            return TRUE;  
483.        }  
484.          
485.          
486.          
487.          
488.        /*************************************************************************************************************************
489.        * 函数            :   bool GU900E_TestAT(u32 retry)
490.        * 功能            :   GU900E AT 命令通信测试
491.        * 参数            :   retry:重试次数
492.        * 返回            :   FALSE:通信失败;TRUE:通信成功
493.        * 依赖            :   底层
494.        * 作者            :   H F Y-GU900
495.        * 时间            :   2016-5-18
496.        * 最后修改时间    :   2016-5-18
497.        * 说明            :   每隔20ms向GU900E发送一个"AT",等待响应返回
498.        ***************************************************************************

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

54

帖子

3

粉丝