gsm 收发短信 打电话


  1. /************************************************************************************************************* 
  2.  * 文件名:         SIM900.c 
  3.  * 功能:          STM32 SIM900底层驱动函数 
  4.  * 作者:          cp1300@139.com 
  5.  * 创建时间:        2013-10-16 
  6.  * 最后修改时间:  2013-10-16 
  7.  * 详细:          GSM_CDMA发送短信等 
  8.                     2014-04-22:添加字节超时与总超时 
  9. *************************************************************************************************************/  
  10. #include "system.h"  
  11. #include "usart.h"  
  12. #include "SIM900.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. //SIM900通信缓冲区  
  21. u8  SIM900_Buff[SIM900_BUFF_SIZE];  //缓冲区  
  22.   
  23.   
  24. //调试开关  
  25. #define SIM900_DBUG 0  
  26. #if SIM900_DBUG  
  27.     #include "system.h"  
  28.     #define SIM900_debug(format,...)    uart_printf(format,##__VA_ARGS__)  
  29. #else  
  30.     #define SIM900_debug(format,...)    /\  
  31. /  
  32. #endif  //SIM900_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 SIM900_SetSMSServeNumber(char *pSMSServeNumber,u8 NumLen) 
  58. * 功能                :   设置全局短信中心号码 
  59. * 参数                :   pSMSServeNumber:短信中心号码,NumLen:短信中心号码长度 
  60. * 返回                :   无 
  61. * 依赖                :   无 
  62. * 作者                :   cp1300@139.com 
  63. * 时间                :   2013-10-25 
  64. * 最后修改时间    :   2013-10-25 
  65. * 说明                :   用于发送短信的时候进行调用 
  66. *************************************************************************************************************************/  
  67. void SIM900_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[i] = pSMSServeNumber[i];  
  75.     }  
  76.     SMSServeNumber.PhoneNumLen = NumLen;  
  77.     SMSServeNumber.PhoneNumBuff[SMSServeNumber.PhoneNumLen] = '\0';     //添加结束符  
  78.     SIM900_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. * 作者                :   cp1300@139.com 
  91. * 时间                :   2013-10-25 
  92. * 最后修改时间    :   2013-10-25 
  93. * 说明                :   用于选择发送短信的模式,选择U2S或者7BIT编码 
  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. * 作者                :   cp1300@139.com 
  117. * 时间                :   2013-10-25 
  118. * 最后修改时间    :   2013-10-25 
  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 SIM900_WaitSleep(void) 
  152. * 功能                :   等待GSM模块空闲,并重新唤醒 
  153. * 参数                :   TimeOut:等待超时,时间单位ms 
  154. * 返回                :   TRUE:成功;FALSE:超时 
  155. * 依赖                :   无 
  156. * 作者                :   cp1300@139.com 
  157. * 时间                :   2013-10-25 
  158. * 最后修改时间    :   2013-10-25 
  159. * 说明                :   用于等待操作完成,防止快速操作造成模块不响应 
  160. *************************************************************************************************************************/  
  161. bool SIM900_WaitSleep(u32 TimeOut)  
  162. {  
  163.     u32 i;  
  164.     u32 cnt;  
  165.       
  166.     TimeOut /= 100;  
  167.     TimeOut +=1;  
  168.       
  169.     SIM900_SetDTR(1);                           //等待模块空闲后进入SLEEP模式  
  170.       
  171.     for(i = 0;i < TimeOut;i ++)  
  172.     {  
  173.         GSM_Delay100MS();                       //延时100ms  
  174.         SIM900_SendATcom("AT");                 //发送"AT",同步波特率,并且等待应答  
  175.         if(AT_RETURN_TIME_OUT == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 15)) //等待响应,超时150ms  
  176.         {  
  177.             break;  
  178.         }  
  179.     }  
  180.     SIM900_SetDTR(0);                           //唤醒  
  181.     if(i == TimeOut)   
  182.     {  
  183.         SIM900_debug("模块进入空闲模式失败!\r\n");  
  184.         return FALSE;  
  185.     }  
  186.     GSM_Delay100MS();                       //延时100ms  
  187.       
  188.     SIM900_debug("模块进入空闲模式成功!\r\n");  
  189.     SIM900_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. *作者         :   cp1300@139.com 
  203. *时间         :   2013-10-25 
  204. *最后修改时间 :   2013-10-25 
  205. *说明         :   需要先调用SIM900_SetSMSServeNumber()设置短信中心号码 
  206.                     需要使用全局的PDU数据缓冲区 
  207.                     一定要添加结束符 
  208.                     当短信长度超过单条短信长度限制后会发送多条短信 
  209. *************************************************************************************************************************/  
  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.         SIM900_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.         //SIM900_WaitSleep(1000);   //等待上一个操作完成  
  253.         if(GSM_SendOneSMS(SMSBuff, PDUBuff, SMSServeNumber.PhoneNumBuff, pPhoneNumber) == TRUE)  
  254.         {  
  255.             SIM900_debug("发送短信成功!\r\n");  
  256.               
  257.               
  258.         }  
  259.         else  
  260.         {  
  261.             SIM900_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 SIM900_HardwareInit(void) 
  275. * 功能            :   初始化SIM900相关的硬件 
  276. * 参数            :   无 
  277. * 返回            :   无 
  278. * 依赖            :   无 
  279. * 作者            :   cp1300@139.com 
  280. * 时间            :   2013-10-16 
  281. * 最后修改时间    :   2013-10-16 
  282. * 说明            :   主要初始化与SIM900相关的STM32 IO 以及 UART 
  283. *************************************************************************************************************************/  
  284. void SIM900_HardwareInit(void)  
  285. {  
  286.     SIM900_UartInit();                                  //初始化串口  
  287.     SIM900_SetRxBuff(SIM900_Buff, SIM900_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.     SIM900_SetDTR(0);                                   //取消SLEEP  
  294.     SIM900_SetRESET(1);                                 //复位无效  
  295.     SIM900_SetPWR(1);                                   //上电无效  
  296. }  
  297.   
  298.   
  299.   
  300.   
  301. /************************************************************************************************************************* 
  302. * 函数                :   void SIM900_HardwarePowerUP(void) 
  303. * 功能                :   SIM900硬件开机 
  304. * 参数                :   无 
  305. * 返回                :   无 
  306. * 依赖                :   无 
  307. * 作者                :   cp1300@139.com 
  308. * 时间                :   2013-10-29 
  309. * 最后修改时间    :   2013-10-29 
  310. * 说明                :   用于SIM900模块开机,拉低PWR 
  311. *************************************************************************************************************************/  
  312. void SIM900_HardwarePowerUP(void)  
  313. {  
  314.     SIM900_SetPWR(1);   //恢复高电平  
  315.     GSM_DelayMS(200);  
  316.     SIM900_SetPWR(0);   //拉低750ms开机  
  317.     GSM_DelayMS(750);  
  318.     GSM_Delay100MS();  
  319.     SIM900_SetPWR(1);   //恢复高电平  
  320.     GSM_DelaySer(3);    //延时3S等待开机完毕                              
  321. }  
  322.   
  323.   
  324.   
  325. /************************************************************************************************************************* 
  326. * 函数                :   void SIM900_HardwarePowerDOWN(void) 
  327. * 功能                :   SIM900硬件关机 
  328. * 参数                :   无 
  329. * 返回                :   无 
  330. * 依赖                :   无 
  331. * 作者                :   cp1300@139.com 
  332. * 时间                :   2013-10-29 
  333. * 最后修改时间    :   2013-10-29 
  334. * 说明                :   用于SIM900模块关机机,拉低PWR大于1S小于5S 
  335. *************************************************************************************************************************/  
  336. void SIM900_HardwarePowerDOWN(void)  
  337. {  
  338.     SIM900_SetPWR(1);   //恢复高电平  
  339.     GSM_DelayMS(200);  
  340.     SIM900_SetPWR(0);   //拉低1500ms关机  
  341.     GSM_DelaySer(1);      
  342.     GSM_DelayMS(500);  
  343.     SIM900_SetPWR(1);   //恢复高电平  
  344.     GSM_DelaySer(2);    //延时2S等待注销网络                      
  345. }  
  346.   
  347.   
  348.   
  349.   
  350.   
  351. /************************************************************************************************************************* 
  352. * 函数                :   void SIM900_HardwareReset(void) 
  353. * 功能                :   SIM900硬件复位 
  354. * 参数                :   无 
  355. * 返回                :   无 
  356. * 依赖                :   无 
  357. * 作者                :   cp1300@139.com 
  358. * 时间                :   2013-10-29 
  359. * 最后修改时间    :   2013-10-29 
  360. * 说明                :   用于SIM900模块硬件复位 
  361. *************************************************************************************************************************/  
  362. void SIM900_HardwareReset(void)  
  363. {  
  364.     SIM900_SetRESET(1); //恢复高电平  
  365.     GSM_Delay100MS();  
  366.     SIM900_SetRESET(0); //拉低100mS复位  
  367.     GSM_Delay100MS();  
  368.     SIM900_SetRESET(1); //恢复高电平  
  369.     GSM_DelaySer(2);    //延时2S                    
  370. }  
  371.   
  372.   
  373. /************************************************************************************************************************* 
  374. * 函数            :   bool SIM900_ModuleInit(void) 
  375. * 功能            :   初始化SIM900模块 
  376. * 参数            :   无 
  377. * 返回            :   FALSE:初始化失败;TRUE:初始化成功 
  378. * 依赖            :   底层 
  379. * 作者            :   cp1300@139.com 
  380. * 时间            :   2013-10-16 
  381. * 最后修改时间    :   2013-10-16 
  382. * 说明            :   主要初始化与SIM900配置,以及初始化网络 
  383. *************************************************************************************************************************/  
  384. bool SIM900_ModuleInit(void)  
  385. {  
  386.     u32 cnt;  
  387.     u8 retry = 5;       //重试次数  
  388.       
  389.     //检测模块存在  
  390.     retry = 5;      //重试次数  
  391.     do  
  392.     {  
  393.         SIM900_SendATcom("AT"); //发送"AT",同步波特率,并且等待应答  
  394.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_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 = SIM900_RETRY;       //重试次数  
  404.     do  
  405.     {  
  406.         SIM900_SendATcom("ATE 0");  //发送"ATE",关闭回显模式  
  407.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 10))   //等待响应,超时100ms  
  408.         {  
  409.             SIM900_debug("\r\n关闭AT回显模式成功!\r\n");  
  410.             break;  
  411.         }  
  412.           
  413.         SIM900_Ready(); //等待就绪  
  414.         retry --;  
  415.     }while(retry);  
  416.     if(retry == 0)  
  417.     {  
  418.         SIM900_debug("\r\n关闭AT回显模式失败!\r\n");  
  419.         return FALSE;  
  420.     }  
  421.       
  422.     //设置短消息格式为PDU格式  
  423.     retry = SIM900_RETRY;       //重试次数  
  424.     do  
  425.     {  
  426.         SIM900_SendATcom("AT+CMGF=0");  //发送"AT+CMGF",设置短消息格式为PDU格式  
  427.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 10))   //等待响应,超时100ms  
  428.         {  
  429.             SIM900_debug("\r\n设置短消息格式为PDU格式成功!\r\n");  
  430.             break;  
  431.         }  
  432.           
  433.         SIM900_Ready(); //等待就绪  
  434.         retry --;  
  435.     }while(retry);  
  436.     if(retry == 0)  
  437.     {  
  438.         SIM900_debug("\r\n设置短消息格式为PDU格式失败!\r\n");  
  439.         return FALSE;  
  440.     }  
  441.       
  442.     //使能RI引脚提示  
  443.     retry = SIM900_RETRY;       //重试次数  
  444.     do  
  445.     {  
  446.         SIM900_SendATcom("AT+CFGRI=1"); //发送"AT+CFGRI",启动RI引脚提示  
  447.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 10))   //等待响应,超时100ms  
  448.         {  
  449.             SIM900_debug("\r\n启动RI引脚提示成功!\r\n");  
  450.             break;  
  451.         }  
  452.         SIM900_Ready(); //等待就绪  
  453.         retry --;  
  454.     }while(retry);  
  455.     if(retry == 0)  
  456.     {  
  457.         SIM900_debug("\r\n启动RI引脚提示失败!\r\n");  
  458.         return FALSE;  
  459.     }  
  460.       
  461.     //设置模块sleep模式使能  
  462.     retry = SIM900_RETRY;       //重试次数  
  463.     do  
  464.     {  
  465.         SIM900_SendATcom("AT+CSCLK=1"); //发送"AT+CSCLK",启动SLEEP模式  
  466.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 10))   //等待响应,超时100ms  
  467.         {  
  468.             SIM900_debug("\r\n设置SLEEP成功!\r\n");  
  469.             break;  
  470.         }  
  471.           
  472.         SIM900_Ready(); //等待就绪  
  473.         retry --;  
  474.     }while(retry);  
  475.     if(retry == 0)  
  476.     {  
  477.         SIM900_debug("\r\n设置SLEEP失败!\r\n");  
  478.         return FALSE;  
  479.     }  
  480.       
  481.     SIM900_SetDTR(1);   //使能SLEEP模式  
  482.     return TRUE;  
  483. }  
  484.   
  485.   
  486.   
  487.   
  488. /************************************************************************************************************************* 
  489. * 函数            :   bool SIM900_TestAT(u32 retry) 
  490. * 功能            :   SIM900 AT 命令通信测试 
  491. * 参数            :   retry:重试次数 
  492. * 返回            :   FALSE:通信失败;TRUE:通信成功 
  493. * 依赖            :   底层 
  494. * 作者            :   cp1300@139.com 
  495. * 时间            :   2013-10-20 
  496. * 最后修改时间    :   2013-10-20 
  497. * 说明            :   每隔20ms向SIM900发送一个"AT",等待响应返回 
  498. *************************************************************************************************************************/  
  499. bool SIM900_TestAT(u32 retry)  
  500. {  
  501.     u32 cnt;  
  502.   
  503.     //检测模块存在  
  504.     do  
  505.     {  
  506.         SIM900_SendATcom("AT");                                             //发送"AT",同步波特率,并且等待应答  
  507.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 15))   //等待响应,超时150ms  
  508.         {  
  509.             return TRUE;  
  510.         }  
  511.         retry --;  
  512.     }while(retry);  
  513.       
  514.     return FALSE;  
  515. }  
  516.   
  517.   
  518. /************************************************************************************************************************* 
  519. * 函数                :   SIM900_ERROR SIM900_GetATResp(u8 *pRxBuff, u32 *pLen, const char *pKeyword, u32 ByteTime, u32 TimeOut) 
  520. * 功能                :   获取SIM900的AT指令响应 
  521. * 参数                :   pRxBuff:接收缓冲区指针(输入);pLen:接收到的数据大小(输出), 
  522.                         pKeyword:关键字,为字符串,比如"OK",如果在接收到的字符串中有OK字符,就返回成功,否则失败(输入) 
  523.                         ByteTime:字节超时时间,单位ms最大999ms 
  524.                         TimeOut:等待超时时间,单位字节超时时间 
  525. * 返回                :   SIM900_ERROR 
  526. * 依赖                :   无 
  527. * 作者                :   cp1300@139.com 
  528. * 时间                :   2013-10-16 
  529. * 最后修改时间    :   2014-04-22 
  530. * 说明                :   本函数会在接收缓冲区字符串结束添加'\0' 
  531.                         2014-04-22:添加字节超时与总超时 
  532. *************************************************************************************************************************/  
  533. SIM900_ERROR SIM900_GetATResp(u8 *pRxBuff, u32 *pLen, const char *pKeyword, u32 ByteTime, u32 TimeOut)  
  534. {  
  535.     u32 cnt1, cnt2=0;   //接收数据计数器  
  536.     u32 timeCnt = TimeOut;  
  537.       
  538.     if(ByteTime > 999)ByteTime = 999;  
  539.     do  
  540.     {  
  541.         cnt1 = cnt2;  
  542.         GSM_DelayMS(ByteTime);              //延时字节超时  
  543.         cnt2 = SIM900_GetRxCnt();           //获取接收数据计数器  
  544.         if(cnt1 == cnt2)                    //完成接收数据了,退出等待  
  545.         {  
  546.             timeCnt --;  
  547.             if((cnt1 > 0)&&(timeCnt!=0)) timeCnt=1;              //数据接收完毕,退出  
  548.         }  
  549.         else  
  550.         {  
  551.             timeCnt = TimeOut;  
  552.         }  
  553.     }while(timeCnt);  
  554.       
  555.     //等待超时  
  556.     if(cnt2 == 0)  
  557.     {  
  558.         SIM900_debug("\r\nAT指令返回超时\r\n");  
  559.         return AT_RETURN_TIME_OUT;          //返回超时错误  
  560.     }  
  561.     //数据接收完毕  
  562.     *pLen = cnt2;                           //返回接收数据长度  
  563.     pRxBuff[cnt2]   = '\0';                 //将数据结尾添加结束字符串  
  564.       
  565.     SIM900_debug("%s\r\n",pRxBuff);         //打印返回信息  
  566.   
  567.     if(strstr((const char*)pRxBuff, pKeyword) != NULL)  //搜索关键字  
  568.     {  
  569.         SIM900_debug("%s 返回成功!\r\n",pKeyword);  
  570.         return AT_RETURN_OK;  
  571.     }  
  572.     else if(strstr((const char*)pRxBuff, "ERROR") != NULL)  
  573.     {  
  574.         SIM900_debug("%s 返回错误!\r\n",pKeyword);  
  575.         return AT_RETURN_ERROR;  
  576.     }  
  577.     else  
  578.     {  
  579.         SIM900_debug("%s 返回未知!\r\n",pKeyword);  
  580.         return AT_RETURN_UNKNOWN;  
  581.     }  
  582.       
  583.       
  584. }  
  585.   
  586.   
  587. /************************************************************************************************************************* 
  588. * 函数            :   int SIM900_GetSmsNum(void) 
  589. * 功能            :   获取SIM卡存储的短信数量 
  590. * 参数            :   无 
  591. * 返回            :   <0:错误,其它:短信数量 
  592. * 依赖            :   底层 
  593. * 作者            :   cp1300@139.com 
  594. * 时间            :   2013-10-20 
  595. * 最后修改时间    :   2013-10-20 
  596. * 说明            :   无 
  597. *************************************************************************************************************************/  
  598. int SIM900_GetSmsNum(void)  
  599. {  
  600.     u8 n;  
  601.     u32 cnt;  
  602.     char *p;  
  603.     u8 retry = SIM900_RETRY;        //重试次数  
  604.       
  605.     do  
  606.     {  
  607.         SIM900_SendATcom("AT+CPMS?");   //发送"AT+CPMS",获取短信数量  
  608.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))   //等待响应,超时200MS  
  609.         {  
  610.             break;  
  611.         }  
  612.         SIM900_Ready(); //等待就绪  
  613.         retry --;  
  614.     }while(retry);  
  615.     if(retry == 0) return -1;                               //超时  
  616.       
  617.     p = strstr((const char*)SIM900_Buff, "\"SM\"");         //搜索字符""SM""  
  618.     if(p != NULL)                 
  619.     {     
  620.         if(p[6] != ',') n = 2;                              //短信数量有可能是1位数,也有可能是2位数,通过判断后面是否为','  
  621.         else n = 1;  
  622.         return GSM_StringToDec(p + 5, n);                   //跳过前面的5字节,""SM",",并获取存储的短信数量                     
  623.     }  
  624.     return -1;                                              //错误  
  625. }  
  626.   
  627.   
  628.   
  629. /************************************************************************************************************************* 
  630. * 函数                :   bool SIM900_DelMultiSMS(SIM900_DEL DelStatus) 
  631. * 功能                :   SIM900批量删除短信 
  632. * 参数                :   SIM900_DEL 
  633. * 返回                :   TRUE:成功;FALSE:失败; 
  634. * 依赖                :   底层 
  635. * 作者                :   cp1300@139.com 
  636. * 时间                :   2013-10-17 
  637. * 最后修改时间        :   2013-10-20 
  638. * 说明                :   批量删除的时候可能会很慢 
  639. *************************************************************************************************************************/  
  640. bool SIM900_DelMultiSMS(SIM900_DEL DelStatus)  
  641. {  
  642.     u32 cnt;  
  643.     u8 retry = SIM900_RETRY;        //重试次数  
  644.       
  645.     do  
  646.     {  
  647.         switch(DelStatus)  
  648.         {  
  649.             case DEL_READ_SMS:          //删除所有已读短信  
  650.                 SIM900_SendATcom("AT+CMGDA=1"); break;  
  651.             case DEL_UNREAD_SMS:        //删除所有未读短信  
  652.                 SIM900_SendATcom("AT+CMGDA=2"); break;  
  653.             case DEL_SENT_SMS:          //删除所有已经发送的短信  
  654.                 SIM900_SendATcom("AT+CMGDA=3"); break;  
  655.             case DEL_UNSENT_SMS:        //删除所有未发送短信  
  656.                 SIM900_SendATcom("AT+CMGDA=4"); break;  
  657.             case DEL_INBOX_SMS:         //删除所有接收短信  
  658.                 SIM900_SendATcom("AT+CMGDA=5"); break;  
  659.             case DEL_ALL_SMS:           //删除所有短信  
  660.                 SIM900_SendATcom("AT+CMGDA=6"); break;  
  661.             defaultreturn FALSE;  
  662.         }  
  663.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 200))//等待响应,超时2S  
  664.         {  
  665.             return TRUE;  
  666.         }  
  667.         SIM900_Ready(); //等待就绪  
  668.     }while(retry --);  
  669.       
  670.     return FALSE;  
  671. }  
  672.   
  673.   
  674.   
  675.   
  676.   
  677. /************************************************************************************************************************* 
  678. * 函数                :   SIM900_ERROR SIM900_GetUnreadSMS(u8 *pUnreadSMSBuff, u32 BuffSize, u32 *pPDUCnt) 
  679. * 功能                :   读取SIM900所有的未读短信 
  680. * 参数                :   pUnreadSMSBuff:未读短信PDU数据缓冲区指针,BuffSize:缓冲区大小,pPDUCnt:PDU数据大小 
  681. * 返回                :   SIM900_ERROR 
  682. * 依赖                :   底层 
  683. * 作者                :   cp1300@139.com 
  684. * 时间                :   2013-10-17 
  685. * 最后修改时间    :   2013-10-17 
  686. * 说明                :   短信最大存储数量为50条 
  687.                         缓冲区必须足够大,做好最坏打算,有50条未读短信,如果缓冲区不够大,会发送溢出 
  688.                         溢出后虽然不会造成系统错误,但是会覆盖前面的未读短信数据. 
  689. *************************************************************************************************************************/  
  690. SIM900_ERROR SIM900_GetUnreadSMS(u8 *pUnreadSMSBuff, u32 BuffSize, u32 *pPDUCnt)  
  691. {  
  692.     SIM900_ERROR error;  
  693.     u8 retry = SIM900_RETRY;        //重试次数  
  694.       
  695.     SIM900_SetRxBuff(pUnreadSMSBuff, BuffSize);                     //重新设置接收缓冲区  
  696.     do  
  697.     {  
  698.         SIM900_SendATcom("AT+CMGL=0");                                  //发送"AT+CMGL",读取所有的未读短息  
  699.         error = SIM900_GetATResp(pUnreadSMSBuff, pPDUCnt, "OK", 250, 4);    //等待响应,超时1000ms  
  700.         if(error == AT_RETURN_OK)  
  701.             break;  
  702.         SIM900_Ready(); //等待就绪  
  703.         retry --;  
  704.     }while(retry);  
  705.       
  706.     SIM900_SetRxBuff(SIM900_Buff, SIM900_BUFF_SIZE);                //恢复默认缓冲区  
  707.       
  708.     return error;  
  709. }  
  710.   
  711.   
  712.   
  713.   
  714.   
  715.   
  716. /************************************************************************************************************************* 
  717. *函数         :   bool GSM_ParsePDUSMS(char *pPDU,char *pSMS,u32 len,SMS_INFO *pInfo) 
  718. *功能         :   解析一条PDU格式短信 
  719. *参数         :   pPDU:短信PDU数据缓冲区指针 
  720. *                   pSMS:解析后的短信缓冲区指针 
  721. *                   pInfo:短信信息指针 
  722. *返回         :   TRUE:成功;FALSE:失败 
  723. *依赖         :   void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt); 
  724. *作者         :   cp1300@139.com 
  725. *时间         :   2013-04-04 
  726. *最后修改时间 :   2013-05-01 
  727. *说明         :   无 
  728. *************************************************************************************************************************/  
  729. bool GSM_ParsePDUSMS(char *pPDU, char *pSMS, u32 PDUSize, SMS_INFO *pInfo)  
  730. {  
  731.     u16 cnt = 0;  
  732.     u16 temp;  
  733.     char *p;  
  734.     u16 SMS_Size;  
  735.       
  736.     p = strstr((const char*)pPDU, "+CMGR:");  
  737.     if(p == NULL)  
  738.     {  
  739.         SIM900_debug("短信中没有搜索到\"+CMGR:\"\r\n");  
  740.         p = strstr((const char*)pPDU, "+CMGL:");  
  741.         if(p == NULL)  
  742.         {  
  743.             SIM900_debug("短信中没有搜索到\"+CMGL:\"\r\n");  
  744.             return FALSE;  
  745.         }  
  746.     }  
  747.     //提取短信的编号 //+CMGR: 1,"",34  
  748.     if(p[8] != ',') pInfo->IndexNum = GSM_StringToDec(p + 7, 2); //短信索引可能是1位数,也有可能是2位数,通过判断后面是否为','  
  749.     else pInfo->IndexNum = GSM_StringToDec(p + 7, 1);;  
  750.                   
  751.     p = strstr((const char*)p, "\r\n"); //寻找短信PDU开始位置  
  752.     cnt = ((u32)p - (u32)pPDU) + 2;     //找到短信PDU开始的位置了  
  753.     if(p == NULL || cnt >= PDUSize)  
  754.     {  
  755.         pInfo->SMS_Size = 0;  
  756.         SIM900_debug("短信解析错误!\r\n");  
  757.         return FALSE;  
  758.     }  
  759.       
  760.     //获取短信中心号码长度  
  761.     temp = GSM_StringToHex(&pPDU[cnt], 2);  //将16进制样式字符串转换为整型数  
  762.     cnt += 2;           //跳过前面的短信中心号码长度字节  
  763.     cnt += temp*2;      //跳过前面的短信中心信息  
  764.       
  765.     //解析PDU数据  RT  UDHI  SRI -  -  MMS   MTI  MTI  //UDHI为1,代表用户数据有头部信息,用于标识短信拆分信息  
  766.     pInfo->PDU = GSM_StringToHex(&pPDU[cnt], 2); //将16进制样式字符串转换为整型数//PDU数据  
  767.     cnt += 2;           //跳过PDU头数据字节  
  768.   
  769.     //计算发送短信的号码的长度  
  770.     temp = GSM_StringToHex(&pPDU[cnt], 2);  //将16进制样式字符串转换为整型数  
  771.     cnt += 2;           //跳过电话号码长度字节  
  772.     cnt += 2;           //跳过地址类型,常为"91",一字节  
  773.     pInfo->NumLen = ChartoPhoneNum((char *)&pPDU[cnt], (char *)&(pInfo->NumBuff[0]), (temp > SMS_NUM_LEN_MAX - 2) ? (SMS_NUM_LEN_MAX - 2) : temp); //转换发送号码  
  774.     pInfo->NumBuff[pInfo->NumLen] = 0;    //结束符  
  775.     //lcd_printf("pInfo->NumLen=%d\r\n",pInfo->NumLen);  
  776.     //uart_printf("%s\r\n",pInfo->NumBuff);  
  777.     cnt += (temp%2) ? (temp+1) : temp;  //跳过发送号码长度的字节数  
  778.     cnt+=2; //跳过PID,2B  
  779.     pInfo->DSC = GSM_StringToHex(&pPDU[cnt], 2); //获取DSC信息  
  780.     cnt+=2; //跳过DSC,2B  
  781.     //cnt+=2;   //跳过VP,2B   //没有这个标志  
  782.     //cnt+=2;   //跳过UDL,2B//没有这个标志  
  783.   
  784.       
  785.     pInfo->Timer.Year = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');      cnt += 2;   //年  
  786.     pInfo->Timer.Month = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0'); cnt += 2;   //年  
  787.     pInfo->Timer.Day = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');       cnt += 2;   //年  
  788.     pInfo->Timer.Hour = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');      cnt += 2;   //年  
  789.     pInfo->Timer.Minute = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');    cnt += 2;   //年  
  790.     pInfo->Timer.Second = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');    cnt += 2;   //年                                  
  791.     cnt += 2;   //跳过时差2字节  
  792.     SMS_Size = GSM_StringToHex(&pPDU[cnt], 2);      //计算短信字符数量,不管英文,中文都算一个字符  
  793.     SIM900_debug("SMS_Size = GSM_StringToHex(&pPDU[cnt], 2) = %d\r\n",SMS_Size);  
  794.     cnt += 2;                                           //跳过短信长度字节,2B  
  795.   
  796.     if(pInfo->PDU & 0x40)    //用户数据有头部信息,标识短信已经被分割为几条  
  797.     {  
  798.         cnt += 8;           //跳过前面8个数据,只要后面的4个,标识  
  799.         SMS_Size -= 12;     //短信长度减去偏移  
  800.           
  801.         pInfo->AllNum = GSM_StringToHex(&pPDU[cnt], 2);//计算总分割数  
  802.         cnt += 2;       //跳过2B的总数  
  803.         pInfo->PreNum = GSM_StringToHex(&pPDU[cnt], 2);//计算当前位置  
  804.         cnt += 2;       //跳过2B的当前位置  
  805.         SIM900_debug("短信分割:%d/%d\r\n",pInfo->AllNum, pInfo->PreNum);  
  806.     }  
  807.     else  
  808.     {  
  809.         pInfo->AllNum = pInfo->PreNum = 0;    //短信没有被分割  
  810.     }  
  811.       
  812.     //DCS 00:7BIT编码;08:UCS2编码;04:8bit编码  
  813.     switch((pInfo->DSC) & 0x0f)  
  814.     {  
  815.         case 0x00:  //7bit编码  
  816.         {  
  817.             SIM900_debug("短信为7bit编码(TEXT格式)\r\n");  
  818.             pInfo->SMS_Size = (SMS_Size > 160) ? 160 : SMS_Size;      //短信大小  
  819.             pInfo->TEXT_MODE = 1;      
  820.             SMS_Size = (SMS_Size * 7 / 8) + (((SMS_Size * 7) % 8) ? 1 : 0);//计算短信占用空间大小  
  821.             pPDU += cnt;  
  822.             for(temp = 0;temp < SMS_Size;temp ++)                //将PDU数据转换为16进制数据  
  823.             {  
  824.                 pPDU[temp] = GSM_StringToHex(&pPDU[temp << 1], 2);    //1B数据转换为PDU格式后占用2B  
  825.             }  
  826.             gsmDecode7bit((u8 *)pPDU, (char *)pSMS, SMS_Size);  //7bit->8bit,数据长度会发生变化  
  827.             //SIM900_debug("SMS:%s\r\n",pSMS);  
  828.         }break;  
  829.         case 0x04:  //8bit编码  
  830.         {  
  831.             SIM900_debug("短信为8bit编码(不支持)\r\n");  
  832.             return FALSE;  
  833.         }  
  834.         case 0x08:  //UCS2编码  
  835.         {  
  836.             SIM900_debug("短信为UCS2编码(PDU格式)\r\n");  
  837.             pInfo->TEXT_MODE = 0;      
  838.             SMS_Size = (SMS_Size > 140) ? 140 : SMS_Size;        //短信字符限制为140B  
  839.             //UNICODE PDU转换为字符串 --> GBK,返回短信大小,每个短信字符占用2字节,每个字节转换为PDU后占用2B  
  840.             pInfo->SMS_Size = UnicodeStrToString((u8 *)pPDU+cnt,(char *)pSMS,SMS_Size<<1);       
  841.         }break;  
  842.         default:SIM900_debug("未知短信编码格式!\r\n");return FALSE;  
  843.     }  
  844.   
  845.     pSMS[pInfo->SMS_Size] = '\0';                //添加结束符       
  846.       
  847.     return TRUE;  
  848. }  
  849.   
  850.   
  851.   
  852.   
  853.   
  854. /************************************************************************************************************************* 
  855. *函数         :   SIM900_ERROR SIM900_ReadTextSMS(char *pSMS, SMS_INFO *pInfo, u16 IndexNum) 
  856. *功能         :   读取一条TEXT格式短信 
  857. *参数         :   pSMS:解析后的短信存放位置指针,注意存放的最大大小由_MAX_SMS_SIZE决定 
  858. *                   pInfo:短信信息指针 
  859. *                   IndexNum:短信索引号 
  860. *返回         :   GSM_ERROR:状态 
  861. *依赖         :   短信读取与解析 
  862. *作者         :   cp1300@139.com 
  863. *时间         :   20130408 
  864. *最后修改时间 :   20130408 
  865. *说明         :    
  866. *************************************************************************************************************************/  
  867. SIM900_ERROR SIM900_ReadTextSMS(char *pSMS, SMS_INFO *pInfo, u16 IndexNum)  
  868. {  
  869.     SIM900_ERROR error;  
  870.     u32 cnt;  
  871.   
  872.     if(SIM900_TestAT(10) == FALSE)  //串口同步失败  
  873.     {  
  874.         SIM900_WaitSleep(1000); //等待上一个操作完成  
  875.     }  
  876.     //配置短信为TEXT格式  
  877.     SIM900_SendATcom("AT+CMGF=1");    
  878.     if(SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20) == AT_RETURN_OK)  
  879.     {  
  880.         sprintf((char *)SIM900_Buff, "AT+CMGR=%d", IndexNum);                       //写入索引号  
  881.         SIM900_SendATcom((char *)SIM900_Buff);                                      //发送读取短信命令  
  882.         error = SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20);                      //等待返回  
  883.         if(error == AT_RETURN_OK)  
  884.         {  
  885.             GSM_ParseTextSMS((char *)SIM900_Buff, pSMS, cnt, pInfo);                //解析TEXT格式短信  
  886.         }  
  887.     }  
  888.     SIM900_SendATcom("AT+CMGF=0");  //配置短信为PDU格式  
  889.     error = SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20);  
  890.       
  891.     return error;  
  892. }  
  893.   
  894.   
  895.   
  896.   
  897. /************************************************************************************************************************* 
  898. *函数         :   u32 GSM_ParseTextSMS(char *pText, char *pSMS, u32 TextSize, SMS_INFO *pInfo) 
  899. *功能         :   解析一条TEXT格式短信 
  900. *参数         :   pText:短信TEXT数据缓冲区指针 
  901. *                   pSMS:解析后的短信缓冲区指针 
  902.                     TextSize:数据大小 
  903. *                   pInfo:短信信息指针 
  904. *返回         :   TRUE:成功;FALSE:失败 
  905. *依赖         :   无 
  906. *作者         :   cp1300@139.com 
  907. *时间         :   2013-04-30 
  908. *最后修改时间 :   2013-04-30 
  909. *说明         :   需要先切换到TEXT格式,用于解析TEXT格式短信,之后会切换回PDU格式 
  910.                     需要先解析为PDU后才知道是否为TEXT格式短信 
  911. *************************************************************************************************************************/  
  912. bool GSM_ParseTextSMS(char *pText, char *pSMS, u32 TextSize, SMS_INFO *pInfo)  
  913. {  
  914.     u16 cnt = 0;  
  915. //  u16 temp;  
  916.     char *p;  
  917. //  u16 SMS_Size;  
  918.       
  919.     pText[TextSize] = '\0';                     //添加结束符  
  920.     p = strstr((const char*)pText, "+CMGR:");  
  921.     p = strstr((const char*)p, "\r\n"); //寻找短信TEXT开始位置  
  922.       
  923.     cnt = ((u32)p - (u32)pText) + 2;        //找到短信TEXT开始的位置了  
  924.     if(p == NULL || cnt >= TextSize)  
  925.     {  
  926.         SIM900_debug("TEXT短信解析错误!\r\n");  
  927.         return FALSE;  
  928.     }  
  929.     p +=2;  //跳到短信开始位置  
  930.     for(cnt = 0;cnt < pInfo->SMS_Size;cnt ++) //复制短信  
  931.     {  
  932.         pSMS[cnt] = p[cnt];  
  933.     }  
  934.     pSMS[pInfo->SMS_Size] = 0;                   //添加结束符  
  935.       
  936.     return TRUE;  
  937. }  
  938.   
  939.   
  940.   
  941.   
  942.   
  943.   
  944.   
  945.   
  946.   
  947.   
  948.   
  949.   
  950.   
  951.   
  952.   
  953. /************************************************************************************************************************* 
  954. *函数         :   static u8 PhoneNumtoPDUChar(u8 *pNum, char *pCHAR,u8 NumLen) 
  955. *功能         :   将电话号码字符转换为PDU要求的字符 
  956. *参数         :   pNum:电话号码指针 
  957. *                   pChar:字符缓冲区指针 
  958. *                   NumLen:电话号码长度 
  959. *返回         :   字符长度 
  960. *依赖         :   底层宏定义 
  961. *作者         :   cp1300@139.com 
  962. *时间         :   2013-04-04 
  963. *最后修改时间 :   2013-10-17 
  964. *说明         :   主要用于电话号码,短信中心号码转换 
  965. *                   如果长度为奇数,则将补成偶数,并在最后一个字符的高位保留位0xf; 
  966. *                   本函数不添加结束符 
  967. *************************************************************************************************************************/  
  968. static u8 PhoneNumtoPDUChar(u8 *pNum, char *pChar,u8 NumLen)  
  969. {  
  970.     u8 i;  
  971.     u8 temp;  
  972.   
  973.     for(i = 0;i < NumLen;i ++)  
  974.     {  
  975.         temp = (pNum[i]+'0') & 0x0f;  
  976.         if(i % 2)   //位数为奇数  
  977.             pChar[i-1] = (temp > 9) ? ('a' + temp - 10) :( temp + '0');  
  978.         else        //位数为偶数  
  979.             pChar[i+1] = (temp > 9) ? ('a' + temp - 10) : (temp + '0');    
  980.     }  
  981.     if(i % 2)  
  982.     {  
  983.         pChar[NumLen-1] = 'F';  
  984.         return (NumLen + 1);  
  985.     }  
  986.       
  987.     return NumLen;  
  988. }  
  989.   
  990.   
  991.   
  992. /************************************************************************************************************************* 
  993. *函数         :   static u8 ChartoPhoneNum(char *pChar, char *pNum, u8 CharLen) 
  994. *功能         :   将字符转换为电话号码 
  995. *参数         :   pCHAR:字符缓冲区指针 
  996. *                   pNum:电话号码指针 
  997. *                   charLen:字符号码长度 
  998. *返回         :   电话长度 
  999. *依赖         :   底层宏定义 
  1000. *作者         :   cp1300@139.com 
  1001. *时间         :   2013-04-04 
  1002. *最后修改时间 :   2013-10-17 
  1003. *说明         :   主要用于电话号码,短信中心号码转换 
  1004. *                   如果电话长度为奇数,则将补成偶数,并在最后一个字符的高位保留位0xf; 
  1005. *                   转换后为字符 
  1006. *************************************************************************************************************************/  
  1007. static u8 ChartoPhoneNum(char *pChar, char *pNum, u8 CharLen)  
  1008. {  
  1009.     u32 i;  
  1010.     u8 temp;  
  1011.   
  1012.     for(i = 0;i < CharLen;i ++)  
  1013.     {  
  1014.         temp = pChar[i];  
  1015.         if(temp == 'F'//还有一位就结束了  
  1016.         {  
  1017.             pNum[i] =   pChar[i+1];   
  1018.             return i + 1;  
  1019.         }  
  1020.         else if(temp > '9')  //非数字  
  1021.         {  
  1022.             return 0;   //电话号码格式错误  
  1023.         }  
  1024.            
  1025.         else if(i % 2)  //位数为奇数  
  1026.             pNum[i-1] =  temp;  
  1027.         else    //位数为偶数  
  1028.             pNum[i+1] = temp;     
  1029.     }  
  1030.     return i;  
  1031. }  
  1032.   
  1033.   
  1034.   
  1035. /************************************************************************************************************************* 
  1036. *函数         :   static u32 StringToUnicodeStr(char *pStr, char *pucode,u32 SrtLen) 
  1037. *功能         :   将字符串转换为unicode,并存储为16进制样式的字符串 
  1038. *参数         :   pStr:字符缓冲区指针 
  1039. *                   pucode:转换结果缓冲区 
  1040. *                   SrtLen:字符串字节长度 
  1041. *返回         :   转换成为字符后的长度 
  1042. *依赖         :   u16 OneGBKtoUNICODE(u16 GBKCode) 
  1043. *作者         :   cp1300@139.com 
  1044. *时间         :   2013-04-04 
  1045. *最后修改时间 :   2013-10-17 
  1046. *说明         :   用于将短信内容转换为PUD格式,本函数不添加字符串结束符 
  1047. *                   如"a,b,c"--->"0,0,6,1,0,0,6,2,0,0,6,3" 
  1048. *                   输出缓冲区至少为输入的4倍 
  1049. *************************************************************************************************************************/  
  1050. static u32 StringToUnicodeStr(char *pStr, char *pucode,u32 SrtLen)  
  1051. {  
  1052.     u32 i;  
  1053.     u16 temp;  
  1054.     u8 m;  
  1055.     u8 chTmp= 0;  
  1056.     u32 cnt = 0;  
  1057.       
  1058.     for(i = 0;i < SrtLen;i ++)  
  1059.     {  
  1060.         if(pStr[i] < 0x80)   //ASCII  
  1061.         {  
  1062.             temp = pStr[i];  
  1063.         }  
  1064.         else                //GBK  
  1065.         {  
  1066.             temp = pStr[i ++]<< 8;  
  1067.             temp |= pStr[i];  
  1068.             temp = OneGBKtoUNICODE(temp);  
  1069.         }  
  1070.   
  1071.         for(m = 0; m <= 12; m+=4)  
  1072.         {  
  1073.           chTmp = (temp >> (12-m)) & 0x0F;            //先取高位  
  1074.           if(chTmp > 0x09)   //! 0x0A-0x0F  
  1075.               pucode[cnt ++] = chTmp-0x0A+'A';       //! 'A'-'F'  
  1076.           else                                 //! 0x00-0x09  
  1077.               pucode[cnt ++] = chTmp-0x00+'0';       //! '0'-'9'  
  1078.         }  
  1079.     }  
  1080.     return cnt;  
  1081. }  
  1082.   
  1083.   
  1084.   
  1085. /************************************************************************************************************************* 
  1086. *函数         :   u32 UnicodeStrToString(u8 *pucode,char *pStr,u32 SrtLen) 
  1087. *功能         :   将字符unicode转换为字符串 
  1088. *参数         :   pucode:转换结果缓冲区 
  1089. *                   pStr:字符缓冲区指针 
  1090. *                   SrtLen:字符串字节长度 
  1091. *返回         :   转换成为字符后的长度 
  1092. *依赖         :   u16 OneUNICODEtoGBK(u16 unicode); 
  1093. *作者         :   cp1300@139.com 
  1094. *时间         :   2013-04-04 
  1095. *最后修改时间 :   2013-10-26 
  1096. *说明         :   用于将PUD格式短信解析,本函数不添加字符串结束符 
  1097.                     2013-10-26:解决短信中句号无法解析 
  1098. *************************************************************************************************************************/  
  1099. static u32 UnicodeStrToString(u8 *pucode,char *pStr,u32 SrtLen)  
  1100. {  
  1101.     u32 i;  
  1102.     u16 temp;  
  1103.     u32 cnt = 0;  
  1104.     u8 H,L;  
  1105.   
  1106.     for(i = 0;i < SrtLen;i+=4)  
  1107.     {  
  1108.         if(pucode[i] == '0')    //0  
  1109.         {  
  1110.             H = pucode[i+2];  
  1111.             L = pucode[i+3];  
  1112.             H = (H > '9') ? H - 'A' + 10 : H - '0';  
  1113.             L = (L > '9') ? L - 'A' + 10 : L - '0';    
  1114.             pStr[cnt++] = (H << 4) + L;     
  1115.         }  
  1116.         else  
  1117.         {  
  1118.             H = pucode[i];  
  1119.             L = pucode[i+1];  
  1120.             H = (H > '9') ? H - 'A' + 10 : H - '0';  
  1121.             L = (L > '9') ? L - 'A' + 10 : L - '0';    
  1122.             temp = (H << 4) + L;  
  1123.             temp <<= 8;  
  1124.             H = pucode[i+2];  
  1125.             L = pucode[i+3];  
  1126.             H = (H > '9') ? H - 'A' + 10 : H - '0';  
  1127.             L = (L > '9') ? L - 'A' + 10 : L - '0';    
  1128.             temp |= (H << 4) + L;  
  1129.             //lcd_printf("temp1 = 0x%04X\r\n",temp);  
  1130.             switch(temp)  
  1131.             {  
  1132.                 case 0x3002:    //句号无法显示,转换为GBK编码句号  
  1133.                     temp = 0xA1A3;break;//'。';  break;  
  1134.                 default :   
  1135.                     temp = OneUNICODEtoGBK(temp);break//编码转换  
  1136.             }  
  1137.             //lcd_printf("temp2 = 0x%04X\r\n",temp);  
  1138.             pStr[cnt++] = temp >> 8 ;  
  1139.             pStr[cnt++] = temp & 0xff;  
  1140.         }  
  1141.     }  
  1142.     return cnt;  
  1143. }  
  1144.   
  1145.   
  1146.   
  1147. /************************************************************************************************************************* 
  1148. *函数         :   u32 GSM_StringToHex(char *pStr, u8 NumDigits) 
  1149. *功能         :   将16进制样式字符串转换为16进制整型数(必须保证字符串字母都是大写) 
  1150. *参数         :   pStr:字符串起始指针 
  1151. *                   NumDigits:数字位数,16进制数字位数 
  1152. *返回         :   转换后的数字 
  1153. *依赖         :   无 
  1154. *作者         :   cp1300@139.com 
  1155. *时间         :   2013-04-30 
  1156. *最后修改时间 :   2013-10-17 
  1157. *说明         :   比如字符串"A865"转换后为0xA865,位数为4位 
  1158.                     必须保证字符串字母都是大写 
  1159. *************************************************************************************************************************/  
  1160. static u32 GSM_StringToHex(char *pStr, u8 NumDigits)  
  1161. {  
  1162.     u8 temp;  
  1163.     u32 HEX = 0;  
  1164.     u8 i;  
  1165.       
  1166.     NumDigits = (NumDigits > 8) ? 8 : NumDigits; //最大支持8位16进制数  
  1167.       
  1168.     for(i = 0;i < NumDigits;i ++)  
  1169.     {  
  1170.         HEX <<= 4;  
  1171.         temp = pStr[i];  
  1172.         temp = (temp > '9') ? temp - 'A' + 10 : temp - '0';  
  1173.         HEX |= temp;  
  1174.     }  
  1175.     return HEX;  
  1176. }  
  1177.   
  1178.   
  1179.   
  1180. /************************************************************************************************************************* 
  1181. *函数         :   void GSM_HexToString(u32 HexNum,c har *pStr, u8 NumDigits) 
  1182. *功能         :   将整型数字转换为16进制样式字符串(字母为大写,不带结束符) 
  1183. *参数         :   HexNum:16进制数字 
  1184.                     pStr:字符缓冲区指针 
  1185. *                   NumDigits:数字位数,16进制数字位数 
  1186. *返回         :   无 
  1187. *依赖         :   无 
  1188. *作者         :   cp1300@139.com 
  1189. *时间         :   2013-04-30 
  1190. *最后修改时间 :   2013-04-30 
  1191. *说明         :   比如字符串0xA865转换后为"A865",位数为4位 
  1192. *************************************************************************************************************************/  
  1193. static void GSM_HexToString(u32 HexNum,char *pStr, u8 NumDigits)  
  1194. {  
  1195.     u8 temp;  
  1196.     u8 i;  
  1197.       
  1198.     NumDigits = (NumDigits > 8) ? 8 : NumDigits; //最大支持8位16进制数  
  1199.       
  1200.     for(i = 0;i < NumDigits;i ++)  
  1201.     {  
  1202.         temp = 0x0f & (HexNum >> (4 * (NumDigits - 1 - i)));  
  1203.         temp = (temp > 0x09) ? (temp - 0x0A + 'A') : (temp + '0');  
  1204.         pStr[i] = temp;  
  1205.     }  
  1206. }  
  1207.   
  1208.   
  1209.   
  1210.   
  1211. /************************************************************************************************************************* 
  1212. *函数         :   u32 GSM_StringToDec(char *pStr, u8 NumDigits) 
  1213. *功能         :   将10进制样式字符串转换为整型数(必须保证完全为数字字符) 
  1214. *参数         :   pStr:字符串起始指针 
  1215. *                   NumDigits:数字位数,10进制数字位数 
  1216. *返回         :   转换后的数字 
  1217. *依赖         :   无 
  1218. *作者         :   cp1300@139.com 
  1219. *时间         :   2013-04-30 
  1220. *最后修改时间 :   2013-04-30 
  1221. *说明         :   比如字符串"1865"转换后为1865,位数为4位 
  1222.                     必须保证完全为数字字符 
  1223. *************************************************************************************************************************/  
  1224. u32 GSM_StringToDec(char *pStr, u8 NumDigits)  
  1225. {  
  1226.     u32 temp;  
  1227.     u32 DEC = 0;  
  1228.     u8 i;  
  1229.     u8 j;  
  1230.       
  1231.     NumDigits = (NumDigits > 10) ? 10 : NumDigits;   //最大支持10位10进制数  
  1232.       
  1233.     for(i = 0;i < NumDigits;i ++)  
  1234.     {  
  1235.         temp = pStr[i] - '0';  
  1236.         if(temp > 9)         //只能是数字范围  
  1237.             return 0;  
  1238.         for(j = 1;j < (NumDigits - i);j ++)  
  1239.         {  
  1240.             temp *= 10;  
  1241.         }  
  1242.         DEC += temp;  
  1243.     }  
  1244.     return DEC;  
  1245. }  
  1246.   
  1247.   
  1248.   
  1249. /************************************************************************************************************************* 
  1250. * 函数            :   SIM900_CALLS SIM900_TestCallStatus(void) 
  1251. * 功能            :   SIM900 通话状态检测 
  1252. * 参数            :   retry:重试次数 
  1253. * 返回            :   FALSE:通信失败;TRUE:通信成功 
  1254. * 依赖            :   底层 
  1255. * 作者            :   cp1300@139.com 
  1256. * 时间            :   2013-10-20 
  1257. * 最后修改时间    :   2013-10-20 
  1258. * 说明            :   每隔20ms向SIM900发送一个"AT",等待响应返回 
  1259. *************************************************************************************************************************/  
  1260. SIM900_CALLS SIM900_TestCallStatus(void)  
  1261. {  
  1262.     u32 cnt;  
  1263.     u8 retry = SIM900_RETRY;  
  1264.     char *p;  
  1265.   
  1266.       
  1267.     do  
  1268.     {  
  1269.         if(SIM900_TestAT(10) == FALSE)  //串口同步失败  
  1270.         {  
  1271.             SIM900_WaitSleep(1000); //等待上一个操作完成  
  1272.         }  
  1273.         SIM900_SendATcom("AT+CPAS");                              
  1274.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))       //等待响应,超时200ms  
  1275.         {  
  1276.             p = strstr((const char*)SIM900_Buff, "+CPAS:");                     //搜索字符"+CPAS"  
  1277.             if(p != NULL)                 
  1278.             {     
  1279.                 cnt = GSM_StringToDec(p + 7, 1);                                //获取状态编码  
  1280.                 if(cnt > SIM900_CALL_CENTER)  
  1281.                     return SIM900_CALL_ERROR;  
  1282.                 else return (SIM900_CALLS)cnt;  
  1283.             }  
  1284.         }  
  1285.         SIM900_Ready(); //等待就绪  
  1286.         retry --;  
  1287.     }while(retry);  
  1288.       
  1289.     return SIM900_CALL_ERROR;  
  1290. }  
  1291.   
  1292. /************************************************************************************************************************* 
  1293. * 函数            :   bool SIM900_HangUp(void) 
  1294. * 功能            :   SIM900 挂掉电话 
  1295. * 参数            :   无 
  1296. * 返回            :   FALSE:通信失败;TRUE:通信成功 
  1297. * 依赖            :   底层 
  1298. * 作者            :   cp1300@139.com 
  1299. * 时间            :   2013-10-20 
  1300. * 最后修改时间    :   2013-10-20 
  1301. * 说明            :    
  1302. *************************************************************************************************************************/  
  1303. bool SIM900_HangUp(void)  
  1304. {  
  1305.     u32 cnt;  
  1306.     u8 retry = SIM900_RETRY;  
  1307.   
  1308.     //检测模块存在  
  1309.     do  
  1310.     {  
  1311.         if(SIM900_TestAT(10) == FALSE)  //串口同步失败  
  1312.         {  
  1313.             SIM900_WaitSleep(1000); //等待上一个操作完成  
  1314.         }  
  1315.         SIM900_SendATcom("ATH");            //挂机                                              
  1316.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))   //等待响应,超时200ms  
  1317.         {  
  1318.             return TRUE;  
  1319.         }  
  1320.         SIM900_Ready(); //等待就绪  
  1321.         retry --;  
  1322.     }while(retry);  
  1323.       
  1324.     return FALSE;  
  1325. }  
  1326.   
  1327.   
  1328.   
  1329.   
  1330. /************************************************************************************************************************* 
  1331. * 函数            :   bool SIM900_GetServeNumber(PHONE_NUMBER *pServeNumber) 
  1332. * 功能            :   获取短信服务中心号码 
  1333. * 参数            :   pServeNumber:电话号码存储缓冲区指针 
  1334. * 返回            :   FALSE:通信失败;TRUE:通信成功 
  1335. * 依赖            :   底层 
  1336. * 作者            :   cp1300@139.com 
  1337. * 时间            :   2013-10-20 
  1338. * 最后修改时间    :   2013-10-20 
  1339. * 说明            :   获取SIM卡内部的短信服务中心号码,一般在办理SIM卡的时候已经进行了设置. 
  1340.                     如果没有预置短信中心号码需要使用手机进行设置 
  1341. *************************************************************************************************************************/  
  1342. bool SIM900_GetServeNumber(PHONE_NUMBER *pServeNumber)  
  1343. {  
  1344.     u8 n;  
  1345.     u32 cnt;  
  1346.     char *p,*p1;  
  1347.     u8 retry = SIM900_RETRY;        //重试次数  
  1348.       
  1349.     do  
  1350.     {     
  1351.         if(SIM900_TestAT(10) == FALSE)  //串口同步失败  
  1352.         {  
  1353.             SIM900_WaitSleep(1000); //等待上一个操作完成  
  1354.         }  
  1355.         //+CSCA: "+8613800270500",145  
  1356.         SIM900_SendATcom("AT+CSCA?");           //发送"AT+CSCA",获取短信服务中心号码  
  1357.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))   //等待响应,超时200MS  
  1358.         {  
  1359.             p = strstr((const char*)SIM900_Buff, "+CSCA:");         //搜索字符"+CSCA:"  
  1360.             if(p != NULL)                                           //搜索成功  
  1361.             {  
  1362.                 p = strstr(p+1, "+");   //搜索"+"  
  1363.                 if(p != NULL)  
  1364.                 {  
  1365.                     p1 = strstr(p+1, "\""); //搜索"\""  
  1366.                     if(p1 != NULL)            
  1367.                     {  
  1368.                         n = p1 - (p+1); //计算电话号码长度  
  1369.                         pServeNumber->PhoneNumLen = (n > PHONE_NUMBER_MAX_LEN) ? PHONE_NUMBER_MAX_LEN : n;    //存储短信服务中心号码长度  
  1370.                         p ++;                   //跳过前面的"+"  
  1371.                         for(n = 0;n < pServeNumber->PhoneNumLen;n ++)  
  1372.                         {  
  1373.                             pServeNumber->PhoneNumBuff[n] = p[n];    //复制电话号码  
  1374.                         }  
  1375.                         pServeNumber->PhoneNumBuff[n] = '\0';        //添加结束符  
  1376.                         SIM900_debug("短信中心号码:%s(长度:%d)\r\n",pServeNumber->PhoneNumBuff,pServeNumber->PhoneNumLen);  
  1377.                         return TRUE;  
  1378.                     }  
  1379.                 }  
  1380.             }  
  1381.             break;  
  1382.         }  
  1383.         SIM900_Ready(); //等待就绪  
  1384.         retry --;  
  1385.     }while(retry);  
  1386.       
  1387.     return FALSE;  
  1388. }  
  1389.   
  1390.   
  1391.   
  1392. /************************************************************************************************************************* 
  1393. * 函数            :   bool SIM900_GetPhoneNumber(PHONE_NUMBER *pPhoneNumber) 
  1394. * 功能            :   获取本机号码 
  1395. * 参数            :   CenterPhone:电话号码存储缓冲区指针 
  1396. * 返回            :   FALSE:通信失败;TRUE:通信成功 
  1397. * 依赖            :   底层 
  1398. * 作者            :   cp1300@139.com 
  1399. * 时间            :   2013-10-20 
  1400. * 最后修改时间    :   2013-10-20 
  1401. * 说明            :   通常会预存本机号码到SIM卡,也可能没有 
  1402. *************************************************************************************************************************/  
  1403. bool SIM900_GetPhoneNumber(PHONE_NUMBER *pPhoneNumber)  
  1404. {  
  1405.     u8 n;  
  1406.     u32 cnt;  
  1407.     char *p,*p1;  
  1408.     u8 retry = SIM900_RETRY;        //重试次数  
  1409.       
  1410.     do  
  1411.     {     
  1412.         if(SIM900_TestAT(10) == FALSE)  //串口同步失败  
  1413.         {  
  1414.             SIM900_WaitSleep(1000); //等待上一个操作完成  
  1415.         }  
  1416.         //+CNUM: "","15871750634",129,7,4  
  1417.         SIM900_SendATcom("AT+CNUM");                                        //发送"AT++CNUM",获取号码  
  1418.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))   //等待响应,超时200MS  
  1419.         {  
  1420.             p = strstr((const char*)SIM900_Buff, "+CNUM:");                 //搜索字符"+CNUM:"  
  1421.             if(p != NULL)                                                   //搜索成功  
  1422.             {  
  1423.                 p = strstr(p+1, "\",\"");   //搜索"",""  
  1424.                 if(p != NULL)  
  1425.                 {  
  1426.                     p1 = strstr(p+3, "\",");    //搜索"","  
  1427.                     if(p1 != NULL)            
  1428.                     {  
  1429.                         n = p1 - (p+3);         //计算电话号码长度  
  1430.                         pPhoneNumber->PhoneNumLen = (n > PHONE_NUMBER_MAX_LEN) ? PHONE_NUMBER_MAX_LEN : n;    //存储号码长度  
  1431.                         p +=3;                  //跳过前面的"\",\""  
  1432.                         for(n = 0;n < pPhoneNumber->PhoneNumLen;n ++)  
  1433.                         {  
  1434.                             pPhoneNumber->PhoneNumBuff[n] = p[n];    //复制电话号码  
  1435.                         }  
  1436.                         pPhoneNumber->PhoneNumBuff[n] = '\0';        //添加结束符  
  1437.                         SIM900_debug("本机号码:%s(长度:%d)\r\n",pPhoneNumber->PhoneNumBuff,pPhoneNumber->PhoneNumLen);  
  1438.                         return TRUE;  
  1439.                     }  
  1440.                 }  
  1441.             }  
  1442.             break;  
  1443.         }  
  1444.         SIM900_Ready(); //等待就绪  
  1445.         retry --;  
  1446.     }while(retry);  
  1447.       
  1448.     return FALSE;  
  1449. }  
  1450.   
  1451.   
  1452.   
  1453. /************************************************************************************************************************* 
  1454. * 函数                :   int SIM900_GetSignal(void) 
  1455. * 功能                :   获取信号强度 
  1456. * 参数                :   无 
  1457. * 返回                :   <0:获取失败;0-31:信号强度; 
  1458. * 依赖                :   底层 
  1459. * 作者                :   cp1300@139.com 
  1460. * 时间                :   2013-10-21 
  1461. * 最后修改时间    :   2013-10-21 
  1462. * 说明                :   无 
  1463. *************************************************************************************************************************/  
  1464. int SIM900_GetSignal(void)  
  1465. {  
  1466.     u8 temp;  
  1467.     u32 cnt;  
  1468.     char *p;  
  1469.     u8 retry = SIM900_RETRY;        //重试次数  
  1470.       
  1471.     do  
  1472.     {     
  1473.         if(SIM900_TestAT(10) == FALSE)  //串口同步失败  
  1474.         {  
  1475.             SIM900_WaitSleep(1000); //等待上一个操作完成  
  1476.         }  
  1477.         //+CSQ: 27,0  
  1478.         //+CSQ: 5,0  
  1479.         SIM900_SendATcom("AT+CSQ");                                         //发送"AT++CSQ",获取号码  
  1480.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))   //等待响应,超时200MS  
  1481.         {  
  1482.             p = strstr((const char*)SIM900_Buff, "+CSQ:");                  //搜索字符"+CSQ:"  
  1483.             if(p != NULL)                                                   //搜索成功  
  1484.             {  
  1485.                 if(p[7] == ','//信号强度为1位数  
  1486.                 {  
  1487.                     temp = GSM_StringToDec(&p[6], 1);  
  1488.                 }  
  1489.                 else  
  1490.                 {  
  1491.                     temp = GSM_StringToDec(&p[6], 2);  
  1492.                 }  
  1493.                   
  1494.                 return temp;  
  1495.             }  
  1496.             break;  
  1497.         }  
  1498.         SIM900_Ready(); //等待就绪  
  1499.         retry --;  
  1500.     }while(retry);  
  1501.       
  1502.     return -1;  
  1503. }  
  1504.   
  1505.   
  1506.   
  1507.   
  1508. /************************************************************************************************************************* 
  1509. * 函数                :   SIM900_NETSTATUS SIM900_GetNetworkStatus(void) 
  1510. * 功能                :   获取网络注册状态 
  1511. * 参数                :   无 
  1512. * 返回                :   SIM900_NETSTATUS 
  1513. * 依赖                :   底层 
  1514. * 作者                :   cp1300@139.com 
  1515. * 时间                :   2013-10-29 
  1516. * 最后修改时间    :   2013-10-29 
  1517. * 说明                :   无 
  1518. *************************************************************************************************************************/  
  1519. SIM900_NETSTATUS SIM900_GetNetworkStatus(void)  
  1520. {  
  1521.     u32 cnt;  
  1522.     char *p;  
  1523.     u8 retry = SIM900_RETRY;        //重试次数  
  1524.       
  1525.     do  
  1526.     {     
  1527.         if(SIM900_TestAT(10) == FALSE)  //串口同步失败  
  1528.         {  
  1529.             SIM900_WaitSleep(1000); //等待上一个操作完成  
  1530.         }  
  1531.         //+CREG: 0,1  
  1532.         SIM900_SendATcom("AT+CREG?");                                           //发送"AT+CREG?",获取网络注册状态  
  1533.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))   //等待响应,超时200MS  
  1534.         {  
  1535.             p = strstr((const char*)SIM900_Buff, "+CREG:");                 //搜索字符"+CSQ:"  
  1536.             if(p != NULL)                                                   //搜索成功  
  1537.             {  
  1538.                 return (SIM900_NETSTATUS)GSM_StringToDec(&p[9], 1);  
  1539.             }  
  1540.             break;  
  1541.         }  
  1542.         SIM900_Ready(); //等待就绪  
  1543.         retry --;  
  1544.     }while(retry);  
  1545.       
  1546.     return SIM900_NET_ERROR;  
  1547. }  
  1548.   
  1549.   
  1550.   
  1551.   
  1552. //PDU模式短信限制长度,最大70个字符,不分中英文  
  1553. //返回:限制之后的字符个数  
  1554. u32 GSM_PDUStrRes(char *pStr)  
  1555. {  
  1556.     u32 n = 0;  
  1557.   
  1558.     while(*pStr != 0)  
  1559.     {  
  1560.         n ++;  
  1561.         if(n == 71)  
  1562.         {  
  1563.             SIM900_debug("PDU模式短信长度超出70B,强制为70B!\r\n");  
  1564.             *pStr = 0;      //强制添加结束符  
  1565.             return n;  
  1566.         }  
  1567.         if((u8)*pStr < 0x80) //ASCII  
  1568.         {  
  1569.             pStr ++;  
  1570.         }  
  1571.         else if((u8)*pStr > 0x80)    //中文  
  1572.         {             
  1573.             pStr += 2;  
  1574.         }  
  1575.           
  1576.     }  
  1577.       
  1578.     return n;  
  1579. }  
  1580.   
  1581.   
  1582.   
  1583. //发送一条短信  
  1584. //短信电话号码长度按照字节算但是短信中心号码按照半字节算  
  1585. //0891683108100005F0 1100 0D 91685156525310F30008AA0C 9E3F9E4475355B5079D16280  
  1586. /************************************************************************************************************************* 
  1587. *函数         :   bool GSM_SendOneSMS(char *pSMS, u8 *pPDU, char *pServeNumber, char *pPhoneNumber) 
  1588. *功能         :   发送一条普通短信,正常长度 
  1589. *参数         :   pSMS:短信内容缓冲区指针,内容为文本文档,并且字符串需要结束符 
  1590. *                   pPDU:PDU数据缓冲区指针 
  1591.                     pServeNumber:短信中心号码 
  1592.                     pPhoneNumber:目标手机号码结构指针 
  1593. *返回         :   TRUE:短信发送成功;FALSE:短信发送失败 
  1594. *依赖         :   底层 
  1595. *作者         :   cp1300@139.com 
  1596. *时间         :   2013-04-04 
  1597. *最后修改时间 :   201310-23 
  1598. *说明         :   短信文本需要添加结束符 
  1599.                     电话号码必须以86等国际区号开头 
  1600.                     PDU可以发送中文,但是text只能发送英文 
  1601. *************************************************************************************************************************/  
  1602. bool GSM_SendOneSMS(char *pSMS, u8 *pPDU, char *pServeNumber, char *pPhoneNumber)  
  1603. {  
  1604.     SIM900_ERROR error;  
  1605.     u16 OffsetCnt = 0;      //缓冲区偏移计数器  
  1606.     u32 cnt;  
  1607.     u16 temp;  
  1608.     char ComBuff[16];  
  1609.     u16  nSMSCenterLen= 0, nSMSPduLen = 0;  
  1610.     u16 SMSLen = 0;         //短信字符长度  
  1611.     FunctionalState EnableU2S = DISABLE;    //使能U2S编码模式,默认为7BIT编码模式  
  1612.     u8 *p = (u8 *)pSMS;  
  1613.       
  1614.     while(*p != 0)  
  1615.     {  
  1616.         if(*p >= 0x80)       //有汉字  
  1617.         {  
  1618.             EnableU2S = ENABLE; //使能U2S编码模式  
  1619.             SIM900_debug("需要发送的短信为PDU格式\r\n");  
  1620.             break;  
  1621.         }  
  1622.         p ++;  
  1623.     }  
  1624.       
  1625.                   
  1626.     if(EnableU2S == ENABLE)         //使能了U2S编码模式  
  1627.     {  
  1628.         SMSLen = GSM_PDUStrRes(pSMS);   //限制PDU短信长度,计算短信长度  
  1629.     }  
  1630.     else                            //TEXT模式短信  
  1631.     {  
  1632.         SMSLen = strlen(pSMS);      //计算短信长度  
  1633.         if(SMSLen > 160)     //短信长度大于160个字符  
  1634.         {  
  1635.             pSMS[160] = 0;          //添加结束符,限制长度  
  1636.             SMSLen = 160;  
  1637.         }  
  1638.     }  
  1639.       
  1640.     //计算短信中心号码长度,+91,+86,短信中心号码必须由86开头,并且要加上91,长度为每个数字半字节,不足补F  
  1641.     temp = (strlen(pServeNumber) + 2 + 1) / 2;    
  1642.     GSM_HexToString(temp, (char *)(pPDU+OffsetCnt), 2); //短信中心号码长度转换为16进制样式字符串  
  1643.     OffsetCnt += 2;                                     //跳过短信中心号码长度字节  
  1644.       
  1645.     pPDU[OffsetCnt++] = '9';    //服务中心类型  
  1646.     pPDU[OffsetCnt++] = '1';  
  1647.     OffsetCnt += PhoneNumtoPDUChar((u8 *)pServeNumber,(char *)(pPDU+OffsetCnt),strlen(pServeNumber));   //短信中心号码  
  1648.     nSMSCenterLen = OffsetCnt / 2;  
  1649.     //! PDU  
  1650.     pPDU[OffsetCnt++] = '1';  
  1651.     pPDU[OffsetCnt++] = '1';  
  1652.     //! For MR  
  1653.     pPDU[OffsetCnt++] = '0';  
  1654.     pPDU[OffsetCnt++] = '0';  
  1655.     //! For DA  
  1656.       
  1657.     //计算电话号码长度,+86,发送短信的电话号码由86开头,电话号码长度为字符个数  
  1658.     GSM_HexToString(strlen(pPhoneNumber), (char *)(pPDU+OffsetCnt), 2); //手机号码长度转换为16进制样式字符串  
  1659.     OffsetCnt += 2; //跳过手机号码长度字节  
  1660.       
  1661.     pPDU[OffsetCnt++] = '9';    //服务中心类型  
  1662.     pPDU[OffsetCnt++] = '1';  
  1663.     OffsetCnt += PhoneNumtoPDUChar((u8 *)pPhoneNumber,(char *)(pPDU+OffsetCnt),strlen(pPhoneNumber));   //短信发送号码  
  1664.     //! For PID  
  1665.     pPDU[OffsetCnt++] = '0';  
  1666.     pPDU[OffsetCnt++] = '0';  
  1667.     //! For DCS  
  1668.     if(EnableU2S == ENABLE)         //U2S  
  1669.     {  
  1670.         pPDU[OffsetCnt++] = '0';  
  1671.         pPDU[OffsetCnt++] = '8';  
  1672.     }  
  1673.     else                            //7BIT  
  1674.     {  
  1675.         pPDU[OffsetCnt++] = '0';  
  1676.         pPDU[OffsetCnt++] = '0';  
  1677.     }  
  1678.       
  1679.     //! For VP  
  1680.     pPDU[OffsetCnt++] = 'A';  
  1681.     pPDU[OffsetCnt++] = 'A';  
  1682.       
  1683.     //! For UDL AND UD  
  1684.       //! 注意,此处先将用户数据长度设置为00,并  
  1685.       //! 记录此时的缓冲区位置,然后等编码完成,   
  1686.       //! 确定了用户数据长度后再修改为实际长度  
  1687.       cnt = OffsetCnt;  
  1688.       pPDU[OffsetCnt++] = '0';  
  1689.       pPDU[OffsetCnt++] = '0';    
  1690.       
  1691.     //短信内容  
  1692.     if(EnableU2S == ENABLE)         //U2S  
  1693.     {  
  1694.         temp = StringToUnicodeStr(pSMS,(char *)&pPDU[OffsetCnt], strlen(pSMS));//将短信数据转换为字符数据  
  1695.         OffsetCnt += temp;  
  1696.         GSM_HexToString(temp/2, (char *)&pPDU[cnt], 2);  
  1697.         //! PDU串的长度,后面AT+CMGS要用到此长度  
  1698.         nSMSPduLen = OffsetCnt / 2 -nSMSCenterLen;  
  1699.     }  
  1700.     else                            //7bit  
  1701.     {  
  1702.         u8 buff[140];               //TEXT短信缓冲区  
  1703.           
  1704.         temp = gsmEncode7bit(pSMS, buff);                       //将ASCII转换为7bit编码  
  1705.         GSM_HexToString(SMSLen, (char *)&pPDU[cnt], 2);  
  1706.           
  1707.         for(cnt = 0;cnt < temp;cnt ++)  
  1708.         {  
  1709.             GSM_HexToString(buff[cnt], (char *)&pPDU[OffsetCnt+cnt*2], 2);  //7bit编码转换为16进制格式字符串  
  1710.         }  
  1711.         OffsetCnt += (temp << 1);  
  1712.         //! PDU串的长度,后面AT+CMGS要用到此长度  
  1713.         nSMSPduLen = OffsetCnt / 2 -nSMSCenterLen;  
  1714.     }  
  1715.       
  1716.                         //短信内容长度转换为16进制样式字符串,存储短信长度  
  1717.       
  1718.     //end  
  1719.     pPDU[OffsetCnt++] = 0x1A;  
  1720.     pPDU[OffsetCnt++] = 0x00;  
  1721.       
  1722.     SIM900_debug("\r\n%s\r\n",pPDU);  
  1723.       
  1724.     //! 下面是发送过程  
  1725.     //! AT  
  1726.     if(SIM900_TestAT(10) == FALSE)  //串口同步失败  
  1727.     {  
  1728.         SIM900_WaitSleep(1000); //等待上一个操作完成  
  1729.     }  
  1730.   
  1731.     //! ATE0  
  1732.     SIM900_SendATcom("ATE0");  
  1733.     if(AT_RETURN_OK != SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))   //等待响应,超时200MS  
  1734.     {  
  1735.         return FALSE;  
  1736.     }  
  1737.   
  1738.     //! AT+CMGF  
  1739.     SIM900_SendATcom("AT+CMGF=0");  
  1740.     if(AT_RETURN_OK != SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))   //等待响应,超时200MS  
  1741.     {  
  1742.         return FALSE;  
  1743.     }  
  1744.   
  1745.       
  1746.     //! AT+CMGS//  
  1747.     sprintf(ComBuff, "AT+CMGS=%d", nSMSPduLen);  
  1748.     SIM900_debug("AT+CMGS=%d\r\n", nSMSPduLen);  
  1749.     SIM900_SendATcom(ComBuff);  
  1750.     if(AT_RETURN_ERROR == SIM900_GetATResp(SIM900_Buff, &cnt, ">", 10, 20))  //等待响应,超时200MS  
  1751.     {    
  1752.         return FALSE;  
  1753.     }  
  1754.   
  1755.     //PDU Content  
  1756.     SIM900_ClearRxCnt();                //清除接收缓冲区  
  1757.     SIM900_SendString((char *)pPDU);    //发送字符串  
  1758.     error = SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 50);  
  1759.     if(error == AT_RETURN_ERROR)        //返回错误  
  1760.     {    
  1761.         return FALSE;  
  1762.     }  
  1763.     else  
  1764.     {  
  1765.         temp = 30;                          //等待短信接收成功,最大等待30S  
  1766.         SIM900_ClearRxCnt();                //清除接收缓冲区  
  1767.           
  1768.         do  
  1769.         {  
  1770.             GSM_DelaySer(1);                //延时1S  
  1771.             error = SIM900_GetATResp(SIM900_Buff, &cnt, "+CMGS", 10, 20);   //查询发送成功提示  
  1772.             SIM900_ClearRxCnt();            //清除接收缓冲区  
  1773.             if(error == AT_RETURN_OK)  
  1774.             {  
  1775.                 SIM900_debug("短信已发送成功,对方已经接收!\r\n");  
  1776.                 break;  
  1777.             }  
  1778.             else if(error == AT_RETURN_ERROR)  
  1779.             {  
  1780.                 SIM900_debug("短信发送失败!很有可能是欠费了!\r\n");  
  1781.                 return FALSE;  
  1782.             }  
  1783.             if(temp == 0)  
  1784.             {  
  1785.                 SIM900_debug("短信发送超时!\r\n");  
  1786.                 return FALSE;  
  1787.             }  
  1788.         }while(temp --);      
  1789.     }  
  1790.       
  1791.     //测试短信  
  1792.     //0891683108200705F011000D91685172910098F40008AA086D4B8BD577ED4FE1  
  1793.     return TRUE;  
  1794. }  
  1795.   
  1796.   
  1797.   
  1798.   
  1799.   
  1800.   
  1801.   
  1802. /************************************************************************************************************************* 
  1803. *函数         :   SIM900_CALLS SIM900_MakingCall(const char *pPhoneNumber, u8 TimeOut) 
  1804. *功能         :   拨打指定电话号码 
  1805. *参数         :   pPhoneNumber:电话号码字符串指针 
  1806.                     TimeOut:接听超时,1-255S 
  1807. *返回         :   SIM900_CALLS:拨打电话状态 
  1808. *依赖         :   底层 
  1809. *作者         :   cp1300@139.com 
  1810. *时间         :   2013-10-24 
  1811. *最后修改时间 :   2013-10-24 
  1812. *说明         :   拨打电话 
  1813. *************************************************************************************************************************/  
  1814. SIM900_CALLS SIM900_MakingCall(const char *pPhoneNumber, u8 TimeOut)  
  1815. {  
  1816.     u32 cnt;  
  1817.     u8 retry = SIM900_RETRY;        //重试次数  
  1818.     char buff[32];  
  1819.     SIM900_ERROR error;  
  1820.       
  1821.     if(strlen(pPhoneNumber) > 26)    return SIM900_CALL_ERROR;   //电话号码太长了  
  1822.     sprintf(buff, "ATD%s;", pPhoneNumber);  
  1823.       
  1824.   
  1825.     if(SIM900_TestAT(10) == FALSE)  //串口同步失败  
  1826.     {  
  1827.         SIM900_WaitSleep(1000); //等待上一个操作完成  
  1828.     }  
  1829.     do  
  1830.     {     
  1831.         SIM900_SendATcom("AT+MORING=1");                                    //发送"AT+MORING=1",设置拨号提示  
  1832.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))   //等待响应,超时200MS  
  1833.         {  
  1834.             break;  
  1835.         }  
  1836.         SIM900_Ready(); //等待就绪  
  1837.         retry --;  
  1838.     }while(retry);  
  1839.     if(retry == 0) return SIM900_CALL_ERROR;  
  1840.       
  1841.     //拨打电话  
  1842.     /* 
  1843. AT+MORING=1 
  1844. OK 
  1845. ATD15271900894; 
  1846. OK 
  1847.  
  1848. MO RING 
  1849.  
  1850. MO CONNECTED 
  1851.  
  1852. +CDRIND: 0 
  1853.  
  1854. NO CARRIER 
  1855. */  
  1856.     SIM900_SendATcom(buff);                                             //拨号  
  1857.     error = SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20);              //等待响应,超时200MS  
  1858.     if(error == AT_RETURN_ERROR)        //返回错误  
  1859.     {    
  1860.         return SIM900_CALL_ERROR;  
  1861.     }  
  1862.     else  
  1863.     {  
  1864.         do  
  1865.         {  
  1866.             GSM_DelaySer(1);                                            //延时1S  
  1867.             error = SIM900_GetATResp(SIM900_Buff, &cnt, "MO RING", 10, 1);  //查询拨打成功提示  
  1868.             if(error == AT_RETURN_OK)  
  1869.             {  
  1870.                 SIM900_debug("呼叫成功,对方振铃中...\r\n");  
  1871.                 return SIM900_CALL_RING;  
  1872.             }  
  1873.             error = SIM900_GetATResp(SIM900_Buff, &cnt, "MO CONNECTED", 10, 1); //查询接通标志  
  1874.             if(error == AT_RETURN_OK)  
  1875.             {  
  1876.                 SIM900_debug("对方已经接听电话!\r\n");  
  1877.                 return SIM900_CALL_PUT;  
  1878.             }  
  1879.               
  1880.             error = SIM900_GetATResp(SIM900_Buff, &cnt, "BUSY", 10, 1); //查询接通标志  
  1881.             if(error == SIM900_CALL_BUSY)  
  1882.             {  
  1883.                 SIM900_debug("对方占线!\r\n");  
  1884.                 return SIM900_CALL_PUT;  
  1885.             }  
  1886.             SIM900_ClearRxCnt();            //清除接收缓冲区  
  1887.             TimeOut --;   
  1888.         }while(TimeOut);  
  1889.         if(TimeOut == 0)  
  1890.         {  
  1891.             SIM900_debug("拨打电话超时!\r\n");  
  1892.             return SIM900_CALL_TIMEOUT;  
  1893.         }  
  1894.     }  
  1895.     return SIM900_CALL_ERROR;  
  1896. }  
  1897.   
  1898.   
  1899.   
  1900.   
  1901.   
  1902. /************************************************************************************************************************* 
  1903. *函数         :   SIM900_CALLS SIM900_WaitGetThrough(u8 TimeOut) 
  1904. *功能         :   电话拨打成功后等待对方接听 
  1905. *参数         :   TimeOut:接听超时,1-255S 
  1906. *返回         :   SIM900_CALLS:电话接通状态 
  1907. *依赖         :   底层 
  1908. *作者         :   cp1300@139.com 
  1909. *时间         :   2013-10-26 
  1910. *最后修改时间 :   2013-10-26 
  1911. *说明         :   拨打电话成功后,等待对方接通,或不接 
  1912. *************************************************************************************************************************/  
  1913. SIM900_CALLS SIM900_WaitGetThrough(u8 TimeOut)  
  1914. {  
  1915.     u32 cnt;  
  1916.     SIM900_ERROR error;  
  1917.       
  1918.     while(TimeOut --)  
  1919.     {  
  1920.         SIM900_ClearRxCnt();                                            //清除接收缓冲区  
  1921.         GSM_DelaySer(1);                                                //延时1S  
  1922.         error = SIM900_GetATResp(SIM900_Buff, &cnt, "MO CONNECTED", 10, 1); //查询接通标志  
  1923.         if(error == AT_RETURN_OK)  
  1924.         {  
  1925.             SIM900_debug("对方已经接听电话!\r\n");  
  1926.             return SIM900_CALL_PUT;  
  1927.         }  
  1928.         error = SIM900_GetATResp(SIM900_Buff, &cnt, "NO ANSWER", 10, 1);    //查询一直未接听标志  
  1929.         if(error == AT_RETURN_OK)  
  1930.         {  
  1931.             SIM900_debug("对方无人接听!\r\n");  
  1932.             return SIM900_CALL_NO_ANSWER;  
  1933.         }  
  1934.         error = SIM900_GetATResp(SIM900_Buff, &cnt, "NO CARRIER", 10, 1);   //电话已经挂断  
  1935.         if(error == AT_RETURN_OK)  
  1936.         {  
  1937.             SIM900_debug("对方拒接电话,对方已经挂断!\r\n");  
  1938.             return SIM900_CALL_NO_CARRIER;  
  1939.         }  
  1940.     }  
  1941.     SIM900_debug("对方接听电话超时!\r\n");  
  1942.     return SIM900_CALL_TIMEOUT;  
  1943. }  
  1944.   
  1945.   
  1946.   
  1947.   
  1948.   
  1949. /************************************************************************************************************************* 
  1950. *函数         :   SIM900_CALLS SIM900_WaitHangUP(u8 TimeOut) 
  1951. *功能         :   电话接通后等待对方挂电话 
  1952. *参数         :   TimeOut:接听超时,1-255S 
  1953. *返回         :   SIM900_CALLS:电话接通状态 
  1954. *依赖         :   底层 
  1955. *作者         :   cp1300@139.com 
  1956. *时间         :   2013-10-26 
  1957. *最后修改时间 :   2013-10-26 
  1958. *说明         :   等待对方挂电话 
  1959. *************************************************************************************************************************/  
  1960. SIM900_CALLS SIM900_WaitHangUP(u8 TimeOut)  
  1961. {  
  1962.     u32 cnt;  
  1963.     SIM900_ERROR error;  
  1964.       
  1965.     while(TimeOut --)  
  1966.     {  
  1967.         SIM900_ClearRxCnt();                                            //清除接收缓冲区  
  1968.         GSM_DelaySer(1);                                                //延时1S  
  1969.         error = SIM900_GetATResp(SIM900_Buff, &cnt, "NO CARRIER", 10, 1);   //电话已经挂断  
  1970.         if(error == AT_RETURN_OK)  
  1971.         {  
  1972.             SIM900_debug("对方电话已经挂断!\r\n");  
  1973.             return SIM900_CALL_NO_CARRIER;  
  1974.         }  
  1975.     }  
  1976.     SIM900_debug("对方挂电话超时!\r\n");  
  1977.     return SIM900_CALL_TIMEOUT;  
  1978. }  
  1979.   
  1980.   
  1981.   
  1982.   
  1983.   
  1984. /************************************************************************************************************************* 
  1985. *函数         :   bool SIM900_TestCall(void) 
  1986. *功能         :   查询模块是否可以拨打电话 
  1987. *参数         :   无 
  1988. *返回         :   TRUE:成功;FALSE:失败 
  1989. *依赖         :   底层 
  1990. *作者         :   cp1300@139.com 
  1991. *时间         :   2013-10-24 
  1992. *最后修改时间 :   2013-10-24 
  1993. *说明         :   用于检查模块是否准备好拨打电话 
  1994. *************************************************************************************************************************/  
  1995. bool SIM900_TestCall(void)  
  1996. {  
  1997.     u32 cnt;  
  1998.     u8 retry = SIM900_RETRY;        //重试次数  
  1999.       
  2000.     do  
  2001.     {     
  2002.         if(SIM900_TestAT(10) == FALSE)  //串口同步失败  
  2003.         {  
  2004.             SIM900_WaitSleep(1000); //等待上一个操作完成  
  2005.         }  
  2006.         SIM900_SendATcom("AT+CCALR?");                                  //发送"AT+CCALR?",查询模块是否准备好  
  2007.         if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))   //等待响应,超时200MS  
  2008.         {  
  2009.             if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "+CCALR: 1", 10, 1))  
  2010.             {  
  2011.                 return TRUE;  
  2012.             }  
  2013.             if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "+CCALR: 0", 10, 1))  
  2014.             {  
  2015.                 return FALSE;  
  2016.             }  
  2017.         }  
  2018.         SIM900_Ready(); //等待就绪  
  2019.         retry --;  
  2020.     }while(retry);  
  2021.     if(retry == 0) return FALSE;  
  2022.       
  2023.     return FALSE;  
  2024. }  
  2025.   
  2026.   
  2027.   
  2028. // 7-bit编码  
  2029. // pSrc: 源字符串指针  
  2030. // pDst: 目标编码串指针  
  2031. // nSrcLength: 源字符串长度  
  2032. // 返回: 目标编码串长度  
  2033. static int gsmEncode7bit(const char* pSrc,u8* pDst)  
  2034. {  
  2035.     int nSrc;        // 源字符串的计数值  
  2036.     int nDst;        // 目标编码串的计数值  
  2037.     int nChar;       // 当前正在处理的组内字符字节的序号,范围是0-7  
  2038.     unsigned char nLeft=0;    // 上一字节残余的数据  
  2039.     int nSrcLength = strlen(pSrc);  
  2040.   
  2041.     // 计数值初始化  
  2042.     nSrc = 0;  
  2043.     nDst = 0;  
  2044.   
  2045.     // 将源串每8个字节分为一组,压缩成7个字节  
  2046.     // 循环该处理过程,直至源串被处理完  
  2047.     // 如果分组不到8字节,也能正确处理  
  2048.     while(nSrc<nSrcLength)  
  2049.     {  
  2050.         // 取源字符串的计数值的最低3位  
  2051.         nChar = nSrc & 7;  
  2052.   
  2053.         // 处理源串的每个字节  
  2054.         if(nChar == 0)  
  2055.         {  
  2056.             // 组内第一个字节,只是保存起来,待处理下一个字节时使用  
  2057.             nLeft = *pSrc;  
  2058.         }  
  2059.         else  
  2060.         {  
  2061.             // 组内其它字节,将其右边部分与残余数据相加,得到一个目标编码字节  
  2062.             *pDst = (*pSrc << (8-nChar)) + nLeft;  
  2063.   
  2064.             // 将该字节剩下的左边部分,作为残余数据保存起来  
  2065.             nLeft = *pSrc >> nChar;  
  2066.             // 修改目标串的指针和计数值 pDst++;  
  2067.             //SIM900_debug("%c",*pDst);  
  2068.             pDst++;  nDst++;  
  2069.         }  
  2070.         // 修改源串的指针和计数值  
  2071.         pSrc++; nSrc++;  
  2072.     }  
  2073.   
  2074.     //Nleft还有剩余,需要一个自己保留。  
  2075.     nChar = nSrc & 7;  
  2076.     if(nChar != 0)  
  2077.     {  
  2078.         *pDst=nLeft;  
  2079.         nDst++;   
  2080.         pDst++;  
  2081.     }  
  2082.     //*pDst='\0';  
  2083.   
  2084.     // 返回目标串长度  
  2085.     return nDst;  
  2086. }  
  2087.   
  2088.   
  2089.       
  2090. // 7-bit解码  
  2091. // pSrc: 源编码串指针,7bit编码  
  2092. // pDst: 目标字符串指针  
  2093. // nSrcLength: 源编码串长度  
  2094. // 返回: 目标字符串长度  
  2095. static int gsmDecode7bit(const u8 *pSrc, char *pDst, int nSrcLength)  
  2096. {  
  2097.     int nSrc;        // 源字符串的计数值  
  2098.     int nDst;        // 目标解码串的计数值  
  2099.     int nByte;       // 当前正在处理的组内字节的序号,范围是0-6  
  2100.     unsigned char nLeft;    // 上一字节残余的数据  
  2101.       
  2102.       
  2103.       
  2104.     // 计数值初始化  
  2105.     nSrc = 0;  
  2106.     nDst = 0;  
  2107.       
  2108.     // 组内字节序号和残余数据初始化  
  2109.     nByte = 0;  
  2110.     nLeft = 0;  
  2111.       
  2112.     // 将源数据每7个字节分为一组,解压缩成8个字节  
  2113.     // 循环该处理过程,直至源数据被处理完  
  2114.     // 如果分组不到7字节,也能正确处理  
  2115.       
  2116.     while(nSrc<nSrcLength)  
  2117.     {  
  2118.         // 将源字节右边部分与残余数据相加,去掉最高位,得到一个目标解码字节  
  2119.         *pDst = (((*pSrc) << nByte) | nLeft) & 0x7f;  
  2120.         // 将该字节剩下的左边部分,作为残余数据保存起来  
  2121.         nLeft = (*pSrc) >> (7-nByte);  
  2122.       
  2123.         // 修改目标串的指针和计数值  
  2124.         pDst++;  
  2125.         nDst++;  
  2126.       
  2127.         // 修改字节计数值  
  2128.         nByte++;  
  2129.       
  2130.         // 到了一组的最后一个字节  
  2131.         if(nByte == 7)  
  2132.         {  
  2133.             // 额外得到一个目标解码字节  
  2134.             *pDst = nLeft;  
  2135.       
  2136.             // 修改目标串的指针和计数值  
  2137.             pDst++;  
  2138.             nDst++;  
  2139.       
  2140.             // 组内字节序号和残余数据初始化  
  2141.             nByte = 0;  
  2142.             nLeft = 0;  
  2143.         }  
  2144.       
  2145.         // 修改源串的指针和计数值  
  2146.         pSrc++;  
  2147.         nSrc++;  
  2148.     }  
  2149.       
  2150.     *pDst = 0;  //添加结束符  
  2151.       
  2152.     // 返回目标串长度  
  2153.     return nDst;  
  2154. }  
  2155. /*************************************************************************************************************
     * 文件名:			SIM900.c
     * 功能:			STM32 SIM900底层驱动函数
     * 作者:			cp1300@139.com
     * 创建时间:		2013-10-16
     * 最后修改时间:	2013-10-16
     * 详细:			GSM_CDMA发送短信等
    					2014-04-22:添加字节超时与总超时
    *************************************************************************************************************/
    #include "system.h"
    #include "usart.h"
    #include "SIM900.h"
    #include "delay.h"
    #include "string.h"
    #include "ucos_ii.h"
    #include "unicode_gbk.h"
    #include "main.h"
    
    
    //SIM900通信缓冲区
    u8	SIM900_Buff[SIM900_BUFF_SIZE];	//缓冲区
    
    
    //调试开关
    #define SIM900_DBUG	0
    #if SIM900_DBUG
    	#include "system.h"
    	#define SIM900_debug(format,...)	uart_printf(format,##__VA_ARGS__)
    #else
    	#define SIM900_debug(format,...)	/\
    /
    #endif	//SIM900_DBUG
    
    //所有短信接收缓冲区
    //#define PDU_BUFF_SIZE	1024*20			//20KB	可以一次读取50条未读短信
    u8	SmsPduBuff[PDU_BUFF_SIZE];			//PDU数据缓冲区
    
    
    
    static u8 PhoneNumtoPDUChar(u8 *pNum, char *pChar,u8 NumLen);		//将电话号码字符转换为PDU要求的字符
    static u8 ChartoPhoneNum(char *pChar, char *pNum, u8 CharLen);		//将字符转换为电话号码
    static u32 StringToUnicodeStr(char *pStr, char *pucode,u32 SrtLen);	//将字符串转换为unicode,并存储为16进制样式的字符串
    static u32 UnicodeStrToString(u8 *pucode,char *pStr,u32 SrtLen);	//将字符unicode转换为字符串
    static u32 GSM_StringToHex(char *pStr, u8 NumDigits);				//将16进制样式字符串转换为16进制整型数(必须保证字符串字母都是大写)
    static void GSM_HexToString(u32 HexNum,char *pStr, u8 NumDigits);	//将整型数字转换为16进制样式字符串(字母为大写,不带结束符)
    static int gsmDecode7bit(const u8* pSrc, char* pDst, int nSrcLength);//7bit编码解码
    static int gsmEncode7bit(const char* pSrc,u8* pDst);
    static u16 GSM_GetU2SCharOffset(char *pBuff,u16 CharNum);
    
    
    static PHONE_NUMBER SMSServeNumber;									//全局短信中心号码
    
    
    
    
    /*************************************************************************************************************************
    * 函数				:	void SIM900_SetSMSServeNumber(char *pSMSServeNumber,u8 NumLen)
    * 功能				:	设置全局短信中心号码
    * 参数				:	pSMSServeNumber:短信中心号码,NumLen:短信中心号码长度
    * 返回				:	无
    * 依赖				:	无
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-25
    * 最后修改时间 	: 	2013-10-25
    * 说明				: 	用于发送短信的时候进行调用
    *************************************************************************************************************************/
    void SIM900_SetSMSServeNumber(char *pSMSServeNumber,u8 NumLen)
    {
    	u8 i;
    	
    	if(NumLen > PHONE_NUMBER_MAX_LEN) NumLen = PHONE_NUMBER_MAX_LEN;	//限制电话号码长度
    	for(i = 0;i < NumLen;i ++)
    	{
    		SMSServeNumber.PhoneNumBuff[i] = pSMSServeNumber[i];
    	}
    	SMSServeNumber.PhoneNumLen = NumLen;
    	SMSServeNumber.PhoneNumBuff[SMSServeNumber.PhoneNumLen] = '\0';		//添加结束符
    	SIM900_debug("设置短信中心号码为:%s\r\n",SMSServeNumber.PhoneNumBuff);
    }
    
    
    
    
    /*************************************************************************************************************************
    * 函数				:	bool GSM_CheckNotASCII(char *pBuff,u16 Len)
    * 功能				:	检查字符串中是否含有非ASCII编码
    * 参数				:	pBuff:字符串缓冲区;Len:长度
    * 返回				:	FALSE:字符串全部为ASCII编码;TRUE:字符串含有非ASCII编码,一般为汉字编码
    * 依赖				:	无
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-25
    * 最后修改时间 	: 	2013-10-25
    * 说明				: 	用于选择发送短信的模式,选择U2S或者7BIT编码
    *************************************************************************************************************************/
    bool GSM_CheckNotASCII(char *pBuff,u16 Len)
    {
    	u16 i;
    	
    	for(i = 0;i < Len;i ++)
    	{
    		if(pBuff[i] >= 0x80)
    			return TRUE;
    	}
    	return FALSE;
    }
    
    
    
    /*************************************************************************************************************************
    * 函数				:	static u16 GSM_GetU2SCharOffset(char *pBuff,u16 CharNum)
    * 功能				:	计算指定字符的偏移位置
    * 参数				:	pBuff:字符串缓冲区;
    						CharNum:字符偏移
    * 返回				:	字符串大小
    * 依赖				:	无
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-25
    * 最后修改时间 	: 	2013-10-25
    * 说明				: 	计算指定数量的字符(不分中英文)的大小,比如PDU,U2S模式下,短信只能有70个字符,但是不分中英文
    						此时英文只占用一个字节,但是中文占用2个字节
    *************************************************************************************************************************/
    static u16 GSM_GetU2SCharOffset(char *pBuff,u16 CharNum)
    {
    	u16 i;
    	u16 cnt = 0;
    	
    
    	for(i = 0;i < CharNum;)
    	{
    		if(pBuff[i] >= 0x80)	//中文
    		{
    			cnt +=2;
    			i +=2;
    		}
    		else if(pBuff[i] == 0)	//字符串结束
    		{
    			break;
    		}
    		else					//ASCII
    		{
    			cnt += 1;
    			i ++;
    		}
    	}
    	return cnt;
    }
    
    
    
    /*************************************************************************************************************************
    * 函数				:	bool SIM900_WaitSleep(void)
    * 功能				:	等待GSM模块空闲,并重新唤醒
    * 参数				:	TimeOut:等待超时,时间单位ms
    * 返回				:	TRUE:成功;FALSE:超时
    * 依赖				:	无
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-25
    * 最后修改时间 	: 	2013-10-25
    * 说明				: 	用于等待操作完成,防止快速操作造成模块不响应
    *************************************************************************************************************************/
    bool SIM900_WaitSleep(u32 TimeOut)
    {
    	u32 i;
    	u32 cnt;
    	
    	TimeOut /= 100;
    	TimeOut +=1;
    	
    	SIM900_SetDTR(1);							//等待模块空闲后进入SLEEP模式
    	
    	for(i = 0;i < TimeOut;i ++)
    	{
    		GSM_Delay100MS();						//延时100ms
    		SIM900_SendATcom("AT");					//发送"AT",同步波特率,并且等待应答
    		if(AT_RETURN_TIME_OUT == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 15))	//等待响应,超时150ms
    		{
    			break;
    		}
    	}
    	SIM900_SetDTR(0);							//唤醒
    	if(i == TimeOut) 
    	{
    		SIM900_debug("模块进入空闲模式失败!\r\n");
    		return FALSE;
    	}
    	GSM_Delay100MS();						//延时100ms
    	
    	SIM900_debug("模块进入空闲模式成功!\r\n");
    	SIM900_TestAT(10);
    	return TRUE;
    }
    
    
    
    /*************************************************************************************************************************
    *函数        	:	bool GSM_SendSMS(char *pSMS, char *pPhoneNumber)
    *功能        	:	发送一条短信
    *参数        	:	pSMS:短信内容缓冲区指针,内容为文本文档,并且字符串需要结束符
    					pPhoneNumber:目标电话号码
    *返回        	:	TRUE:短信发送成功;FALSE:短信发送失败
    *依赖        	:	底层
    *作者        	:	cp1300@139.com
    *时间        	:	2013-10-25
    *最后修改时间	:	2013-10-25
    *说明        	:	需要先调用SIM900_SetSMSServeNumber()设置短信中心号码
    					需要使用全局的PDU数据缓冲区
    					一定要添加结束符
    					当短信长度超过单条短信长度限制后会发送多条短信
    *************************************************************************************************************************/
    #define SMS_MAX_LEN		2048					//短信最大长度
    bool GSM_SendSMS(char *pSMS, char *pPhoneNumber)
    {
    	char SMSBuff[160+1];	//短信最大160B,加上一个结束符
    	u8 PDUBuff[512];		//短信PDU数据缓冲区
    	u16 SMSLen;				//短信长度
    	u16 SMSOffset;			//短信发送偏移位置,用于发送多条短信
    	u16 i,j;
    	
    	SMSLen = strlen(pSMS);	//获取要发送的短信长度
    	if(SMSLen > SMS_MAX_LEN) SMSLen = SMS_MAX_LEN;	//限制短信最大长度,防止无限发送
    	
    	if(strlen(SMSServeNumber.PhoneNumBuff) == 0)
    	{
    		SIM900_debug("由于短信中心号码设置失败,导致短信无法发送!\r\n");
    		return FALSE;
    	}
    	
    	SMSOffset = 0;			//起始偏移为0
    	while(1)
    	{
    		if((SMSLen-SMSOffset) > 160)
    			j = 160;
    		else 
    			j = SMSLen-SMSOffset;
    		for(i = 0;i < j;i ++)
    		{
    			SMSBuff[i] = pSMS[SMSOffset + i];	//复制短信到发送缓冲区
    		}
    		SMSBuff[j] = 0;	//添加结束符
    		
    		if(GSM_CheckNotASCII(SMSBuff,j) == TRUE)	//分割的短信中含有非ASCII编码,那么只能使用U2S编码,只能发送70个字符(包括中英文)
    		{
    			SMSOffset += GSM_GetU2SCharOffset(SMSBuff,70);	//第一条短信限制70个字符,返回下一条分割的起始位置
    			SMSBuff[SMSOffset] = 0;
    		}
    		else
    		{
    			SMSOffset += j;	//下一条分割的起始位置
    			SMSBuff[SMSOffset] = 0;
    		}
    		
    		//SIM900_WaitSleep(1000);	//等待上一个操作完成
    		if(GSM_SendOneSMS(SMSBuff, PDUBuff, SMSServeNumber.PhoneNumBuff, pPhoneNumber) == TRUE)
    		{
    			SIM900_debug("发送短信成功!\r\n");
    			
    			
    		}
    		else
    		{
    			SIM900_debug("发送短信失败!\r\n");
    			return FALSE;
    		}
    		if(SMSOffset >= SMSLen) break;	//短信发送完成,退出
    	}
    	
    	return TRUE;
    	
    }
    
    
    
    /*************************************************************************************************************************
    * 函数			:	void SIM900_HardwareInit(void)
    * 功能			:	初始化SIM900相关的硬件
    * 参数			:	无
    * 返回			:	无
    * 依赖			:	无
    * 作者			:	cp1300@139.com
    * 时间			:	2013-10-16
    * 最后修改时间 	: 	2013-10-16
    * 说明			: 	主要初始化与SIM900相关的STM32 IO 以及 UART
    *************************************************************************************************************************/
    void SIM900_HardwareInit(void)
    {
    	SIM900_UartInit();									//初始化串口
    	SIM900_SetRxBuff(SIM900_Buff, SIM900_BUFF_SIZE);	//设置通信缓冲区
    
    	//初始化RI,用于指示新短信或者电话
    	DeviceClockEnable(DEV_GPIOB,ENABLE);				//使能GPIOB时钟
    	GPIOx_Init(GPIOB,BIT14, IN_IPU, IN_IN);				//上拉输入
    	GPIOx_Init(GPIOB,BIT12|BIT13|BIT15, OUT_PP, SPEED_10M);	//推挽输出
    	SIM900_SetDTR(0);									//取消SLEEP
    	SIM900_SetRESET(1);									//复位无效
    	SIM900_SetPWR(1);									//上电无效
    }
    
    
    
    
    /*************************************************************************************************************************
    * 函数				:	void SIM900_HardwarePowerUP(void)
    * 功能				:	SIM900硬件开机
    * 参数				:	无
    * 返回				:	无
    * 依赖				:	无
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-29
    * 最后修改时间 	: 	2013-10-29
    * 说明				: 	用于SIM900模块开机,拉低PWR
    *************************************************************************************************************************/
    void SIM900_HardwarePowerUP(void)
    {
    	SIM900_SetPWR(1);	//恢复高电平
    	GSM_DelayMS(200);
    	SIM900_SetPWR(0);	//拉低750ms开机
    	GSM_DelayMS(750);
    	GSM_Delay100MS();
    	SIM900_SetPWR(1);	//恢复高电平
    	GSM_DelaySer(3);	//延时3S等待开机完毕							
    }
    
    
    
    /*************************************************************************************************************************
    * 函数				:	void SIM900_HardwarePowerDOWN(void)
    * 功能				:	SIM900硬件关机
    * 参数				:	无
    * 返回				:	无
    * 依赖				:	无
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-29
    * 最后修改时间 	: 	2013-10-29
    * 说明				: 	用于SIM900模块关机机,拉低PWR大于1S小于5S
    *************************************************************************************************************************/
    void SIM900_HardwarePowerDOWN(void)
    {
    	SIM900_SetPWR(1);	//恢复高电平
    	GSM_DelayMS(200);
    	SIM900_SetPWR(0);	//拉低1500ms关机
    	GSM_DelaySer(1);	
    	GSM_DelayMS(500);
    	SIM900_SetPWR(1);	//恢复高电平
    	GSM_DelaySer(2);	//延时2S等待注销网络					
    }
    
    
    
    
    
    /*************************************************************************************************************************
    * 函数				:	void SIM900_HardwareReset(void)
    * 功能				:	SIM900硬件复位
    * 参数				:	无
    * 返回				:	无
    * 依赖				:	无
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-29
    * 最后修改时间 	: 	2013-10-29
    * 说明				: 	用于SIM900模块硬件复位
    *************************************************************************************************************************/
    void SIM900_HardwareReset(void)
    {
    	SIM900_SetRESET(1);	//恢复高电平
    	GSM_Delay100MS();
    	SIM900_SetRESET(0);	//拉低100mS复位
    	GSM_Delay100MS();
    	SIM900_SetRESET(1);	//恢复高电平
    	GSM_DelaySer(2);	//延时2S					
    }
    
    
    /*************************************************************************************************************************
    * 函数			:	bool SIM900_ModuleInit(void)
    * 功能			:	初始化SIM900模块
    * 参数			:	无
    * 返回			:	FALSE:初始化失败;TRUE:初始化成功
    * 依赖			:	底层
    * 作者			:	cp1300@139.com
    * 时间			:	2013-10-16
    * 最后修改时间 	: 	2013-10-16
    * 说明			: 	主要初始化与SIM900配置,以及初始化网络
    *************************************************************************************************************************/
    bool SIM900_ModuleInit(void)
    {
    	u32 cnt;
    	u8 retry = 5;		//重试次数
    	
    	//检测模块存在
    	retry = 5;		//重试次数
    	do
    	{
    		SIM900_SendATcom("AT");	//发送"AT",同步波特率,并且等待应答
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 10))	//等待响应,超时100ms
    		{
    			break;
    		}
    		retry --;
    	}while(retry);
    	if(retry == 0) return FALSE;
    	
    	//设置关闭回显
    	retry = SIM900_RETRY;		//重试次数
    	do
    	{
    		SIM900_SendATcom("ATE 0");	//发送"ATE",关闭回显模式
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 10))	//等待响应,超时100ms
    		{
    			SIM900_debug("\r\n关闭AT回显模式成功!\r\n");
    			break;
    		}
    		
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	if(retry == 0)
    	{
    		SIM900_debug("\r\n关闭AT回显模式失败!\r\n");
    		return FALSE;
    	}
    	
    	//设置短消息格式为PDU格式
    	retry = SIM900_RETRY;		//重试次数
    	do
    	{
    		SIM900_SendATcom("AT+CMGF=0");	//发送"AT+CMGF",设置短消息格式为PDU格式
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 10))	//等待响应,超时100ms
    		{
    			SIM900_debug("\r\n设置短消息格式为PDU格式成功!\r\n");
    			break;
    		}
    		
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	if(retry == 0)
    	{
    		SIM900_debug("\r\n设置短消息格式为PDU格式失败!\r\n");
    		return FALSE;
    	}
    	
    	//使能RI引脚提示
    	retry = SIM900_RETRY;		//重试次数
    	do
    	{
    		SIM900_SendATcom("AT+CFGRI=1");	//发送"AT+CFGRI",启动RI引脚提示
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 10))	//等待响应,超时100ms
    		{
    			SIM900_debug("\r\n启动RI引脚提示成功!\r\n");
    			break;
    		}
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	if(retry == 0)
    	{
    		SIM900_debug("\r\n启动RI引脚提示失败!\r\n");
    		return FALSE;
    	}
    	
    	//设置模块sleep模式使能
    	retry = SIM900_RETRY;		//重试次数
    	do
    	{
    		SIM900_SendATcom("AT+CSCLK=1");	//发送"AT+CSCLK",启动SLEEP模式
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 10))	//等待响应,超时100ms
    		{
    			SIM900_debug("\r\n设置SLEEP成功!\r\n");
    			break;
    		}
    		
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	if(retry == 0)
    	{
    		SIM900_debug("\r\n设置SLEEP失败!\r\n");
    		return FALSE;
    	}
    	
    	SIM900_SetDTR(1);	//使能SLEEP模式
    	return TRUE;
    }
    
    
    
    
    /*************************************************************************************************************************
    * 函数			:	bool SIM900_TestAT(u32 retry)
    * 功能			:	SIM900 AT 命令通信测试
    * 参数			:	retry:重试次数
    * 返回			:	FALSE:通信失败;TRUE:通信成功
    * 依赖			:	底层
    * 作者			:	cp1300@139.com
    * 时间			:	2013-10-20
    * 最后修改时间 	: 	2013-10-20
    * 说明			: 	每隔20ms向SIM900发送一个"AT",等待响应返回
    *************************************************************************************************************************/
    bool SIM900_TestAT(u32 retry)
    {
    	u32 cnt;
    
    	//检测模块存在
    	do
    	{
    		SIM900_SendATcom("AT");												//发送"AT",同步波特率,并且等待应答
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 15))	//等待响应,超时150ms
    		{
    			return TRUE;
    		}
    		retry --;
    	}while(retry);
    	
    	return FALSE;
    }
    
    
    /*************************************************************************************************************************
    * 函数				:	SIM900_ERROR SIM900_GetATResp(u8 *pRxBuff, u32 *pLen, const char *pKeyword, u32 ByteTime, u32 TimeOut)
    * 功能				:	获取SIM900的AT指令响应
    * 参数				:	pRxBuff:接收缓冲区指针(输入);pLen:接收到的数据大小(输出),
    						pKeyword:关键字,为字符串,比如"OK",如果在接收到的字符串中有OK字符,就返回成功,否则失败(输入)
    						ByteTime:字节超时时间,单位ms最大999ms
    						TimeOut:等待超时时间,单位字节超时时间
    * 返回				:	SIM900_ERROR
    * 依赖				:	无
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-16
    * 最后修改时间 	: 	2014-04-22
    * 说明				: 	本函数会在接收缓冲区字符串结束添加'\0'
    						2014-04-22:添加字节超时与总超时
    *************************************************************************************************************************/
    SIM900_ERROR SIM900_GetATResp(u8 *pRxBuff, u32 *pLen, const char *pKeyword, u32 ByteTime, u32 TimeOut)
    {
    	u32 cnt1, cnt2=0;	//接收数据计数器
    	u32 timeCnt = TimeOut;
    	
    	if(ByteTime > 999)ByteTime = 999;
    	do
    	{
    		cnt1 = cnt2;
    		GSM_DelayMS(ByteTime);				//延时字节超时
    		cnt2 = SIM900_GetRxCnt();			//获取接收数据计数器
    		if(cnt1 == cnt2)					//完成接收数据了,退出等待
    		{
    			timeCnt --;
    			if((cnt1 > 0)&&(timeCnt!=0)) timeCnt=1;				//数据接收完毕,退出
    		}
    		else
    		{
    			timeCnt = TimeOut;
    		}
    	}while(timeCnt);
    	
    	//等待超时
    	if(cnt2 == 0)
    	{
    		SIM900_debug("\r\nAT指令返回超时\r\n");
    		return AT_RETURN_TIME_OUT;			//返回超时错误
    	}
    	//数据接收完毕
    	*pLen = cnt2;							//返回接收数据长度
    	pRxBuff[cnt2]	= '\0';					//将数据结尾添加结束字符串
    	
    	SIM900_debug("%s\r\n",pRxBuff);			//打印返回信息
    
    	if(strstr((const char*)pRxBuff, pKeyword) != NULL) 	//搜索关键字
    	{
    		SIM900_debug("%s 返回成功!\r\n",pKeyword);
    	    return AT_RETURN_OK;
    	}
    	else if(strstr((const char*)pRxBuff, "ERROR") != NULL)
    	{
    		SIM900_debug("%s 返回错误!\r\n",pKeyword);
    		return AT_RETURN_ERROR;
    	}
    	else
    	{
    		SIM900_debug("%s 返回未知!\r\n",pKeyword);
    		return AT_RETURN_UNKNOWN;
    	}
    	
    	
    }
    
    
    /*************************************************************************************************************************
    * 函数			:	int SIM900_GetSmsNum(void)
    * 功能			:	获取SIM卡存储的短信数量
    * 参数			:	无
    * 返回			:	<0:错误,其它:短信数量
    * 依赖			:	底层
    * 作者			:	cp1300@139.com
    * 时间			:	2013-10-20
    * 最后修改时间 	: 	2013-10-20
    * 说明			: 	无
    *************************************************************************************************************************/
    int SIM900_GetSmsNum(void)
    {
    	u8 n;
    	u32 cnt;
    	char *p;
    	u8 retry = SIM900_RETRY;		//重试次数
    	
    	do
    	{
    		SIM900_SendATcom("AT+CPMS?");	//发送"AT+CPMS",获取短信数量
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))	//等待响应,超时200MS
    		{
    			break;
    		}
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	if(retry == 0) return -1;								//超时
    	
    	p = strstr((const char*)SIM900_Buff, "\"SM\"");			//搜索字符""SM""
    	if(p != NULL) 				
    	{	
    		if(p[6] != ',')	n = 2;								//短信数量有可能是1位数,也有可能是2位数,通过判断后面是否为','
    		else n = 1;
    		return GSM_StringToDec(p + 5, n);					//跳过前面的5字节,""SM",",并获取存储的短信数量					
    	}
    	return -1;												//错误
    }
    
    
    
    /*************************************************************************************************************************
    * 函数				:	bool SIM900_DelMultiSMS(SIM900_DEL DelStatus)
    * 功能				:	SIM900批量删除短信
    * 参数				:	SIM900_DEL
    * 返回				:	TRUE:成功;FALSE:失败;
    * 依赖				:	底层
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-17
    * 最后修改时间 		: 	2013-10-20
    * 说明				: 	批量删除的时候可能会很慢
    *************************************************************************************************************************/
    bool SIM900_DelMultiSMS(SIM900_DEL DelStatus)
    {
    	u32 cnt;
    	u8 retry = SIM900_RETRY;		//重试次数
    	
    	do
    	{
    		switch(DelStatus)
    		{
    			case DEL_READ_SMS:			//删除所有已读短信
    				SIM900_SendATcom("AT+CMGDA=1");	break;
    			case DEL_UNREAD_SMS:		//删除所有未读短信
    				SIM900_SendATcom("AT+CMGDA=2");	break;
    			case DEL_SENT_SMS:			//删除所有已经发送的短信
    				SIM900_SendATcom("AT+CMGDA=3");	break;
    			case DEL_UNSENT_SMS:		//删除所有未发送短信
    				SIM900_SendATcom("AT+CMGDA=4");	break;
    			case DEL_INBOX_SMS:			//删除所有接收短信
    				SIM900_SendATcom("AT+CMGDA=5");	break;
    			case DEL_ALL_SMS:			//删除所有短信
    				SIM900_SendATcom("AT+CMGDA=6");	break;
    			default: return FALSE;
    		}
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 200))//等待响应,超时2S
    		{
    			return TRUE;
    		}
    		SIM900_Ready();	//等待就绪
    	}while(retry --);
    	
    	return FALSE;
    }
    
    
    
    
    
    /*************************************************************************************************************************
    * 函数				:	SIM900_ERROR SIM900_GetUnreadSMS(u8 *pUnreadSMSBuff, u32 BuffSize, u32 *pPDUCnt)
    * 功能				:	读取SIM900所有的未读短信
    * 参数				:	pUnreadSMSBuff:未读短信PDU数据缓冲区指针,BuffSize:缓冲区大小,pPDUCnt:PDU数据大小
    * 返回				:	SIM900_ERROR
    * 依赖				:	底层
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-17
    * 最后修改时间 	: 	2013-10-17
    * 说明				: 	短信最大存储数量为50条
    						缓冲区必须足够大,做好最坏打算,有50条未读短信,如果缓冲区不够大,会发送溢出
    						溢出后虽然不会造成系统错误,但是会覆盖前面的未读短信数据.
    *************************************************************************************************************************/
    SIM900_ERROR SIM900_GetUnreadSMS(u8 *pUnreadSMSBuff, u32 BuffSize, u32 *pPDUCnt)
    {
    	SIM900_ERROR error;
    	u8 retry = SIM900_RETRY;		//重试次数
    	
    	SIM900_SetRxBuff(pUnreadSMSBuff, BuffSize);						//重新设置接收缓冲区
    	do
    	{
    		SIM900_SendATcom("AT+CMGL=0");									//发送"AT+CMGL",读取所有的未读短息
    		error = SIM900_GetATResp(pUnreadSMSBuff, pPDUCnt, "OK", 250, 4);	//等待响应,超时1000ms
    		if(error == AT_RETURN_OK)
    			break;
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	
    	SIM900_SetRxBuff(SIM900_Buff, SIM900_BUFF_SIZE);				//恢复默认缓冲区
    	
    	return error;
    }
    
    
    
    
    
    
    /*************************************************************************************************************************
    *函数        	:	bool GSM_ParsePDUSMS(char *pPDU,char *pSMS,u32 len,SMS_INFO *pInfo)
    *功能        	:	解析一条PDU格式短信
    *参数        	:	pPDU:短信PDU数据缓冲区指针
    * 					pSMS:解析后的短信缓冲区指针
    * 					pInfo:短信信息指针
    *返回        	:	TRUE:成功;FALSE:失败
    *依赖        	:	void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt);
    *作者        	:	cp1300@139.com
    *时间        	:	2013-04-04
    *最后修改时间	:	2013-05-01
    *说明        	:	无
    *************************************************************************************************************************/
    bool GSM_ParsePDUSMS(char *pPDU, char *pSMS, u32 PDUSize, SMS_INFO *pInfo)
    {
    	u16 cnt = 0;
    	u16 temp;
    	char *p;
    	u16 SMS_Size;
    	
    	p = strstr((const char*)pPDU, "+CMGR:");
    	if(p == NULL)
    	{
    		SIM900_debug("短信中没有搜索到\"+CMGR:\"\r\n");
    		p = strstr((const char*)pPDU, "+CMGL:");
    		if(p == NULL)
    		{
    			SIM900_debug("短信中没有搜索到\"+CMGL:\"\r\n");
    			return FALSE;
    		}
    	}
    	//提取短信的编号 //+CMGR: 1,"",34
    	if(p[8] != ',')	pInfo->IndexNum = GSM_StringToDec(p + 7, 2);	//短信索引可能是1位数,也有可能是2位数,通过判断后面是否为','
    	else pInfo->IndexNum = GSM_StringToDec(p + 7, 1);;
    				
    	p = strstr((const char*)p, "\r\n");	//寻找短信PDU开始位置
    	cnt = ((u32)p - (u32)pPDU) + 2;		//找到短信PDU开始的位置了
    	if(p == NULL || cnt >= PDUSize)
    	{
    		pInfo->SMS_Size = 0;
    		SIM900_debug("短信解析错误!\r\n");
    		return FALSE;
    	}
    	
    	//获取短信中心号码长度
    	temp = GSM_StringToHex(&pPDU[cnt], 2);	//将16进制样式字符串转换为整型数
    	cnt += 2;			//跳过前面的短信中心号码长度字节
    	cnt += temp*2;		//跳过前面的短信中心信息
    	
    	//解析PDU数据  RT  UDHI  SRI -  -  MMS   MTI  MTI  //UDHI为1,代表用户数据有头部信息,用于标识短信拆分信息
    	pInfo->PDU = GSM_StringToHex(&pPDU[cnt], 2);	//将16进制样式字符串转换为整型数//PDU数据
    	cnt += 2;			//跳过PDU头数据字节
    
    	//计算发送短信的号码的长度
    	temp = GSM_StringToHex(&pPDU[cnt], 2);	//将16进制样式字符串转换为整型数
    	cnt += 2;			//跳过电话号码长度字节
    	cnt += 2;			//跳过地址类型,常为"91",一字节
    	pInfo->NumLen = ChartoPhoneNum((char *)&pPDU[cnt], (char *)&(pInfo->NumBuff[0]), (temp > SMS_NUM_LEN_MAX - 2) ? (SMS_NUM_LEN_MAX - 2) : temp);	//转换发送号码
    	pInfo->NumBuff[pInfo->NumLen] = 0;	//结束符
    	//lcd_printf("pInfo->NumLen=%d\r\n",pInfo->NumLen);
    	//uart_printf("%s\r\n",pInfo->NumBuff);
    	cnt += (temp%2) ? (temp+1) : temp;	//跳过发送号码长度的字节数
    	cnt+=2;	//跳过PID,2B
    	pInfo->DSC = GSM_StringToHex(&pPDU[cnt], 2);	//获取DSC信息
    	cnt+=2;	//跳过DSC,2B
    	//cnt+=2;	//跳过VP,2B	//没有这个标志
    	//cnt+=2;	//跳过UDL,2B//没有这个标志
    
    	
    	pInfo->Timer.Year = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');		cnt += 2;	//年
    	pInfo->Timer.Month = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');	cnt += 2;	//年
    	pInfo->Timer.Day = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');		cnt += 2;	//年
    	pInfo->Timer.Hour = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');		cnt += 2;	//年
    	pInfo->Timer.Minute = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');	cnt += 2;	//年
    	pInfo->Timer.Second = (pPDU[cnt + 1] - '0') * 10 + (pPDU[cnt] - '0');	cnt += 2;	//年      	                       
       	cnt += 2;	//跳过时差2字节
    	SMS_Size = GSM_StringToHex(&pPDU[cnt], 2);		//计算短信字符数量,不管英文,中文都算一个字符
    	SIM900_debug("SMS_Size = GSM_StringToHex(&pPDU[cnt], 2) = %d\r\n",SMS_Size);
    	cnt += 2;											//跳过短信长度字节,2B
    
    	if(pInfo->PDU & 0x40)	//用户数据有头部信息,标识短信已经被分割为几条
    	{
    		cnt += 8;			//跳过前面8个数据,只要后面的4个,标识
    		SMS_Size -= 12;		//短信长度减去偏移
    		
    		pInfo->AllNum = GSM_StringToHex(&pPDU[cnt], 2);//计算总分割数
    		cnt += 2;		//跳过2B的总数
    		pInfo->PreNum = GSM_StringToHex(&pPDU[cnt], 2);//计算当前位置
    		cnt += 2;		//跳过2B的当前位置
    		SIM900_debug("短信分割:%d/%d\r\n",pInfo->AllNum, pInfo->PreNum);
    	}
    	else
    	{
    		pInfo->AllNum = pInfo->PreNum = 0;	//短信没有被分割
    	}
    	
    	//DCS 00:7BIT编码;08:UCS2编码;04:8bit编码
    	switch((pInfo->DSC) & 0x0f)
    	{
    		case 0x00:	//7bit编码
    		{
    			SIM900_debug("短信为7bit编码(TEXT格式)\r\n");
    			pInfo->SMS_Size = (SMS_Size > 160) ? 160 : SMS_Size;		//短信大小
    			pInfo->TEXT_MODE = 1;	
    			SMS_Size = (SMS_Size * 7 / 8) + (((SMS_Size * 7) % 8) ? 1 : 0);//计算短信占用空间大小
    			pPDU += cnt;
    			for(temp = 0;temp < SMS_Size;temp ++)				//将PDU数据转换为16进制数据
    			{
    				pPDU[temp] = GSM_StringToHex(&pPDU[temp << 1], 2);	//1B数据转换为PDU格式后占用2B
    			}
    			gsmDecode7bit((u8 *)pPDU, (char *)pSMS, SMS_Size);	//7bit->8bit,数据长度会发生变化
    			//SIM900_debug("SMS:%s\r\n",pSMS);
    		}break;
    		case 0x04:	//8bit编码
    		{
    			SIM900_debug("短信为8bit编码(不支持)\r\n");
    			return FALSE;
    		}
    		case 0x08:	//UCS2编码
    		{
    			SIM900_debug("短信为UCS2编码(PDU格式)\r\n");
    			pInfo->TEXT_MODE = 0;	
    			SMS_Size = (SMS_Size > 140) ? 140 : SMS_Size;		//短信字符限制为140B
    			//UNICODE PDU转换为字符串 --> GBK,返回短信大小,每个短信字符占用2字节,每个字节转换为PDU后占用2B
    			pInfo->SMS_Size = UnicodeStrToString((u8 *)pPDU+cnt,(char *)pSMS,SMS_Size<<1);		
    		}break;
    		default:SIM900_debug("未知短信编码格式!\r\n");return FALSE;
    	}
    
    	pSMS[pInfo->SMS_Size] = '\0';				//添加结束符		
    	
    	return TRUE;
    }
    
    
    
    
    
    /*************************************************************************************************************************
    *函数        	:	SIM900_ERROR SIM900_ReadTextSMS(char *pSMS, SMS_INFO *pInfo, u16 IndexNum)
    *功能        	:	读取一条TEXT格式短信
    *参数        	:	pSMS:解析后的短信存放位置指针,注意存放的最大大小由_MAX_SMS_SIZE决定
    * 					pInfo:短信信息指针
    * 					IndexNum:短信索引号
    *返回        	:	GSM_ERROR:状态
    *依赖        	:	短信读取与解析
    *作者        	:	cp1300@139.com
    *时间        	:	20130408
    *最后修改时间	:	20130408
    *说明        	:	
    *************************************************************************************************************************/
    SIM900_ERROR SIM900_ReadTextSMS(char *pSMS, SMS_INFO *pInfo, u16 IndexNum)
    {
    	SIM900_ERROR error;
    	u32 cnt;
    
    	if(SIM900_TestAT(10) == FALSE)	//串口同步失败
    	{
    		SIM900_WaitSleep(1000);	//等待上一个操作完成
    	}
    	//配置短信为TEXT格式
    	SIM900_SendATcom("AT+CMGF=1");	
    	if(SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20) == AT_RETURN_OK)
    	{
    		sprintf((char *)SIM900_Buff, "AT+CMGR=%d", IndexNum);						//写入索引号
    		SIM900_SendATcom((char *)SIM900_Buff);										//发送读取短信命令
    		error = SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20);						//等待返回
    		if(error == AT_RETURN_OK)
    		{
    			GSM_ParseTextSMS((char *)SIM900_Buff, pSMS, cnt, pInfo);				//解析TEXT格式短信
    		}
    	}
    	SIM900_SendATcom("AT+CMGF=0");	//配置短信为PDU格式
    	error = SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20);
    	
    	return error;
    }
    
    
    
    
    /*************************************************************************************************************************
    *函数        	:	u32 GSM_ParseTextSMS(char *pText, char *pSMS, u32 TextSize, SMS_INFO *pInfo)
    *功能        	:	解析一条TEXT格式短信
    *参数        	:	pText:短信TEXT数据缓冲区指针
    * 					pSMS:解析后的短信缓冲区指针
    					TextSize:数据大小
    * 					pInfo:短信信息指针
    *返回        	:	TRUE:成功;FALSE:失败
    *依赖        	:	无
    *作者        	:	cp1300@139.com
    *时间        	:	2013-04-30
    *最后修改时间	:	2013-04-30
    *说明        	:	需要先切换到TEXT格式,用于解析TEXT格式短信,之后会切换回PDU格式
    					需要先解析为PDU后才知道是否为TEXT格式短信
    *************************************************************************************************************************/
    bool GSM_ParseTextSMS(char *pText, char *pSMS, u32 TextSize, SMS_INFO *pInfo)
    {
    	u16 cnt = 0;
    //	u16 temp;
    	char *p;
    //	u16 SMS_Size;
    	
    	pText[TextSize] = '\0';						//添加结束符
    	p = strstr((const char*)pText, "+CMGR:");
    	p = strstr((const char*)p, "\r\n");	//寻找短信TEXT开始位置
    	
    	cnt = ((u32)p - (u32)pText) + 2;		//找到短信TEXT开始的位置了
    	if(p == NULL || cnt >= TextSize)
    	{
    		SIM900_debug("TEXT短信解析错误!\r\n");
    		return FALSE;
    	}
    	p +=2;	//跳到短信开始位置
    	for(cnt = 0;cnt < pInfo->SMS_Size;cnt ++)	//复制短信
    	{
    		pSMS[cnt] = p[cnt];
    	}
    	pSMS[pInfo->SMS_Size] = 0;					//添加结束符
    	
    	return TRUE;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    /*************************************************************************************************************************
    *函数        	:	static u8 PhoneNumtoPDUChar(u8 *pNum, char *pCHAR,u8 NumLen)
    *功能        	:	将电话号码字符转换为PDU要求的字符
    *参数        	:	pNum:电话号码指针
    * 					pChar:字符缓冲区指针
    * 					NumLen:电话号码长度
    *返回        	:	字符长度
    *依赖        	:	底层宏定义
    *作者        	:	cp1300@139.com
    *时间        	:	2013-04-04
    *最后修改时间	:	2013-10-17
    *说明        	:	主要用于电话号码,短信中心号码转换
    * 					如果长度为奇数,则将补成偶数,并在最后一个字符的高位保留位0xf;
    * 					本函数不添加结束符
    *************************************************************************************************************************/
    static u8 PhoneNumtoPDUChar(u8 *pNum, char *pChar,u8 NumLen)
    {
    	u8 i;
    	u8 temp;
    
    	for(i = 0;i < NumLen;i ++)
    	{
    		temp = (pNum[i]+'0') & 0x0f;
    		if(i % 2)	//位数为奇数
    			pChar[i-1] = (temp > 9) ? ('a' + temp - 10) :( temp + '0');
    		else		//位数为偶数
    			pChar[i+1] = (temp > 9) ? ('a' + temp - 10) : (temp + '0');	
    	}
    	if(i % 2)
    	{
    		pChar[NumLen-1] = 'F';
    		return (NumLen + 1);
    	}
    	
    	return NumLen;
    }
    
    
    
    /*************************************************************************************************************************
    *函数        	:	static u8 ChartoPhoneNum(char *pChar, char *pNum, u8 CharLen)
    *功能        	:	将字符转换为电话号码
    *参数        	:	pCHAR:字符缓冲区指针
    * 					pNum:电话号码指针
    * 					charLen:字符号码长度
    *返回        	:	电话长度
    *依赖        	:	底层宏定义
    *作者        	:	cp1300@139.com
    *时间        	:	2013-04-04
    *最后修改时间	:	2013-10-17
    *说明        	:	主要用于电话号码,短信中心号码转换
    * 					如果电话长度为奇数,则将补成偶数,并在最后一个字符的高位保留位0xf;
    * 					转换后为字符
    *************************************************************************************************************************/
    static u8 ChartoPhoneNum(char *pChar, char *pNum, u8 CharLen)
    {
    	u32 i;
    	u8 temp;
    
    	for(i = 0;i < CharLen;i ++)
    	{
    		temp = pChar[i];
    		if(temp == 'F')	//还有一位就结束了
    		{
    			pNum[i] =   pChar[i+1];	
    			return i + 1;
    		}
    		else if(temp > '9')	//非数字
    		{
    			return 0;	//电话号码格式错误
    		}
    		 
    		else if(i % 2)	//位数为奇数
    			pNum[i-1] =  temp;
    		else	//位数为偶数
    			pNum[i+1] = temp;	
    	}
    	return i;
    }
    
    
    
    /*************************************************************************************************************************
    *函数        	:	static u32 StringToUnicodeStr(char *pStr, char *pucode,u32 SrtLen)
    *功能        	:	将字符串转换为unicode,并存储为16进制样式的字符串
    *参数        	:	pStr:字符缓冲区指针
    * 					pucode:转换结果缓冲区
    * 					SrtLen:字符串字节长度
    *返回        	:	转换成为字符后的长度
    *依赖        	:	u16 OneGBKtoUNICODE(u16 GBKCode)
    *作者        	:	cp1300@139.com
    *时间        	:	2013-04-04
    *最后修改时间	:	2013-10-17
    *说明        	:	用于将短信内容转换为PUD格式,本函数不添加字符串结束符
    * 					如"a,b,c"--->"0,0,6,1,0,0,6,2,0,0,6,3"
    * 					输出缓冲区至少为输入的4倍
    *************************************************************************************************************************/
    static u32 StringToUnicodeStr(char *pStr, char *pucode,u32 SrtLen)
    {
    	u32 i;
    	u16 temp;
    	u8 m;
    	u8 chTmp= 0;
    	u32 cnt = 0;
    	
    	for(i = 0;i < SrtLen;i ++)
    	{
    		if(pStr[i] < 0x80)	//ASCII
    		{
    			temp = pStr[i];
    		}
    		else				//GBK
    		{
    			temp = pStr[i ++]<< 8;
    			temp |= pStr[i];
    			temp = OneGBKtoUNICODE(temp);
    		}
    
    		for(m = 0; m <= 12; m+=4)
    	    {
    	      chTmp = (temp >> (12-m)) & 0x0F;			//先取高位
    	      if(chTmp > 0x09)   //! 0x0A-0x0F
    	    	  pucode[cnt ++] = chTmp-0x0A+'A';       //! 'A'-'F'
    	      else                                 //! 0x00-0x09
    	    	  pucode[cnt ++] = chTmp-0x00+'0';       //! '0'-'9'
    	    }
    	}
    	return cnt;
    }
    
    
    
    /*************************************************************************************************************************
    *函数        	:	u32 UnicodeStrToString(u8 *pucode,char *pStr,u32 SrtLen)
    *功能        	:	将字符unicode转换为字符串
    *参数        	:	pucode:转换结果缓冲区
    * 					pStr:字符缓冲区指针
    * 					SrtLen:字符串字节长度
    *返回        	:	转换成为字符后的长度
    *依赖        	:	u16 OneUNICODEtoGBK(u16 unicode);
    *作者        	:	cp1300@139.com
    *时间        	:	2013-04-04
    *最后修改时间	:	2013-10-26
    *说明        	:	用于将PUD格式短信解析,本函数不添加字符串结束符
    					2013-10-26:解决短信中句号无法解析
    *************************************************************************************************************************/
    static u32 UnicodeStrToString(u8 *pucode,char *pStr,u32 SrtLen)
    {
    	u32 i;
    	u16 temp;
    	u32 cnt = 0;
    	u8 H,L;
    
    	for(i = 0;i < SrtLen;i+=4)
    	{
    		if(pucode[i] == '0')	//0
    		{
    			H = pucode[i+2];
    			L = pucode[i+3];
    			H = (H > '9') ? H - 'A' + 10 : H - '0';
    			L = (L > '9') ? L - 'A' + 10 : L - '0';	
    			pStr[cnt++] = (H << 4) + L;	
    		}
    		else
    		{
    			H = pucode[i];
    			L = pucode[i+1];
    			H = (H > '9') ? H - 'A' + 10 : H - '0';
    			L = (L > '9') ? L - 'A' + 10 : L - '0';	
    			temp = (H << 4) + L;
    			temp <<= 8;
    			H = pucode[i+2];
    			L = pucode[i+3];
    			H = (H > '9') ? H - 'A' + 10 : H - '0';
    			L = (L > '9') ? L - 'A' + 10 : L - '0';	
    			temp |= (H << 4) + L;
    			//lcd_printf("temp1 = 0x%04X\r\n",temp);
    			switch(temp)
    			{
    				case 0x3002:	//句号无法显示,转换为GBK编码句号
    					temp = 0xA1A3;break;//'。';	break;
    				default : 
    					temp = OneUNICODEtoGBK(temp);break;	//编码转换
    			}
    			//lcd_printf("temp2 = 0x%04X\r\n",temp);
    			pStr[cnt++] = temp >> 8 ;
    			pStr[cnt++] = temp & 0xff;
    		}
    	}
    	return cnt;
    }
    
    
    
    /*************************************************************************************************************************
    *函数        	:	u32 GSM_StringToHex(char *pStr, u8 NumDigits)
    *功能        	:	将16进制样式字符串转换为16进制整型数(必须保证字符串字母都是大写)
    *参数        	:	pStr:字符串起始指针
    * 					NumDigits:数字位数,16进制数字位数
    *返回        	:	转换后的数字
    *依赖        	:	无
    *作者        	:	cp1300@139.com
    *时间        	:	2013-04-30
    *最后修改时间	:	2013-10-17
    *说明        	:	比如字符串"A865"转换后为0xA865,位数为4位
    					必须保证字符串字母都是大写
    *************************************************************************************************************************/
    static u32 GSM_StringToHex(char *pStr, u8 NumDigits)
    {
    	u8 temp;
    	u32 HEX = 0;
    	u8 i;
    	
    	NumDigits = (NumDigits > 8) ? 8 : NumDigits;	//最大支持8位16进制数
    	
    	for(i = 0;i < NumDigits;i ++)
    	{
    		HEX <<= 4;
    		temp = pStr[i];
    		temp = (temp > '9') ? temp - 'A' + 10 : temp - '0';
    		HEX |= temp;
    	}
    	return HEX;
    }
    
    
    
    /*************************************************************************************************************************
    *函数        	:	void GSM_HexToString(u32 HexNum,c har *pStr, u8 NumDigits)
    *功能        	:	将整型数字转换为16进制样式字符串(字母为大写,不带结束符)
    *参数        	:	HexNum:16进制数字
    					pStr:字符缓冲区指针
    * 					NumDigits:数字位数,16进制数字位数
    *返回        	:	无
    *依赖        	:	无
    *作者        	:	cp1300@139.com
    *时间        	:	2013-04-30
    *最后修改时间	:	2013-04-30
    *说明        	:	比如字符串0xA865转换后为"A865",位数为4位
    *************************************************************************************************************************/
    static void GSM_HexToString(u32 HexNum,char *pStr, u8 NumDigits)
    {
    	u8 temp;
    	u8 i;
    	
    	NumDigits = (NumDigits > 8) ? 8 : NumDigits;	//最大支持8位16进制数
    	
    	for(i = 0;i < NumDigits;i ++)
    	{
    		temp = 0x0f & (HexNum >> (4 * (NumDigits - 1 - i)));
    		temp = (temp > 0x09) ? (temp - 0x0A + 'A') : (temp + '0');
    		pStr[i] = temp;
    	}
    }
    
    
    
    
    /*************************************************************************************************************************
    *函数        	:	u32 GSM_StringToDec(char *pStr, u8 NumDigits)
    *功能        	:	将10进制样式字符串转换为整型数(必须保证完全为数字字符)
    *参数        	:	pStr:字符串起始指针
    * 					NumDigits:数字位数,10进制数字位数
    *返回        	:	转换后的数字
    *依赖        	:	无
    *作者        	:	cp1300@139.com
    *时间        	:	2013-04-30
    *最后修改时间	:	2013-04-30
    *说明        	:	比如字符串"1865"转换后为1865,位数为4位
    					必须保证完全为数字字符
    *************************************************************************************************************************/
    u32 GSM_StringToDec(char *pStr, u8 NumDigits)
    {
    	u32 temp;
    	u32 DEC = 0;
    	u8 i;
    	u8 j;
    	
    	NumDigits = (NumDigits > 10) ? 10 : NumDigits;	//最大支持10位10进制数
    	
    	for(i = 0;i < NumDigits;i ++)
    	{
    		temp = pStr[i] - '0';
    		if(temp > 9)			//只能是数字范围
    			return 0;
    		for(j = 1;j < (NumDigits - i);j ++)
    		{
    			temp *= 10;
    		}
    		DEC += temp;
    	}
    	return DEC;
    }
    
    
    
    /*************************************************************************************************************************
    * 函数			:	SIM900_CALLS SIM900_TestCallStatus(void)
    * 功能			:	SIM900 通话状态检测
    * 参数			:	retry:重试次数
    * 返回			:	FALSE:通信失败;TRUE:通信成功
    * 依赖			:	底层
    * 作者			:	cp1300@139.com
    * 时间			:	2013-10-20
    * 最后修改时间 	: 	2013-10-20
    * 说明			: 	每隔20ms向SIM900发送一个"AT",等待响应返回
    *************************************************************************************************************************/
    SIM900_CALLS SIM900_TestCallStatus(void)
    {
    	u32 cnt;
    	u8 retry = SIM900_RETRY;
    	char *p;
    
    	
    	do
    	{
    		if(SIM900_TestAT(10) == FALSE)	//串口同步失败
    		{
    			SIM900_WaitSleep(1000);	//等待上一个操作完成
    		}
    		SIM900_SendATcom("AT+CPAS");							
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))		//等待响应,超时200ms
    		{
    			p = strstr((const char*)SIM900_Buff, "+CPAS:");						//搜索字符"+CPAS"
    			if(p != NULL) 				
    			{	
    				cnt = GSM_StringToDec(p + 7, 1);								//获取状态编码
    				if(cnt > SIM900_CALL_CENTER)
    					return SIM900_CALL_ERROR;
    				else return (SIM900_CALLS)cnt;
    			}
    		}
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	
    	return SIM900_CALL_ERROR;
    }
    
    /*************************************************************************************************************************
    * 函数			:	bool SIM900_HangUp(void)
    * 功能			:	SIM900 挂掉电话
    * 参数			:	无
    * 返回			:	FALSE:通信失败;TRUE:通信成功
    * 依赖			:	底层
    * 作者			:	cp1300@139.com
    * 时间			:	2013-10-20
    * 最后修改时间 	: 	2013-10-20
    * 说明			: 	
    *************************************************************************************************************************/
    bool SIM900_HangUp(void)
    {
    	u32 cnt;
    	u8 retry = SIM900_RETRY;
    
    	//检测模块存在
    	do
    	{
    		if(SIM900_TestAT(10) == FALSE)	//串口同步失败
    		{
    			SIM900_WaitSleep(1000);	//等待上一个操作完成
    		}
    		SIM900_SendATcom("ATH");			//挂机											
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))	//等待响应,超时200ms
    		{
    			return TRUE;
    		}
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	
    	return FALSE;
    }
    
    
    
    
    /*************************************************************************************************************************
    * 函数			:	bool SIM900_GetServeNumber(PHONE_NUMBER *pServeNumber)
    * 功能			:	获取短信服务中心号码
    * 参数			:	pServeNumber:电话号码存储缓冲区指针
    * 返回			:	FALSE:通信失败;TRUE:通信成功
    * 依赖			:	底层
    * 作者			:	cp1300@139.com
    * 时间			:	2013-10-20
    * 最后修改时间 	: 	2013-10-20
    * 说明			: 	获取SIM卡内部的短信服务中心号码,一般在办理SIM卡的时候已经进行了设置.
    					如果没有预置短信中心号码需要使用手机进行设置
    *************************************************************************************************************************/
    bool SIM900_GetServeNumber(PHONE_NUMBER *pServeNumber)
    {
    	u8 n;
    	u32 cnt;
    	char *p,*p1;
    	u8 retry = SIM900_RETRY;		//重试次数
    	
    	do
    	{	
    		if(SIM900_TestAT(10) == FALSE)	//串口同步失败
    		{
    			SIM900_WaitSleep(1000);	//等待上一个操作完成
    		}
    		//+CSCA: "+8613800270500",145
    		SIM900_SendATcom("AT+CSCA?");			//发送"AT+CSCA",获取短信服务中心号码
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))	//等待响应,超时200MS
    		{
    			p = strstr((const char*)SIM900_Buff, "+CSCA:");			//搜索字符"+CSCA:"
    			if(p != NULL) 											//搜索成功
    			{
    				p = strstr(p+1, "+");	//搜索"+"
    				if(p != NULL)
    				{
    					p1 = strstr(p+1, "\"");	//搜索"\""
    					if(p1 != NULL)			
    					{
    						n = p1 - (p+1);	//计算电话号码长度
    						pServeNumber->PhoneNumLen = (n > PHONE_NUMBER_MAX_LEN) ? PHONE_NUMBER_MAX_LEN : n;	//存储短信服务中心号码长度
    						p ++;					//跳过前面的"+"
    						for(n = 0;n < pServeNumber->PhoneNumLen;n ++)
    						{
    							pServeNumber->PhoneNumBuff[n] = p[n];	//复制电话号码
    						}
    						pServeNumber->PhoneNumBuff[n] = '\0';		//添加结束符
    						SIM900_debug("短信中心号码:%s(长度:%d)\r\n",pServeNumber->PhoneNumBuff,pServeNumber->PhoneNumLen);
    						return TRUE;
    					}
    				}
    			}
    			break;
    		}
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	
    	return FALSE;
    }
    
    
    
    /*************************************************************************************************************************
    * 函数			:	bool SIM900_GetPhoneNumber(PHONE_NUMBER *pPhoneNumber)
    * 功能			:	获取本机号码
    * 参数			:	CenterPhone:电话号码存储缓冲区指针
    * 返回			:	FALSE:通信失败;TRUE:通信成功
    * 依赖			:	底层
    * 作者			:	cp1300@139.com
    * 时间			:	2013-10-20
    * 最后修改时间 	: 	2013-10-20
    * 说明			: 	通常会预存本机号码到SIM卡,也可能没有
    *************************************************************************************************************************/
    bool SIM900_GetPhoneNumber(PHONE_NUMBER *pPhoneNumber)
    {
    	u8 n;
    	u32 cnt;
    	char *p,*p1;
    	u8 retry = SIM900_RETRY;		//重试次数
    	
    	do
    	{	
    		if(SIM900_TestAT(10) == FALSE)	//串口同步失败
    		{
    			SIM900_WaitSleep(1000);	//等待上一个操作完成
    		}
    		//+CNUM: "","15871750634",129,7,4
    		SIM900_SendATcom("AT+CNUM");										//发送"AT++CNUM",获取号码
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))	//等待响应,超时200MS
    		{
    			p = strstr((const char*)SIM900_Buff, "+CNUM:");					//搜索字符"+CNUM:"
    			if(p != NULL) 													//搜索成功
    			{
    				p = strstr(p+1, "\",\"");	//搜索"",""
    				if(p != NULL)
    				{
    					p1 = strstr(p+3, "\",");	//搜索"","
    					if(p1 != NULL)			
    					{
    						n = p1 - (p+3);			//计算电话号码长度
    						pPhoneNumber->PhoneNumLen = (n > PHONE_NUMBER_MAX_LEN) ? PHONE_NUMBER_MAX_LEN : n;	//存储号码长度
    						p +=3;					//跳过前面的"\",\""
    						for(n = 0;n < pPhoneNumber->PhoneNumLen;n ++)
    						{
    							pPhoneNumber->PhoneNumBuff[n] = p[n];	//复制电话号码
    						}
    						pPhoneNumber->PhoneNumBuff[n] = '\0';		//添加结束符
    						SIM900_debug("本机号码:%s(长度:%d)\r\n",pPhoneNumber->PhoneNumBuff,pPhoneNumber->PhoneNumLen);
    						return TRUE;
    					}
    				}
    			}
    			break;
    		}
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	
    	return FALSE;
    }
    
    
    
    /*************************************************************************************************************************
    * 函数				:	int SIM900_GetSignal(void)
    * 功能				:	获取信号强度
    * 参数				:	无
    * 返回				:	<0:获取失败;0-31:信号强度;
    * 依赖				:	底层
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-21
    * 最后修改时间 	: 	2013-10-21
    * 说明				: 	无
    *************************************************************************************************************************/
    int SIM900_GetSignal(void)
    {
    	u8 temp;
    	u32 cnt;
    	char *p;
    	u8 retry = SIM900_RETRY;		//重试次数
    	
    	do
    	{	
    		if(SIM900_TestAT(10) == FALSE)	//串口同步失败
    		{
    			SIM900_WaitSleep(1000);	//等待上一个操作完成
    		}
    		//+CSQ: 27,0
    		//+CSQ: 5,0
    		SIM900_SendATcom("AT+CSQ");											//发送"AT++CSQ",获取号码
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))	//等待响应,超时200MS
    		{
    			p = strstr((const char*)SIM900_Buff, "+CSQ:");					//搜索字符"+CSQ:"
    			if(p != NULL) 													//搜索成功
    			{
    				if(p[7] == ',')	//信号强度为1位数
    				{
    					temp = GSM_StringToDec(&p[6], 1);
    				}
    				else
    				{
    					temp = GSM_StringToDec(&p[6], 2);
    				}
    				
    				return temp;
    			}
    			break;
    		}
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	
    	return -1;
    }
    
    
    
    
    /*************************************************************************************************************************
    * 函数				:	SIM900_NETSTATUS SIM900_GetNetworkStatus(void)
    * 功能				:	获取网络注册状态
    * 参数				:	无
    * 返回				:	SIM900_NETSTATUS
    * 依赖				:	底层
    * 作者				:	cp1300@139.com
    * 时间				:	2013-10-29
    * 最后修改时间 	: 	2013-10-29
    * 说明				: 	无
    *************************************************************************************************************************/
    SIM900_NETSTATUS SIM900_GetNetworkStatus(void)
    {
    	u32 cnt;
    	char *p;
    	u8 retry = SIM900_RETRY;		//重试次数
    	
    	do
    	{	
    		if(SIM900_TestAT(10) == FALSE)	//串口同步失败
    		{
    			SIM900_WaitSleep(1000);	//等待上一个操作完成
    		}
    		//+CREG: 0,1
    		SIM900_SendATcom("AT+CREG?");											//发送"AT+CREG?",获取网络注册状态
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))	//等待响应,超时200MS
    		{
    			p = strstr((const char*)SIM900_Buff, "+CREG:");					//搜索字符"+CSQ:"
    			if(p != NULL) 													//搜索成功
    			{
    				return (SIM900_NETSTATUS)GSM_StringToDec(&p[9], 1);
    			}
    			break;
    		}
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	
    	return SIM900_NET_ERROR;
    }
    
    
    
    
    //PDU模式短信限制长度,最大70个字符,不分中英文
    //返回:限制之后的字符个数
    u32 GSM_PDUStrRes(char *pStr)
    {
    	u32 n = 0;
    
    	while(*pStr != 0)
    	{
    		n ++;
    		if(n == 71)
    		{
    			SIM900_debug("PDU模式短信长度超出70B,强制为70B!\r\n");
    			*pStr = 0;		//强制添加结束符
    			return n;
    		}
    		if((u8)*pStr < 0x80)	//ASCII
    		{
    			pStr ++;
    		}
    		else if((u8)*pStr > 0x80)	//中文
    		{			
    			pStr += 2;
    		}
    		
    	}
    	
    	return n;
    }
    
    
    
    //发送一条短信
    //短信电话号码长度按照字节算但是短信中心号码按照半字节算
    //0891683108100005F0 1100 0D 91685156525310F30008AA0C 9E3F9E4475355B5079D16280
    /*************************************************************************************************************************
    *函数        	:	bool GSM_SendOneSMS(char *pSMS, u8 *pPDU, char *pServeNumber, char *pPhoneNumber)
    *功能        	:	发送一条普通短信,正常长度
    *参数        	:	pSMS:短信内容缓冲区指针,内容为文本文档,并且字符串需要结束符
    * 					pPDU:PDU数据缓冲区指针
    					pServeNumber:短信中心号码
    					pPhoneNumber:目标手机号码结构指针
    *返回        	:	TRUE:短信发送成功;FALSE:短信发送失败
    *依赖        	:	底层
    *作者        	:	cp1300@139.com
    *时间        	:	2013-04-04
    *最后修改时间	:	201310-23
    *说明        	:	短信文本需要添加结束符
    					电话号码必须以86等国际区号开头
    					PDU可以发送中文,但是text只能发送英文
    *************************************************************************************************************************/
    bool GSM_SendOneSMS(char *pSMS, u8 *pPDU, char *pServeNumber, char *pPhoneNumber)
    {
    	SIM900_ERROR error;
    	u16 OffsetCnt = 0;		//缓冲区偏移计数器
    	u32 cnt;
    	u16 temp;
    	char ComBuff[16];
    	u16  nSMSCenterLen= 0, nSMSPduLen = 0;
    	u16 SMSLen = 0;			//短信字符长度
    	FunctionalState EnableU2S = DISABLE;	//使能U2S编码模式,默认为7BIT编码模式
    	u8 *p = (u8 *)pSMS;
    	
    	while(*p != 0)
    	{
    		if(*p >= 0x80)		//有汉字
    		{
    			EnableU2S = ENABLE;	//使能U2S编码模式
    			SIM900_debug("需要发送的短信为PDU格式\r\n");
    			break;
    		}
    		p ++;
    	}
    	
    				
    	if(EnableU2S == ENABLE)			//使能了U2S编码模式
    	{
    		SMSLen = GSM_PDUStrRes(pSMS);	//限制PDU短信长度,计算短信长度
    	}
    	else 							//TEXT模式短信
    	{
    		SMSLen = strlen(pSMS);		//计算短信长度
    		if(SMSLen > 160)		//短信长度大于160个字符
    		{
    			pSMS[160] = 0;			//添加结束符,限制长度
    			SMSLen = 160;
    		}
    	}
    	
    	//计算短信中心号码长度,+91,+86,短信中心号码必须由86开头,并且要加上91,长度为每个数字半字节,不足补F
    	temp = (strlen(pServeNumber) + 2 + 1) / 2;	
    	GSM_HexToString(temp, (char *)(pPDU+OffsetCnt), 2);	//短信中心号码长度转换为16进制样式字符串
    	OffsetCnt += 2;										//跳过短信中心号码长度字节
    	
    	pPDU[OffsetCnt++] = '9';	//服务中心类型
    	pPDU[OffsetCnt++] = '1';
    	OffsetCnt += PhoneNumtoPDUChar((u8 *)pServeNumber,(char *)(pPDU+OffsetCnt),strlen(pServeNumber));	//短信中心号码
    	nSMSCenterLen = OffsetCnt / 2;
    	//! PDU
    	pPDU[OffsetCnt++] = '1';
    	pPDU[OffsetCnt++] = '1';
    	//! For MR
    	pPDU[OffsetCnt++] = '0';
    	pPDU[OffsetCnt++] = '0';
    	//! For DA
    	
    	//计算电话号码长度,+86,发送短信的电话号码由86开头,电话号码长度为字符个数
    	GSM_HexToString(strlen(pPhoneNumber), (char *)(pPDU+OffsetCnt), 2);	//手机号码长度转换为16进制样式字符串
    	OffsetCnt += 2;	//跳过手机号码长度字节
    	
    	pPDU[OffsetCnt++] = '9';	//服务中心类型
    	pPDU[OffsetCnt++] = '1';
    	OffsetCnt += PhoneNumtoPDUChar((u8 *)pPhoneNumber,(char *)(pPDU+OffsetCnt),strlen(pPhoneNumber));	//短信发送号码
    	//! For PID
    	pPDU[OffsetCnt++] = '0';
    	pPDU[OffsetCnt++] = '0';
    	//! For DCS
    	if(EnableU2S == ENABLE)			//U2S
    	{
    		pPDU[OffsetCnt++] = '0';
    		pPDU[OffsetCnt++] = '8';
    	}
    	else 							//7BIT
    	{
    		pPDU[OffsetCnt++] = '0';
    		pPDU[OffsetCnt++] = '0';
    	}
    	
    	//! For VP
    	pPDU[OffsetCnt++] = 'A';
    	pPDU[OffsetCnt++] = 'A';
    	
    	//! For UDL AND UD
    	  //! 注意,此处先将用户数据长度设置为00,并
    	  //! 记录此时的缓冲区位置,然后等编码完成, 
    	  //! 确定了用户数据长度后再修改为实际长度
    	  cnt = OffsetCnt;
    	  pPDU[OffsetCnt++] = '0';
    	  pPDU[OffsetCnt++] = '0'; 	
    	
    	//短信内容
    	if(EnableU2S == ENABLE)			//U2S
    	{
    		temp = StringToUnicodeStr(pSMS,(char *)&pPDU[OffsetCnt], strlen(pSMS));//将短信数据转换为字符数据
    		OffsetCnt += temp;
    		GSM_HexToString(temp/2, (char *)&pPDU[cnt], 2);
    		//! PDU串的长度,后面AT+CMGS要用到此长度
    		nSMSPduLen = OffsetCnt / 2 -nSMSCenterLen;
    	}
    	else 							//7bit
    	{
    		u8 buff[140];				//TEXT短信缓冲区
    		
    		temp = gsmEncode7bit(pSMS, buff);						//将ASCII转换为7bit编码
    		GSM_HexToString(SMSLen, (char *)&pPDU[cnt], 2);
    		
    		for(cnt = 0;cnt < temp;cnt ++)
    		{
    			GSM_HexToString(buff[cnt], (char *)&pPDU[OffsetCnt+cnt*2], 2);	//7bit编码转换为16进制格式字符串
    		}
    		OffsetCnt += (temp << 1);
    		//! PDU串的长度,后面AT+CMGS要用到此长度
    		nSMSPduLen = OffsetCnt / 2 -nSMSCenterLen;
    	}
    	
    						//短信内容长度转换为16进制样式字符串,存储短信长度
    	
    	//end
    	pPDU[OffsetCnt++] = 0x1A;
    	pPDU[OffsetCnt++] = 0x00;
    	
    	SIM900_debug("\r\n%s\r\n",pPDU);
    	
    	//! 下面是发送过程
    	//! AT
    	if(SIM900_TestAT(10) == FALSE)	//串口同步失败
    	{
    		SIM900_WaitSleep(1000);	//等待上一个操作完成
    	}
    
    	//! ATE0
    	SIM900_SendATcom("ATE0");
    	if(AT_RETURN_OK != SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))	//等待响应,超时200MS
    	{
    		return FALSE;
    	}
    
    	//! AT+CMGF
    	SIM900_SendATcom("AT+CMGF=0");
    	if(AT_RETURN_OK != SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))	//等待响应,超时200MS
    	{
    		return FALSE;
    	}
    
    	
    	//! AT+CMGS//
    	sprintf(ComBuff, "AT+CMGS=%d", nSMSPduLen);
    	SIM900_debug("AT+CMGS=%d\r\n", nSMSPduLen);
    	SIM900_SendATcom(ComBuff);
    	if(AT_RETURN_ERROR == SIM900_GetATResp(SIM900_Buff, &cnt, ">", 10, 20))	//等待响应,超时200MS
    	{  
    		return FALSE;
    	}
    
    	//PDU Content
    	SIM900_ClearRxCnt();				//清除接收缓冲区
    	SIM900_SendString((char *)pPDU);	//发送字符串
    	error = SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 50);
    	if(error == AT_RETURN_ERROR)		//返回错误
    	{  
    		return FALSE;
    	}
    	else
    	{
    		temp = 30;							//等待短信接收成功,最大等待30S
    		SIM900_ClearRxCnt();				//清除接收缓冲区
    		
    		do
    		{
    			GSM_DelaySer(1);				//延时1S
    			error = SIM900_GetATResp(SIM900_Buff, &cnt, "+CMGS", 10, 20);	//查询发送成功提示
    			SIM900_ClearRxCnt();			//清除接收缓冲区
    			if(error == AT_RETURN_OK)
    			{
    				SIM900_debug("短信已发送成功,对方已经接收!\r\n");
    				break;
    			}
    			else if(error == AT_RETURN_ERROR)
    			{
    				SIM900_debug("短信发送失败!很有可能是欠费了!\r\n");
    				return FALSE;
    			}
    			if(temp == 0)
    			{
    				SIM900_debug("短信发送超时!\r\n");
    				return FALSE;
    			}
    		}while(temp --);	
    	}
    	
    	//测试短信
    	//0891683108200705F011000D91685172910098F40008AA086D4B8BD577ED4FE1
    	return TRUE;
    }
    
    
    
    
    
    
    
    /*************************************************************************************************************************
    *函数        	:	SIM900_CALLS SIM900_MakingCall(const char *pPhoneNumber, u8 TimeOut)
    *功能        	:	拨打指定电话号码
    *参数        	:	pPhoneNumber:电话号码字符串指针
    					TimeOut:接听超时,1-255S
    *返回        	:	SIM900_CALLS:拨打电话状态
    *依赖        	:	底层
    *作者        	:	cp1300@139.com
    *时间        	:	2013-10-24
    *最后修改时间	:	2013-10-24
    *说明        	:	拨打电话
    *************************************************************************************************************************/
    SIM900_CALLS SIM900_MakingCall(const char *pPhoneNumber, u8 TimeOut)
    {
    	u32 cnt;
    	u8 retry = SIM900_RETRY;		//重试次数
    	char buff[32];
    	SIM900_ERROR error;
    	
    	if(strlen(pPhoneNumber) > 26)	return SIM900_CALL_ERROR;	//电话号码太长了
    	sprintf(buff, "ATD%s;", pPhoneNumber);
    	
    
    	if(SIM900_TestAT(10) == FALSE)	//串口同步失败
    	{
    		SIM900_WaitSleep(1000);	//等待上一个操作完成
    	}
    	do
    	{	
    		SIM900_SendATcom("AT+MORING=1");									//发送"AT+MORING=1",设置拨号提示
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))	//等待响应,超时200MS
    		{
    			break;
    		}
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	if(retry == 0) return SIM900_CALL_ERROR;
    	
    	//拨打电话
    	/*
    AT+MORING=1
    OK
    ATD15271900894;
    OK
    
    MO RING
    
    MO CONNECTED
    
    +CDRIND: 0
    
    NO CARRIER
    */
    	SIM900_SendATcom(buff);												//拨号
    	error = SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20);				//等待响应,超时200MS
    	if(error == AT_RETURN_ERROR)		//返回错误
    	{  
    		return SIM900_CALL_ERROR;
    	}
    	else
    	{
    		do
    		{
    			GSM_DelaySer(1);											//延时1S
    			error = SIM900_GetATResp(SIM900_Buff, &cnt, "MO RING", 10, 1);	//查询拨打成功提示
    			if(error == AT_RETURN_OK)
    			{
    				SIM900_debug("呼叫成功,对方振铃中...\r\n");
    				return SIM900_CALL_RING;
    			}
    			error = SIM900_GetATResp(SIM900_Buff, &cnt, "MO CONNECTED", 10, 1);	//查询接通标志
    			if(error == AT_RETURN_OK)
    			{
    				SIM900_debug("对方已经接听电话!\r\n");
    				return SIM900_CALL_PUT;
    			}
    			
    			error = SIM900_GetATResp(SIM900_Buff, &cnt, "BUSY", 10, 1);	//查询接通标志
    			if(error == SIM900_CALL_BUSY)
    			{
    				SIM900_debug("对方占线!\r\n");
    				return SIM900_CALL_PUT;
    			}
    			SIM900_ClearRxCnt();			//清除接收缓冲区
    			TimeOut --;	
    		}while(TimeOut);
    		if(TimeOut == 0)
    		{
    			SIM900_debug("拨打电话超时!\r\n");
    			return SIM900_CALL_TIMEOUT;
    		}
    	}
    	return SIM900_CALL_ERROR;
    }
    
    
    
    
    
    /*************************************************************************************************************************
    *函数        	:	SIM900_CALLS SIM900_WaitGetThrough(u8 TimeOut)
    *功能        	:	电话拨打成功后等待对方接听
    *参数        	:	TimeOut:接听超时,1-255S
    *返回        	:	SIM900_CALLS:电话接通状态
    *依赖        	:	底层
    *作者        	:	cp1300@139.com
    *时间        	:	2013-10-26
    *最后修改时间	:	2013-10-26
    *说明        	:	拨打电话成功后,等待对方接通,或不接
    *************************************************************************************************************************/
    SIM900_CALLS SIM900_WaitGetThrough(u8 TimeOut)
    {
    	u32 cnt;
    	SIM900_ERROR error;
    	
    	while(TimeOut --)
    	{
    		SIM900_ClearRxCnt();											//清除接收缓冲区
    		GSM_DelaySer(1);												//延时1S
    		error = SIM900_GetATResp(SIM900_Buff, &cnt, "MO CONNECTED", 10, 1);	//查询接通标志
    		if(error == AT_RETURN_OK)
    		{
    			SIM900_debug("对方已经接听电话!\r\n");
    			return SIM900_CALL_PUT;
    		}
    		error = SIM900_GetATResp(SIM900_Buff, &cnt, "NO ANSWER", 10, 1);	//查询一直未接听标志
    		if(error == AT_RETURN_OK)
    		{
    			SIM900_debug("对方无人接听!\r\n");
    			return SIM900_CALL_NO_ANSWER;
    		}
    		error = SIM900_GetATResp(SIM900_Buff, &cnt, "NO CARRIER", 10, 1);	//电话已经挂断
    		if(error == AT_RETURN_OK)
    		{
    			SIM900_debug("对方拒接电话,对方已经挂断!\r\n");
    			return SIM900_CALL_NO_CARRIER;
    		}
    	}
    	SIM900_debug("对方接听电话超时!\r\n");
    	return SIM900_CALL_TIMEOUT;
    }
    
    
    
    
    
    /*************************************************************************************************************************
    *函数        	:	SIM900_CALLS SIM900_WaitHangUP(u8 TimeOut)
    *功能        	:	电话接通后等待对方挂电话
    *参数        	:	TimeOut:接听超时,1-255S
    *返回        	:	SIM900_CALLS:电话接通状态
    *依赖        	:	底层
    *作者        	:	cp1300@139.com
    *时间        	:	2013-10-26
    *最后修改时间	:	2013-10-26
    *说明        	:	等待对方挂电话
    *************************************************************************************************************************/
    SIM900_CALLS SIM900_WaitHangUP(u8 TimeOut)
    {
    	u32 cnt;
    	SIM900_ERROR error;
    	
    	while(TimeOut --)
    	{
    		SIM900_ClearRxCnt();											//清除接收缓冲区
    		GSM_DelaySer(1);												//延时1S
    		error = SIM900_GetATResp(SIM900_Buff, &cnt, "NO CARRIER", 10, 1);	//电话已经挂断
    		if(error == AT_RETURN_OK)
    		{
    			SIM900_debug("对方电话已经挂断!\r\n");
    			return SIM900_CALL_NO_CARRIER;
    		}
    	}
    	SIM900_debug("对方挂电话超时!\r\n");
    	return SIM900_CALL_TIMEOUT;
    }
    
    
    
    
    
    /*************************************************************************************************************************
    *函数        	:	bool SIM900_TestCall(void)
    *功能        	:	查询模块是否可以拨打电话
    *参数        	:	无
    *返回        	:	TRUE:成功;FALSE:失败
    *依赖        	:	底层
    *作者        	:	cp1300@139.com
    *时间        	:	2013-10-24
    *最后修改时间	:	2013-10-24
    *说明        	:	用于检查模块是否准备好拨打电话
    *************************************************************************************************************************/
    bool SIM900_TestCall(void)
    {
    	u32 cnt;
    	u8 retry = SIM900_RETRY;		//重试次数
    	
    	do
    	{	
    		if(SIM900_TestAT(10) == FALSE)	//串口同步失败
    		{
    			SIM900_WaitSleep(1000);	//等待上一个操作完成
    		}
    		SIM900_SendATcom("AT+CCALR?");									//发送"AT+CCALR?",查询模块是否准备好
    		if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "OK", 10, 20))	//等待响应,超时200MS
    		{
    			if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "+CCALR: 1", 10, 1))
    			{
    				return TRUE;
    			}
    			if(AT_RETURN_OK == SIM900_GetATResp(SIM900_Buff, &cnt, "+CCALR: 0", 10, 1))
    			{
    				return FALSE;
    			}
    		}
    		SIM900_Ready();	//等待就绪
    		retry --;
    	}while(retry);
    	if(retry == 0) return FALSE;
    	
    	return FALSE;
    }
    
    
    
    // 7-bit编码
    // pSrc: 源字符串指针
    // pDst: 目标编码串指针
    // nSrcLength: 源字符串长度
    // 返回: 目标编码串长度
    static int gsmEncode7bit(const char* pSrc,u8* pDst)
    {
    	int nSrc;        // 源字符串的计数值
    	int nDst;        // 目标编码串的计数值
    	int nChar;       // 当前正在处理的组内字符字节的序号,范围是0-7
    	unsigned char nLeft=0;    // 上一字节残余的数据
    	int nSrcLength = strlen(pSrc);
    
    	// 计数值初始化
    	nSrc = 0;
    	nDst = 0;
    
    	// 将源串每8个字节分为一组,压缩成7个字节
    	// 循环该处理过程,直至源串被处理完
    	// 如果分组不到8字节,也能正确处理
    	while(nSrc<nSrcLength)
    	{
    		// 取源字符串的计数值的最低3位
    		nChar = nSrc & 7;
    
    		// 处理源串的每个字节
    		if(nChar == 0)
    		{
    			// 组内第一个字节,只是保存起来,待处理下一个字节时使用
    			nLeft = *pSrc;
    		}
    		else
    		{
    			// 组内其它字节,将其右边部分与残余数据相加,得到一个目标编码字节
    			*pDst = (*pSrc << (8-nChar)) + nLeft;
    
    			// 将该字节剩下的左边部分,作为残余数据保存起来
    			nLeft = *pSrc >> nChar;
    			// 修改目标串的指针和计数值 pDst++;
    			//SIM900_debug("%c",*pDst);
    			pDst++;  nDst++;
    		}
    		// 修改源串的指针和计数值
    		pSrc++; nSrc++;
    	}
    
    	//Nleft还有剩余,需要一个自己保留。
    	nChar = nSrc & 7;
    	if(nChar != 0)
    	{
    		*pDst=nLeft;
    		nDst++; 
    		pDst++;
    	}
    	//*pDst='\0';
    
    	// 返回目标串长度
    	return nDst;
    }
    
    
        
    // 7-bit解码
    // pSrc: 源编码串指针,7bit编码
    // pDst: 目标字符串指针
    // nSrcLength: 源编码串长度
    // 返回: 目标字符串长度
    static int gsmDecode7bit(const u8 *pSrc, char *pDst, int nSrcLength)
    {
        int nSrc;        // 源字符串的计数值
        int nDst;        // 目标解码串的计数值
        int nByte;       // 当前正在处理的组内字节的序号,范围是0-6
        unsigned char nLeft;    // 上一字节残余的数据
        
    	
    	
        // 计数值初始化
        nSrc = 0;
        nDst = 0;
        
        // 组内字节序号和残余数据初始化
        nByte = 0;
        nLeft = 0;
        
        // 将源数据每7个字节分为一组,解压缩成8个字节
        // 循环该处理过程,直至源数据被处理完
        // 如果分组不到7字节,也能正确处理
    	
        while(nSrc<nSrcLength)
        {
            // 将源字节右边部分与残余数据相加,去掉最高位,得到一个目标解码字节
            *pDst = (((*pSrc) << nByte) | nLeft) & 0x7f;
            // 将该字节剩下的左边部分,作为残余数据保存起来
            nLeft = (*pSrc) >> (7-nByte);
        
            // 修改目标串的指针和计数值
            pDst++;
            nDst++;
        
            // 修改字节计数值
            nByte++;
        
            // 到了一组的最后一个字节
            if(nByte == 7)
            {
                // 额外得到一个目标解码字节
                *pDst = nLeft;
        
                // 修改目标串的指针和计数值
                pDst++;
                nDst++;
        
                // 组内字节序号和残余数据初始化
                nByte = 0;
                nLeft = 0;
            }
        
            // 修改源串的指针和计数值
            pSrc++;
            nSrc++;
        }
        
        *pDst = 0;	//添加结束符
        
        // 返回目标串长度
        return nDst;
    }
    
    
    

     

  1. /************************************************************************************************************* 
  2.  * 文件名:     SIM900.h 
  3.  * 功能:      STM32 SIM900底层驱动函数 
  4.  * 作者:      cp1300@139.com 
  5.  * 创建时间:        2013-04-03 
  6.  * 最后修改时间:  2013-10-16 
  7.  * 详细:      GSM_CDMA发送短信等 
  8. *************************************************************************************************************/  
  9. #ifndef SIM900_H_  
  10. #define SIM900_H_  
  11. #include "system.h"  
  12.   
  13.   
  14.   
  15. //GSM模块相关定义  
  16. /*#define SIM900_RESET      //PBout(6)  //PB6 
  17. #define SIM900_PORON        PBout(5)    //PB5 
  18. #define GSM_STATUS_IN       PDin(2)     //PD2 
  19. #define GSM_BUZZ            PCout(12)   //PC12*/  
  20. #define SIM900_UART_CH      UART_CH3    //串口3  
  21. //GSM底层操作宏  
  22. /*#define GSM_RESET_H() (GSM_RESET=1) 
  23. #define GSM_RESET_L()   (GSM_RESET=0) 
  24. #define GSM_PORON_H()   (GSM_PORON=1) 
  25. #define GSM_PORON_L()   (GSM_PORON=0) 
  26. #define GSM_STATUS()    (GSM_STATUS_IN) 
  27. #define GSM_BUZZ_H()    (GSM_BUZZ=1) 
  28. #define GSM_BUZZ_L()    (GSM_BUZZ=0) 
  29. #define GSM_Delay_MS(x) Delay_MS(x) //CDMA GSM操作延时,单位MS*/  
  30. //GSM/CDMA模块UART相关接口          
  31. #define SIM900_SendATcom(x)             UARTx_ClearRxCnt(SIM900_UART_CH);UARTx_SendString(SIM900_UART_CH,x);UARTx_SendString(SIM900_UART_CH,"\r\n")     //调用串口发送一个AT命令,并且先清除接收计数器  
  32. #define SIM900_SendData(data,len)       UARTx_SendData(SIM900_UART_CH, data, len);  //发送指定长度数据  
  33. #define SIM900_SendString(x)            UARTx_SendString(SIM900_UART_CH, x)         //发送字符串  
  34. #define SIM900_GetRxCnt()               UARTx_GetRxCnt(SIM900_UART_CH);             //获取新数据计数器  
  35. #define SIM900_ClearRxCnt()             UARTx_ClearRxCnt(SIM900_UART_CH);           //清除新数据计数器  
  36. #define SIM900_UartInit()               UARTx_Init(SIM900_UART_CH, 115200, ENABLE)  //初始化串口,波特率115200,开启接收中断  
  37. #define SIM900_SetRxBuff(pBuff, size)   UARTx_SetRxBuff(SIM900_UART_CH, pBuff,size) //设置串口接收缓冲区  
  38.   
  39. #define GSM_DelayMS(x)                  OSTimeDlyHMSM(0,0,0,x)                  //延时ms,最大延时999ms  
  40. #define GSM_Delay10MS()                 OSTimeDlyHMSM(0,0,0,10)                 //延时10ms  
  41. #define GSM_Delay100MS()                OSTimeDlyHMSM(0,0,0,100)                //延时100ms  
  42. #define GSM_DelaySer(x)                 OSTimeDlyHMSM(0,0,x,0)                  //S延时,最大59S  
  43.   
  44.   
  45. //SIM900返回错误  
  46. typedef enum  
  47. {  
  48.     AT_RETURN_OK            =       0,      //返回成功  
  49.     AT_RETURN_ERROR         =       1,      //返回错误  
  50.     AT_RETURN_UNKNOWN       =       2,      //返回结果未知  
  51.     AT_RETURN_TIME_OUT      =       0xf,    //等待返回超时  
  52. }SIM900_ERROR;  
  53.   
  54.   
  55.   
  56. //短信发送日期,使用字符格式  
  57. typedef __packed struct  
  58. {  
  59.     u8  Year;       //年20xx年  
  60.     u8  Month;      //月  
  61.     u8  Day;        //日  
  62.     u8  Hour;       //小时  
  63.     u8  Minute;     //分钟  
  64.     u8  Second;     //秒  
  65.     u8  Reserve1;   //保留  
  66.     u8  Reserve2;   //保留  
  67. }SMS_TIMER ;  
  68.   
  69.   
  70. //短信解析相关//注意要保证数据对齐  
  71. #define SMS_NUM_LEN_MAX     16      //电话号码最大长度16位  
  72. typedef __packed struct  
  73. {  
  74.     SMS_TIMER       Timer;                      //短信发送的时间     
  75.     char            NumBuff[SMS_NUM_LEN_MAX];   //电话号码缓冲区,使用的是字符模式                
  76.     u8              NumLen;                     //电话号码长度  
  77.     u8              SMS_Size;                   //短信有效内容长度,最大140B  
  78.     u8              TEXT_MODE;                  //1:短信为TEXT模式;0:短信为PDU模式  
  79.     u8              PDU;                        //PDU数据,用于区分是否有短信头部信息  
  80.     u8              DSC;                        //DSC数据,用于区分是否为字符模式(0),PDU模式(0X08)  
  81.     u8              AllNum;                     //当前短信总分割数  
  82.     u8              PreNum;                     //当前位置  
  83.     u8              IndexNum;                   //当前索引位置1-50  
  84. }SMS_INFO ;  
  85.   
  86.   
  87.   
  88. //GSM/CDMA模块型号  
  89. typedef enum  
  90. {  
  91.     GSM_MG323   =   0,      //GSM_CDMA模块型号,MG323  
  92.     CDMA_MC323  =   1,      //GSM_CDMA模块型号,MC323  
  93.     GSM_SIM900A =   2,      //GSM_CDMA模块SIM900A  
  94.     GSM_UNKNOWN =   0xff    //未知模块  
  95. }GSM_TYPE;  
  96.   
  97.   
  98. //SIM900删除短信选择  
  99. typedef enum  
  100. {  
  101.     DEL_READ_SMS    =   1,  //删除所有已读短信  
  102.     DEL_UNREAD_SMS  =   2,  //删除所有未读短信  
  103.     DEL_SENT_SMS    =   3,  //删除所有已经发送的短信  
  104.     DEL_UNSENT_SMS  =   4,  //删除所有未发送短信  
  105.     DEL_INBOX_SMS   =   5,  //删除所有接收短信  
  106.     DEL_ALL_SMS     =   6,  //删除所有短信  
  107. }SIM900_DEL;  
  108.   
  109.   
  110. //通话状态  
  111. typedef enum  
  112. {  
  113.     SIM900_CALL_READY   =   0,  //准备就绪,当前空闲  
  114.     SIM900_CALL_UNKNOWN =   1,  //未知响应指令  
  115.     SIM900_CALL_RING    =   2,  //振铃,准备好可以接通  
  116.     SIM900_CALL_CENTER  =   3,  //呼叫进行中  
  117.     SIM900_CALL_TIMEOUT =   4,  //拨打电话超时  
  118.     SIM900_CALL_PUT     =   5,  //拨打的电话对方已经接通  
  119.     SIM900_CALL_NO_ANSWER=  6,  //对方无人接听  
  120.     SIM900_CALL_NO_CARRIER= 7,  //对方已经挂断  
  121.     SIM900_CALL_BUSY    =   8,  //占线  
  122.     SIM900_CALL_ERROR   =   0xff//其他错误  
  123. }SIM900_CALLS;  
  124.   
  125.   
  126. //网络注册状态  
  127. typedef enum  
  128. {  
  129.     SIM900_NET_NOT = 0, //未注册  
  130.     SIM900_NET_YES = 1, //已经注册  
  131.     SIM900_NET_SEA = 2, //未注册,正在搜索  
  132.     SIM900_NET_TUR = 3, //注册被拒绝  
  133.     SIM900_NET_UNK = 4, //未知  
  134.     SIM900_NET_ROA = 5, //已经注册,但是漫游  
  135.     SIM900_NET_ERROR=0XFF//错误  
  136. }SIM900_NETSTATUS;  
  137.   
  138.   
  139.   
  140.   
  141. //SIM900通信缓冲区  
  142. #define SIM900_BUFF_SIZE    2048            //2KB  
  143. extern u8   SIM900_Buff[SIM900_BUFF_SIZE];  //缓冲区  
  144.   
  145. #define PDU_BUFF_SIZE   1024*10             //20KB  可以一次读取50条未读短信  
  146. extern u8   SmsPduBuff[PDU_BUFF_SIZE];      //PDU数据缓冲区  
  147.   
  148.   
  149. //相关控制引脚  
  150. #define SIM900_GetRI()          PBin(14)            //RI PB14  
  151. #define SIM900_SetDTR(x)        (PBout(13)=x)       //DTR PB13  
  152. #define SIM900_SetRESET(x)      (PBout(15)=x)       //RESET PB15  
  153. #define SIM900_SetPWR(x)        (PBout(12)=x)       //PWR   PB12  
  154.   
  155.   
  156. //电话号码结构  
  157. #define PHONE_NUMBER_MAX_LEN    24-2        //电话号码最大长度  
  158. typedef __packed struct  
  159. {  
  160.     u8      PhoneNumLen;        //电话号码长度  
  161.     char    PhoneNumBuff[PHONE_NUMBER_MAX_LEN + 1];//电话号码缓冲区,电话号码前面的2位为地区编号,中国为86,打电话需要跳过前面的2位数字  
  162. }PHONE_NUMBER;  
  163.   
  164. //最大重试次数,防止AT指令操作失败  
  165. #define SIM900_RETRY    2   
  166.   
  167.   
  168. //API  
  169. #define SIM900_Ready()  if(SIM900_TestAT(10) == FALSE){SIM900_WaitSleep(1000);} //让SIM900就绪,防止卡住//串口同步失败,等待上一个操作完成  
  170. void SIM900_HardwarePowerUP(void);//SIM900硬件开机  
  171. void SIM900_HardwarePowerDOWN(void);//SIM900硬件关机  
  172. void SIM900_HardwareReset(void);//SIM900硬件复位  
  173. bool GSM_SendSMS(char *pSMS, char *pPhoneNumber);//发送短信  
  174. void SIM900_HardwareInit(void); //初始化SIM900相关的硬件  
  175. bool SIM900_ModuleInit(void);   //初始化SIM900模块  
  176. bool SIM900_TestAT(u32 retry);  //检测模块响应  
  177. bool SIM900_HangUp(void);       //挂掉电话  
  178. SIM900_CALLS SIM900_TestCallStatus(void);//检测电话通话状态  
  179. SIM900_ERROR SIM900_GetATResp(u8 *pRxBuff, u32 *pLen, const char *pKeyword, u32 ByteTime, u32 TimeOut);//获取SIM900的AT指令响应  
  180. int SIM900_GetSmsNum(void); //获取SIM卡存储的短信数量  
  181. bool GSM_ParsePDUSMS(char *pPDU, char *pSMS, u32 PDUSize, SMS_INFO *pInfo);//解析一条PDU格式短信  
  182. SIM900_ERROR SIM900_GetUnreadSMS(u8 *pUnreadSMSBuff, u32 BuffSize, u32 *pPDUCnt);//读取SIM900所有的未读短信  
  183. SIM900_ERROR SIM900_ReadTextSMS(char *pSMS, SMS_INFO *pInfo, u16 IndexNum);//用text格式读取短信  
  184. bool GSM_ParseTextSMS(char *pText, char *pSMS, u32 TextSize, SMS_INFO *pInfo);//解析一条TEXT格式短信  
  185. bool SIM900_DelMultiSMS(SIM900_DEL DelStatus);  //批量删除SIM900短信  
  186. bool SIM900_GetServeNumber(PHONE_NUMBER *pServeNumber); //获取短信服务中心号码  
  187. bool SIM900_GetPhoneNumber(PHONE_NUMBER *pPhoneNumber); //获取本机号码  
  188. bool GSM_SendOneSMS(char *pSMS, u8 *pPDU, char *pServeNumber, char *pPhoneNumber);  //发送一条短信  
  189. int SIM900_GetSignal(void); //获取信号强度  
  190. SIM900_CALLS SIM900_MakingCall(const char *pPhoneNumber, u8 TimeOut);//拨打电话  
  191. bool SIM900_TestCall(void);//检查是否可以拨打电话  
  192. void SIM900_SetSMSServeNumber(char *pSMSServeNumber,u8 NumLen);//设置短信中心号码  
  193. bool SIM900_WaitSleep(u32 TimeOut); //等待模块空闲  
  194. SIM900_CALLS SIM900_WaitGetThrough(u8 TimeOut);//等待对方接听电话  
  195. SIM900_CALLS SIM900_WaitHangUP(u8 TimeOut);     //等待对方挂电话  
  196. SIM900_NETSTATUS SIM900_GetNetworkStatus(void); //获取网络注册状态  
  197.   
  198.   
  199. u32 GSM_StringToDec(char *pStr, u8 NumDigits);              //将10进制样式字符串转换为整型数(必须保证完全为数字字符  
  200.   
  201. #endif /*SIM900A_H_*/  
/*************************************************************************************************************
 * 文件名:		SIM900.h
 * 功能:		STM32 SIM900底层驱动函数
 * 作者:		cp1300@139.com
 * 创建时间:		2013-04-03
 * 最后修改时间:	2013-10-16
 * 详细:		GSM_CDMA发送短信等
*************************************************************************************************************/
#ifndef SIM900_H_
#define SIM900_H_
#include "system.h"



//GSM模块相关定义
/*#define SIM900_RESET		//PBout(6)	//PB6
#define SIM900_PORON		PBout(5)	//PB5
#define GSM_STATUS_IN		PDin(2)		//PD2
#define GSM_BUZZ			PCout(12)	//PC12*/
#define SIM900_UART_CH		UART_CH3	//串口3
//GSM底层操作宏
/*#define GSM_RESET_H()	(GSM_RESET=1)
#define GSM_RESET_L()	(GSM_RESET=0)
#define GSM_PORON_H()	(GSM_PORON=1)
#define GSM_PORON_L()	(GSM_PORON=0)
#define GSM_STATUS()	(GSM_STATUS_IN)
#define GSM_BUZZ_H()	(GSM_BUZZ=1)
#define GSM_BUZZ_L()	(GSM_BUZZ=0)
#define GSM_Delay_MS(x)	Delay_MS(x)	//CDMA GSM操作延时,单位MS*/
//GSM/CDMA模块UART相关接口		
#define SIM900_SendATcom(x)				UARTx_ClearRxCnt(SIM900_UART_CH);UARTx_SendString(SIM900_UART_CH,x);UARTx_SendString(SIM900_UART_CH,"\r\n")		//调用串口发送一个AT命令,并且先清除接收计数器
#define SIM900_SendData(data,len)		UARTx_SendData(SIM900_UART_CH, data, len);	//发送指定长度数据
#define SIM900_SendString(x)			UARTx_SendString(SIM900_UART_CH, x)			//发送字符串
#define SIM900_GetRxCnt()				UARTx_GetRxCnt(SIM900_UART_CH);				//获取新数据计数器
#define SIM900_ClearRxCnt()				UARTx_ClearRxCnt(SIM900_UART_CH);			//清除新数据计数器
#define SIM900_UartInit()				UARTx_Init(SIM900_UART_CH, 115200, ENABLE)	//初始化串口,波特率115200,开启接收中断
#define SIM900_SetRxBuff(pBuff, size)	UARTx_SetRxBuff(SIM900_UART_CH, pBuff,size)	//设置串口接收缓冲区

#define GSM_DelayMS(x)					OSTimeDlyHMSM(0,0,0,x)					//延时ms,最大延时999ms
#define GSM_Delay10MS()					OSTimeDlyHMSM(0,0,0,10)					//延时10ms
#define GSM_Delay100MS()				OSTimeDlyHMSM(0,0,0,100)				//延时100ms
#define GSM_DelaySer(x)					OSTimeDlyHMSM(0,0,x,0)					//S延时,最大59S


//SIM900返回错误
typedef enum
{
	AT_RETURN_OK			=		0,		//返回成功
	AT_RETURN_ERROR			=		1,		//返回错误
	AT_RETURN_UNKNOWN		=		2,		//返回结果未知
	AT_RETURN_TIME_OUT		=		0xf,	//等待返回超时
}SIM900_ERROR;



//短信发送日期,使用字符格式
typedef __packed struct
{
	u8	Year;		//年20xx年
	u8	Month;		//月
	u8	Day;		//日
	u8	Hour;		//小时
	u8	Minute;		//分钟
	u8	Second;		//秒
	u8	Reserve1;	//保留
	u8	Reserve2;	//保留
}SMS_TIMER ;


//短信解析相关//注意要保证数据对齐
#define SMS_NUM_LEN_MAX		16		//电话号码最大长度16位
typedef __packed struct
{
	SMS_TIMER		Timer;						//短信发送的时间	
	char			NumBuff[SMS_NUM_LEN_MAX];	//电话号码缓冲区,使用的是字符模式				
	u8				NumLen;						//电话号码长度
	u8				SMS_Size;					//短信有效内容长度,最大140B
	u8				TEXT_MODE;					//1:短信为TEXT模式;0:短信为PDU模式
	u8				PDU;						//PDU数据,用于区分是否有短信头部信息
	u8				DSC;						//DSC数据,用于区分是否为字符模式(0),PDU模式(0X08)
	u8				AllNum;						//当前短信总分割数
	u8				PreNum;						//当前位置
	u8				IndexNum;					//当前索引位置1-50
}SMS_INFO ;



//GSM/CDMA模块型号
typedef enum
{
	GSM_MG323	=	0,		//GSM_CDMA模块型号,MG323
	CDMA_MC323	=	1,		//GSM_CDMA模块型号,MC323
	GSM_SIM900A	=	2,		//GSM_CDMA模块SIM900A
	GSM_UNKNOWN	=	0xff	//未知模块
}GSM_TYPE;


//SIM900删除短信选择
typedef enum
{
	DEL_READ_SMS	=	1,	//删除所有已读短信
	DEL_UNREAD_SMS	=	2,	//删除所有未读短信
	DEL_SENT_SMS	=	3,	//删除所有已经发送的短信
	DEL_UNSENT_SMS	=	4,	//删除所有未发送短信
	DEL_INBOX_SMS	=	5,	//删除所有接收短信
	DEL_ALL_SMS		=	6,	//删除所有短信
}SIM900_DEL;


//通话状态
typedef enum
{
	SIM900_CALL_READY	=	0,	//准备就绪,当前空闲
	SIM900_CALL_UNKNOWN	=	1,	//未知响应指令
	SIM900_CALL_RING	=	2,	//振铃,准备好可以接通
	SIM900_CALL_CENTER	=	3,	//呼叫进行中
	SIM900_CALL_TIMEOUT	=	4,	//拨打电话超时
	SIM900_CALL_PUT		=	5,	//拨打的电话对方已经接通
	SIM900_CALL_NO_ANSWER=	6,	//对方无人接听
	SIM900_CALL_NO_CARRIER=	7,	//对方已经挂断
	SIM900_CALL_BUSY	=	8,	//占线
	SIM900_CALL_ERROR	=	0xff//其他错误
}SIM900_CALLS;


//网络注册状态
typedef enum
{
	SIM900_NET_NOT = 0,	//未注册
	SIM900_NET_YES = 1,	//已经注册
	SIM900_NET_SEA = 2,	//未注册,正在搜索
	SIM900_NET_TUR = 3,	//注册被拒绝
	SIM900_NET_UNK = 4,	//未知
	SIM900_NET_ROA = 5,	//已经注册,但是漫游
	SIM900_NET_ERROR=0XFF//错误
}SIM900_NETSTATUS;




//SIM900通信缓冲区
#define SIM900_BUFF_SIZE	2048			//2KB
extern u8	SIM900_Buff[SIM900_BUFF_SIZE];	//缓冲区

#define PDU_BUFF_SIZE	1024*10				//20KB	可以一次读取50条未读短信
extern u8	SmsPduBuff[PDU_BUFF_SIZE];		//PDU数据缓冲区


//相关控制引脚
#define SIM900_GetRI()			PBin(14)			//RI PB14
#define SIM900_SetDTR(x)		(PBout(13)=x)		//DTR PB13
#define SIM900_SetRESET(x)		(PBout(15)=x)		//RESET PB15
#define SIM900_SetPWR(x)		(PBout(12)=x)		//PWR	PB12


//电话号码结构
#define PHONE_NUMBER_MAX_LEN	24-2		//电话号码最大长度
typedef __packed struct
{
	u8		PhoneNumLen;		//电话号码长度
	char	PhoneNumBuff[PHONE_NUMBER_MAX_LEN + 1];//电话号码缓冲区,电话号码前面的2位为地区编号,中国为86,打电话需要跳过前面的2位数字
}PHONE_NUMBER;

//最大重试次数,防止AT指令操作失败
#define SIM900_RETRY	2 


//API
#define SIM900_Ready()	if(SIM900_TestAT(10) == FALSE){SIM900_WaitSleep(1000);}	//让SIM900就绪,防止卡住//串口同步失败,等待上一个操作完成
void SIM900_HardwarePowerUP(void);//SIM900硬件开机
void SIM900_HardwarePowerDOWN(void);//SIM900硬件关机
void SIM900_HardwareReset(void);//SIM900硬件复位
bool GSM_SendSMS(char *pSMS, char *pPhoneNumber);//发送短信
void SIM900_HardwareInit(void);	//初始化SIM900相关的硬件
bool SIM900_ModuleInit(void);	//初始化SIM900模块
bool SIM900_TestAT(u32 retry);	//检测模块响应
bool SIM900_HangUp(void);		//挂掉电话
SIM900_CALLS SIM900_TestCallStatus(void);//检测电话通话状态
SIM900_ERROR SIM900_GetATResp(u8 *pRxBuff, u32 *pLen, const char *pKeyword, u32 ByteTime, u32 TimeOut);//获取SIM900的AT指令响应
int SIM900_GetSmsNum(void);	//获取SIM卡存储的短信数量
bool GSM_ParsePDUSMS(char *pPDU, char *pSMS, u32 PDUSize, SMS_INFO *pInfo);//解析一条PDU格式短信
SIM900_ERROR SIM900_GetUnreadSMS(u8 *pUnreadSMSBuff, u32 BuffSize, u32 *pPDUCnt);//读取SIM900所有的未读短信
SIM900_ERROR SIM900_ReadTextSMS(char *pSMS, SMS_INFO *pInfo, u16 IndexNum);//用text格式读取短信
bool GSM_ParseTextSMS(char *pText, char *pSMS, u32 TextSize, SMS_INFO *pInfo);//解析一条TEXT格式短信
bool SIM900_DelMultiSMS(SIM900_DEL DelStatus);	//批量删除SIM900短信
bool SIM900_GetServeNumber(PHONE_NUMBER *pServeNumber);	//获取短信服务中心号码
bool SIM900_GetPhoneNumber(PHONE_NUMBER *pPhoneNumber);	//获取本机号码
bool GSM_SendOneSMS(char *pSMS, u8 *pPDU, char *pServeNumber, char *pPhoneNumber);	//发送一条短信
int SIM900_GetSignal(void);	//获取信号强度
SIM900_CALLS SIM900_MakingCall(const char *pPhoneNumber, u8 TimeOut);//拨打电话
bool SIM900_TestCall(void);//检查是否可以拨打电话
void SIM900_SetSMSServeNumber(char *pSMSServeNumber,u8 NumLen);//设置短信中心号码
bool SIM900_WaitSleep(u32 TimeOut);	//等待模块空闲
SIM900_CALLS SIM900_WaitGetThrough(u8 TimeOut);//等待对方接听电话
SIM900_CALLS SIM900_WaitHangUP(u8 TimeOut);		//等待对方挂电话
SIM900_NETSTATUS SIM900_GetNetworkStatus(void);	//获取网络注册状态


u32 GSM_StringToDec(char *pStr, u8 NumDigits);				//将10进制样式字符串转换为整型数(必须保证完全为数字字符

#endif /*SIM900A_H_*/



  1. /************************************************************************************************************* 
  2.  * 文件名: unicode_gbk.c 
  3.  * 功能:      汉字编码转换 
  4.  * 作者:      cp1300@139.com 
  5.  * 创建时间:    2013-04-03 
  6.  * 最后修改时间:2013-04-03 
  7.  * 详细:      需要码表支持 
  8. *************************************************************************************************************/  
  9. #include "system.h"  
  10. #include "unicode_gbk.h"  
  11.   
  12.   
  13.   
  14. #define GBK_UNICODE_IS_SDCARD   0   //GBK,UNICODE编码表在SD卡或其它存储器中  
  15.   
  16.   
  17.   
  18.   
  19.   
  20. //码表在SD卡中  
  21. #if GBK_UNICODE_IS_SDCARD  
  22.   
  23. #include "ff.h"  
  24. #define GtoU    "0:/GtoU.sys"       //GBK 转 UCICODE 编码表位置  
  25. #define UtoG    "0:/UtoG.sys"       //UCICODE 转 GBK 编码表位置  
  26.   
  27. static  FIL   GtoU_File;            //GtoU 文件工作区  
  28. static  FIL   UtoG_File;            //UtoG 文件工作区  
  29.   
  30.   
  31. /************************************************************************************************************************* 
  32. * 函数    :   u8 GBK_UNICODE_Init(void) 
  33. * 功能    :   初始化GBK,UNICODE编码表 
  34. * 参数    :   无    
  35. * 返回    :   0:初始化成功;其它:初始化失败 
  36. * 依赖    :   底层读写函数 
  37. * 作者    :   cp1300@139.com 
  38. * 时间    :   2013-04-18 
  39. * 最后修改时间 : 2013-04-18 
  40. * 说明    :   无 
  41. *************************************************************************************************************************/   
  42. u8 GBK_UNICODE_Init(void)  
  43. {  
  44.     FRESULT status;  
  45.   
  46.     status = f_open(&UtoG_File, UtoG, FA_OPEN_EXISTING | FA_READ);  //以只读方式打开UNICODEtoGBK码表,打开失败返回错误  
  47.     if(status != FR_OK) //打开失败  
  48.     {  
  49.         lcd_printf("open %s error (%d)!\r\n",UtoG, status);  
  50.         return 1;  
  51.     }  
  52.   
  53.     status = f_open(&GtoU_File, GtoU, FA_OPEN_EXISTING | FA_READ);  //以只读方式打开GBKtoUNICODE码表,打开失败返回错误  
  54.     if(status != FR_OK) //打开失败  
  55.     {  
  56.         lcd_printf("open %s error (%d)!\r\n",GtoU, status);  
  57.         return 1;  
  58.     }  
  59.   
  60.   
  61.     return 0;  
  62. }  
  63.   
  64.   
  65.   
  66.   
  67. /************************************************************************************************************************* 
  68. * 函数    :   u16 OneGBKtoUNICODE(u16 GBKCode) 
  69. * 功能    :   将GBK编码转换为unicode编码 
  70. * 参数    :   GBK  
  71. * 返回    :   unicode 
  72. * 依赖    :   底层读写函数 
  73. * 作者    :   cp1300@139.com 
  74. * 时间    :   20120602 
  75. * 最后修改时间 : 20120602 
  76. * 说明    :   需要flash中的码表支持 
  77.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  78. *************************************************************************************************************************/   
  79. u16 OneGBKtoUNICODE(u16 GBKCode)  
  80. {  
  81.     u8 ch,cl;  
  82.     UINT bw;  
  83.     u16 data;  
  84.   
  85.     ch = GBKCode >> 8;  
  86.     cl = GBKCode & 0x00ff;  
  87.   
  88.     ch -= 0x81;  
  89.     cl -= 0x40;  
  90.       
  91.     f_lseek(&GtoU_File, (ch*0xbf+cl)*2);                        //文件指针调到偏移位置  
  92.     if(f_read(&GtoU_File, (u8 *)&data, 2, &bw) != FR_OK)        //读取2字节  
  93.     {  
  94.        return 0x1fff;  
  95.     }  
  96.       
  97.     return (ch<=0x7d && cl<=0xbe) ? data : 0x1fff;  
  98.   
  99.   
  100.   
  101.    /*   ch = GBKCode >> 8; 
  102.     cl = GBKCode & 0x00ff; 
  103.  
  104.     ch -= 0x81; 
  105.     cl -= 0x40;  
  106.     return (ch<=0x7d && cl<=0xbe) ? wUnicodes[ch*0xbf+cl] : 0x1fff;      */  
  107.   
  108. }  
  109.   
  110.   
  111.   
  112. /************************************************************************************************************************* 
  113. * 函数    :   u16 OneUNICODEtoGBK(u16 unicode) 
  114. * 功能    :   将unicode编码转换为GBK编码 
  115. * 参数    :   unicode 
  116. * 返回    :   GBK  
  117. * 依赖    :   底层读写函数 
  118. * 作者    :   cp1300@139.com 
  119. * 时间    :   20120602 
  120. * 最后修改时间 : 20120602 
  121. * 说明    :   需要flash中的码表支持 
  122.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  123. *************************************************************************************************************************/   
  124. u16 OneUNICODEtoGBK(u16 unicode)  //用二分查找算法  
  125. {  
  126.     u32 offset;  
  127.     u16 temp;  
  128.     UINT bw;  
  129.     u8 buff[2];  
  130.   
  131.     if(unicode<=0X9FA5)  
  132.     {  
  133.         if(unicode>=0X4E00)  
  134.             offset=unicode-0X4E00;//0x1b87      //0X4E00,汉字偏移起点  
  135.         else  
  136.             return 0x2020;      //不能显示的字符就给两个空格填充,否则乱码  
  137.     }     
  138.     else if(unicode>0X9FA5)//是标点符号  
  139.     {  
  140.         if(unicode<0XFF01||unicode>0XFF61)  
  141.             return 0x2020;//没有对应编码  //不能显示的字符就给两个空格填充,否则乱码  
  142.         offset=unicode-0XFF01+0X9FA6-0X4E00;      
  143.     }  
  144.     offset *= 2;  
  145.   
  146.   
  147.     f_lseek(&UtoG_File, offset);                        //文件指针调到偏移位置  
  148.     if(f_read(&UtoG_File, buff, 2, &bw) != FR_OK)   //读取2字节  
  149.     {  
  150.        return 0x2020;  
  151.     }  
  152.   
  153.     temp = buff[0];  
  154.     temp <<= 8;  
  155.     temp += buff[1];  
  156.     return temp;    //返回找到的编码                  
  157. }  
  158.   
  159.   
  160.   
  161.   
  162.   
  163.   
  164.   
  165.   
  166.   
  167.   
  168.   
  169.   
  170. #else                               //码表直接在代码中  
  171. #include "unicode_gbk_code.h"  
  172.   
  173.   
  174. /************************************************************************************************************************* 
  175. * 函数    :   u8 GBK_UNICODE_Init(void) 
  176. * 功能    :   初始化GBK,UNICODE编码表 
  177. * 参数    :   无    
  178. * 返回    :   0:初始化成功;其它:初始化失败 
  179. * 依赖    :   底层读写函数 
  180. * 作者    :   cp1300@139.com 
  181. * 时间    :   2013-04-18 
  182. * 最后修改时间 : 2013-04-18 
  183. * 说明    :   无 
  184. *************************************************************************************************************************/   
  185. u8 GBK_UNICODE_Init(void)  
  186. {  
  187.     return 0;  
  188. }  
  189.   
  190.   
  191.   
  192.   
  193. /************************************************************************************************************************* 
  194. * 函数    :   u16 OneGBKtoUNICODE(u16 GBKCode) 
  195. * 功能    :   将GBK编码转换为unicode编码 
  196. * 参数    :   GBK  
  197. * 返回    :   unicode 
  198. * 依赖    :   底层读写函数 
  199. * 作者    :   cp1300@139.com 
  200. * 时间    :   20120602 
  201. * 最后修改时间 : 20120602 
  202. * 说明    :   需要flash中的码表支持 
  203.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  204. *************************************************************************************************************************/   
  205. u16 OneGBKtoUNICODE(u16 GBKCode)  
  206. {  
  207.     u8 ch,cl;  
  208.   
  209.     ch = GBKCode >> 8;  
  210.     cl = GBKCode & 0x00ff;  
  211.   
  212.     ch -= 0x81;  
  213.     cl -= 0x40;  
  214.     return (ch<=0x7d && cl<=0xbe) ? wUnicodes[ch*0xbf+cl] : 0x1fff;  
  215.   
  216. }  
  217.   
  218.   
  219.   
  220. /************************************************************************************************************************* 
  221. * 函数    :   u16 OneUNICODEtoGBK(u16 unicode) 
  222. * 功能    :   将unicode编码转换为GBK编码 
  223. * 参数    :   unicode 
  224. * 返回    :   GBK  
  225. * 依赖    :   底层读写函数 
  226. * 作者    :   cp1300@139.com 
  227. * 时间    :   20120602 
  228. * 最后修改时间 : 20120602 
  229. * 说明    :   需要flash中的码表支持 
  230.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  231. *************************************************************************************************************************/   
  232. u16 OneUNICODEtoGBK(u16 unicode)  //用二分查找算法  
  233. {  
  234.     u32 offset;  
  235.     u16 temp;  
  236.   
  237.     if(unicode<=0X9FA5)  
  238.     {  
  239.         if(unicode>=0X4E00)  
  240.             offset=unicode-0X4E00;//0x1b87      //0X4E00,汉字偏移起点  
  241.         else  
  242.             return 0x2020;      //不能显示的字符就给两个空格填充,否则乱码  
  243.     }     
  244.     else if(unicode>0X9FA5)//是标点符号  
  245.     {  
  246.         if(unicode<0XFF01||unicode>0XFF61)  
  247.             return 0x2020;//没有对应编码  //不能显示的字符就给两个空格填充,否则乱码  
  248.         offset=unicode-0XFF01+0X9FA6-0X4E00;      
  249.     }  
  250.     offset *= 2;  
  251.       
  252.     temp = wGBKs[offset];  
  253.     temp <<= 8;  
  254.     temp += wGBKs[offset+1];  
  255.     return temp;    //返回找到的编码                  
  256. }  
  257.   
  258.   
  259. #endif //GBK_UNICODE_IS_SDCARD  
  260.   
  261.   
  262.   
  263. /************************************************************************************************************************* 
  264. * 函数    :   void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt) 
  265. * 功能    :   将多个GBK编码转换为UNICODE 
  266. * 参数    :   pGBK:GBK编码缓冲区 
  267. *           pUnicode:UNCODE编码缓冲区 
  268. *           cnt:转换编码个数 
  269. * 返回    :   无    
  270. * 依赖    :   OneGBKtoUNICODE 
  271. * 作者    :   cp1300@139.com 
  272. * 时间    :   20130403 
  273. * 最后修改时间 : 20130403 
  274. * 说明    :   需要flash中的码表支持 
  275.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  276. *************************************************************************************************************************/   
  277. void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)  
  278. {  
  279.     while(cnt --)  
  280.     {  
  281.         *pUnicode = OneGBKtoUNICODE(*pGBK ++);  
  282.         pUnicode ++;  
  283.     }  
  284. }  
  285.   
  286.   
  287.   
  288.   
  289. /************************************************************************************************************************* 
  290. * 函数    :   void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt) 
  291. * 功能    :   将多个UNICODE编码转换为GBK 
  292. * 参数    :   pUnicode:UNCODE编码缓冲区 
  293. *           pGBK:GBK编码缓冲区 
  294. *           cnt:转换编码个数 
  295. * 返回    :   无    
  296. * 依赖    :   OneUNICODEtoGBK 
  297. * 作者    :   cp1300@139.com 
  298. * 时间    :   20130403 
  299. * 最后修改时间 : 20130403 
  300. * 说明    :   需要flash中的码表支持 
  301.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  302. *************************************************************************************************************************/   
  303. void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)  
  304. {  
  305.     while(cnt --)  
  306.     {  
  307.         *pGBK = OneUNICODEtoGBK(*pUnicode ++);  
  308.         pGBK ++;  
  309.     }  
  310. }  
/*************************************************************************************************************
 * 文件名:	unicode_gbk.c
 * 功能:		汉字编码转换
 * 作者:		cp1300@139.com
 * 创建时间:	2013-04-03
 * 最后修改时间:2013-04-03
 * 详细:		需要码表支持
*************************************************************************************************************/
#include "system.h"
#include "unicode_gbk.h"



#define GBK_UNICODE_IS_SDCARD	0	//GBK,UNICODE编码表在SD卡或其它存储器中





//码表在SD卡中
#if GBK_UNICODE_IS_SDCARD

#include "ff.h"
#define GtoU	"0:/GtoU.sys" 		//GBK 转 UCICODE 编码表位置
#define UtoG	"0:/UtoG.sys"		//UCICODE 转 GBK 编码表位置

static 	FIL   GtoU_File;			//GtoU 文件工作区
static 	FIL   UtoG_File;			//UtoG 文件工作区


/*************************************************************************************************************************
* 函数	:	u8 GBK_UNICODE_Init(void)
* 功能	:	初始化GBK,UNICODE编码表
* 参数	:	无	
* 返回	:	0:初始化成功;其它:初始化失败
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	2013-04-18
* 最后修改时间 : 2013-04-18
* 说明	: 	无
*************************************************************************************************************************/ 
u8 GBK_UNICODE_Init(void)
{
 	FRESULT status;

	status = f_open(&UtoG_File, UtoG, FA_OPEN_EXISTING | FA_READ);	//以只读方式打开UNICODEtoGBK码表,打开失败返回错误
	if(status != FR_OK)	//打开失败
	{
		lcd_printf("open %s error (%d)!\r\n",UtoG, status);
		return 1;
	}

	status = f_open(&GtoU_File, GtoU, FA_OPEN_EXISTING | FA_READ);	//以只读方式打开GBKtoUNICODE码表,打开失败返回错误
	if(status != FR_OK)	//打开失败
	{
		lcd_printf("open %s error (%d)!\r\n",GtoU, status);
		return 1;
	}


	return 0;
}




/*************************************************************************************************************************
* 函数	:	u16 OneGBKtoUNICODE(u16 GBKCode)
* 功能	:	将GBK编码转换为unicode编码
* 参数	:	GBK	
* 返回	:	unicode
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	20120602
* 最后修改时间 : 20120602
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneGBKtoUNICODE(u16 GBKCode)
{
	u8 ch,cl;
	UINT bw;
	u16 data;

	ch = GBKCode >> 8;
	cl = GBKCode & 0x00ff;

	ch -= 0x81;
    cl -= 0x40;
	
	f_lseek(&GtoU_File, (ch*0xbf+cl)*2);						//文件指针调到偏移位置
	if(f_read(&GtoU_File, (u8 *)&data, 2, &bw) != FR_OK)		//读取2字节
	{
	   return 0x1fff;
	}
	
    return (ch<=0x7d && cl<=0xbe) ? data : 0x1fff;



   /*	ch = GBKCode >> 8;
	cl = GBKCode & 0x00ff;

	ch -= 0x81;
    cl -= 0x40;	
    return (ch<=0x7d && cl<=0xbe) ? wUnicodes[ch*0xbf+cl] : 0x1fff;	   */

}



/*************************************************************************************************************************
* 函数	:	u16 OneUNICODEtoGBK(u16 unicode)
* 功能	:	将unicode编码转换为GBK编码
* 参数	:	unicode
* 返回	:	GBK	
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	20120602
* 最后修改时间 : 20120602
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneUNICODEtoGBK(u16 unicode)  //用二分查找算法
{
	u32 offset;
	u16 temp;
	UINT bw;
	u8 buff[2];

	if(unicode<=0X9FA5)
	{
		if(unicode>=0X4E00)
			offset=unicode-0X4E00;//0x1b87		//0X4E00,汉字偏移起点
		else
			return 0x2020;		//不能显示的字符就给两个空格填充,否则乱码
	}	
	else if(unicode>0X9FA5)//是标点符号
	{
		if(unicode<0XFF01||unicode>0XFF61)
			return 0x2020;//没有对应编码	//不能显示的字符就给两个空格填充,否则乱码
		offset=unicode-0XFF01+0X9FA6-0X4E00;    
	}
	offset *= 2;


	f_lseek(&UtoG_File, offset);						//文件指针调到偏移位置
	if(f_read(&UtoG_File, buff, 2, &bw) != FR_OK)	//读取2字节
	{
	   return 0x2020;
	}

	temp = buff[0];
	temp <<= 8;
	temp += buff[1];
	return temp;	//返回找到的编码				 
}












#else								//码表直接在代码中
#include "unicode_gbk_code.h"


/*************************************************************************************************************************
* 函数	:	u8 GBK_UNICODE_Init(void)
* 功能	:	初始化GBK,UNICODE编码表
* 参数	:	无	
* 返回	:	0:初始化成功;其它:初始化失败
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	2013-04-18
* 最后修改时间 : 2013-04-18
* 说明	: 	无
*************************************************************************************************************************/ 
u8 GBK_UNICODE_Init(void)
{
	return 0;
}




/*************************************************************************************************************************
* 函数	:	u16 OneGBKtoUNICODE(u16 GBKCode)
* 功能	:	将GBK编码转换为unicode编码
* 参数	:	GBK	
* 返回	:	unicode
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	20120602
* 最后修改时间 : 20120602
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneGBKtoUNICODE(u16 GBKCode)
{
	u8 ch,cl;

	ch = GBKCode >> 8;
	cl = GBKCode & 0x00ff;

	ch -= 0x81;
    cl -= 0x40;
    return (ch<=0x7d && cl<=0xbe) ? wUnicodes[ch*0xbf+cl] : 0x1fff;

}



/*************************************************************************************************************************
* 函数	:	u16 OneUNICODEtoGBK(u16 unicode)
* 功能	:	将unicode编码转换为GBK编码
* 参数	:	unicode
* 返回	:	GBK	
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	20120602
* 最后修改时间 : 20120602
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneUNICODEtoGBK(u16 unicode)  //用二分查找算法
{
	u32 offset;
	u16 temp;

	if(unicode<=0X9FA5)
	{
		if(unicode>=0X4E00)
			offset=unicode-0X4E00;//0x1b87		//0X4E00,汉字偏移起点
		else
			return 0x2020;		//不能显示的字符就给两个空格填充,否则乱码
	}	
	else if(unicode>0X9FA5)//是标点符号
	{
		if(unicode<0XFF01||unicode>0XFF61)
			return 0x2020;//没有对应编码	//不能显示的字符就给两个空格填充,否则乱码
		offset=unicode-0XFF01+0X9FA6-0X4E00;    
	}
	offset *= 2;
	
	temp = wGBKs[offset];
	temp <<= 8;
	temp += wGBKs[offset+1];
	return temp;	//返回找到的编码				 
}


#endif //GBK_UNICODE_IS_SDCARD



/*************************************************************************************************************************
* 函数	:	void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)
* 功能	:	将多个GBK编码转换为UNICODE
* 参数	:	pGBK:GBK编码缓冲区
* 			pUnicode:UNCODE编码缓冲区
* 			cnt:转换编码个数
* 返回	:	无	
* 依赖	:	OneGBKtoUNICODE
* 作者	:	cp1300@139.com
* 时间	:	20130403
* 最后修改时间 : 20130403
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)
{
	while(cnt --)
	{
		*pUnicode = OneGBKtoUNICODE(*pGBK ++);
		pUnicode ++;
	}
}




/*************************************************************************************************************************
* 函数	:	void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)
* 功能	:	将多个UNICODE编码转换为GBK
* 参数	:	pUnicode:UNCODE编码缓冲区
* 			pGBK:GBK编码缓冲区
* 			cnt:转换编码个数
* 返回	:	无	
* 依赖	:	OneUNICODEtoGBK
* 作者	:	cp1300@139.com
* 时间	:	20130403
* 最后修改时间 : 20130403
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)
{
	while(cnt --)
	{
		*pGBK = OneUNICODEtoGBK(*pUnicode ++);
		pGBK ++;
	}
}


  1. /************************************************************************************************************* 
  2.  * 文件名: unicode_gbk.c 
  3.  * 功能:      汉字编码转换 
  4.  * 作者:      cp1300@139.com 
  5.  * 创建时间:    2013-04-03 
  6.  * 最后修改时间:2013-04-03 
  7.  * 详细:      需要码表支持 
  8. *************************************************************************************************************/  
  9. #include "system.h"  
  10. #include "unicode_gbk.h"  
  11.   
  12.   
  13.   
  14. #define GBK_UNICODE_IS_SDCARD   0   //GBK,UNICODE编码表在SD卡或其它存储器中  
  15.   
  16.   
  17.   
  18.   
  19.   
  20. //码表在SD卡中  
  21. #if GBK_UNICODE_IS_SDCARD  
  22.   
  23. #include "ff.h"  
  24. #define GtoU    "0:/GtoU.sys"       //GBK 转 UCICODE 编码表位置  
  25. #define UtoG    "0:/UtoG.sys"       //UCICODE 转 GBK 编码表位置  
  26.   
  27. static  FIL   GtoU_File;            //GtoU 文件工作区  
  28. static  FIL   UtoG_File;            //UtoG 文件工作区  
  29.   
  30.   
  31. /************************************************************************************************************************* 
  32. * 函数    :   u8 GBK_UNICODE_Init(void) 
  33. * 功能    :   初始化GBK,UNICODE编码表 
  34. * 参数    :   无    
  35. * 返回    :   0:初始化成功;其它:初始化失败 
  36. * 依赖    :   底层读写函数 
  37. * 作者    :   cp1300@139.com 
  38. * 时间    :   2013-04-18 
  39. * 最后修改时间 : 2013-04-18 
  40. * 说明    :   无 
  41. *************************************************************************************************************************/   
  42. u8 GBK_UNICODE_Init(void)  
  43. {  
  44.     FRESULT status;  
  45.   
  46.     status = f_open(&UtoG_File, UtoG, FA_OPEN_EXISTING | FA_READ);  //以只读方式打开UNICODEtoGBK码表,打开失败返回错误  
  47.     if(status != FR_OK) //打开失败  
  48.     {  
  49.         lcd_printf("open %s error (%d)!\r\n",UtoG, status);  
  50.         return 1;  
  51.     }  
  52.   
  53.     status = f_open(&GtoU_File, GtoU, FA_OPEN_EXISTING | FA_READ);  //以只读方式打开GBKtoUNICODE码表,打开失败返回错误  
  54.     if(status != FR_OK) //打开失败  
  55.     {  
  56.         lcd_printf("open %s error (%d)!\r\n",GtoU, status);  
  57.         return 1;  
  58.     }  
  59.   
  60.   
  61.     return 0;  
  62. }  
  63.   
  64.   
  65.   
  66.   
  67. /************************************************************************************************************************* 
  68. * 函数    :   u16 OneGBKtoUNICODE(u16 GBKCode) 
  69. * 功能    :   将GBK编码转换为unicode编码 
  70. * 参数    :   GBK  
  71. * 返回    :   unicode 
  72. * 依赖    :   底层读写函数 
  73. * 作者    :   cp1300@139.com 
  74. * 时间    :   20120602 
  75. * 最后修改时间 : 20120602 
  76. * 说明    :   需要flash中的码表支持 
  77.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  78. *************************************************************************************************************************/   
  79. u16 OneGBKtoUNICODE(u16 GBKCode)  
  80. {  
  81.     u8 ch,cl;  
  82.     UINT bw;  
  83.     u16 data;  
  84.   
  85.     ch = GBKCode >> 8;  
  86.     cl = GBKCode & 0x00ff;  
  87.   
  88.     ch -= 0x81;  
  89.     cl -= 0x40;  
  90.       
  91.     f_lseek(&GtoU_File, (ch*0xbf+cl)*2);                        //文件指针调到偏移位置  
  92.     if(f_read(&GtoU_File, (u8 *)&data, 2, &bw) != FR_OK)        //读取2字节  
  93.     {  
  94.        return 0x1fff;  
  95.     }  
  96.       
  97.     return (ch<=0x7d && cl<=0xbe) ? data : 0x1fff;  
  98.   
  99.   
  100.   
  101.    /*   ch = GBKCode >> 8; 
  102.     cl = GBKCode & 0x00ff; 
  103.  
  104.     ch -= 0x81; 
  105.     cl -= 0x40;  
  106.     return (ch<=0x7d && cl<=0xbe) ? wUnicodes[ch*0xbf+cl] : 0x1fff;      */  
  107.   
  108. }  
  109.   
  110.   
  111.   
  112. /************************************************************************************************************************* 
  113. * 函数    :   u16 OneUNICODEtoGBK(u16 unicode) 
  114. * 功能    :   将unicode编码转换为GBK编码 
  115. * 参数    :   unicode 
  116. * 返回    :   GBK  
  117. * 依赖    :   底层读写函数 
  118. * 作者    :   cp1300@139.com 
  119. * 时间    :   20120602 
  120. * 最后修改时间 : 20120602 
  121. * 说明    :   需要flash中的码表支持 
  122.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  123. *************************************************************************************************************************/   
  124. u16 OneUNICODEtoGBK(u16 unicode)  //用二分查找算法  
  125. {  
  126.     u32 offset;  
  127.     u16 temp;  
  128.     UINT bw;  
  129.     u8 buff[2];  
  130.   
  131.     if(unicode<=0X9FA5)  
  132.     {  
  133.         if(unicode>=0X4E00)  
  134.             offset=unicode-0X4E00;//0x1b87      //0X4E00,汉字偏移起点  
  135.         else  
  136.             return 0x2020;      //不能显示的字符就给两个空格填充,否则乱码  
  137.     }     
  138.     else if(unicode>0X9FA5)//是标点符号  
  139.     {  
  140.         if(unicode<0XFF01||unicode>0XFF61)  
  141.             return 0x2020;//没有对应编码  //不能显示的字符就给两个空格填充,否则乱码  
  142.         offset=unicode-0XFF01+0X9FA6-0X4E00;      
  143.     }  
  144.     offset *= 2;  
  145.   
  146.   
  147.     f_lseek(&UtoG_File, offset);                        //文件指针调到偏移位置  
  148.     if(f_read(&UtoG_File, buff, 2, &bw) != FR_OK)   //读取2字节  
  149.     {  
  150.        return 0x2020;  
  151.     }  
  152.   
  153.     temp = buff[0];  
  154.     temp <<= 8;  
  155.     temp += buff[1];  
  156.     return temp;    //返回找到的编码                  
  157. }  
  158.   
  159.   
  160.   
  161.   
  162.   
  163.   
  164.   
  165.   
  166.   
  167.   
  168.   
  169.   
  170. #else                               //码表直接在代码中  
  171. #include "unicode_gbk_code.h"  
  172.   
  173.   
  174. /************************************************************************************************************************* 
  175. * 函数    :   u8 GBK_UNICODE_Init(void) 
  176. * 功能    :   初始化GBK,UNICODE编码表 
  177. * 参数    :   无    
  178. * 返回    :   0:初始化成功;其它:初始化失败 
  179. * 依赖    :   底层读写函数 
  180. * 作者    :   cp1300@139.com 
  181. * 时间    :   2013-04-18 
  182. * 最后修改时间 : 2013-04-18 
  183. * 说明    :   无 
  184. *************************************************************************************************************************/   
  185. u8 GBK_UNICODE_Init(void)  
  186. {  
  187.     return 0;  
  188. }  
  189.   
  190.   
  191.   
  192.   
  193. /************************************************************************************************************************* 
  194. * 函数    :   u16 OneGBKtoUNICODE(u16 GBKCode) 
  195. * 功能    :   将GBK编码转换为unicode编码 
  196. * 参数    :   GBK  
  197. * 返回    :   unicode 
  198. * 依赖    :   底层读写函数 
  199. * 作者    :   cp1300@139.com 
  200. * 时间    :   20120602 
  201. * 最后修改时间 : 20120602 
  202. * 说明    :   需要flash中的码表支持 
  203.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  204. *************************************************************************************************************************/   
  205. u16 OneGBKtoUNICODE(u16 GBKCode)  
  206. {  
  207.     u8 ch,cl;  
  208.   
  209.     ch = GBKCode >> 8;  
  210.     cl = GBKCode & 0x00ff;  
  211.   
  212.     ch -= 0x81;  
  213.     cl -= 0x40;  
  214.     return (ch<=0x7d && cl<=0xbe) ? wUnicodes[ch*0xbf+cl] : 0x1fff;  
  215.   
  216. }  
  217.   
  218.   
  219.   
  220. /************************************************************************************************************************* 
  221. * 函数    :   u16 OneUNICODEtoGBK(u16 unicode) 
  222. * 功能    :   将unicode编码转换为GBK编码 
  223. * 参数    :   unicode 
  224. * 返回    :   GBK  
  225. * 依赖    :   底层读写函数 
  226. * 作者    :   cp1300@139.com 
  227. * 时间    :   20120602 
  228. * 最后修改时间 : 20120602 
  229. * 说明    :   需要flash中的码表支持 
  230.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  231. *************************************************************************************************************************/   
  232. u16 OneUNICODEtoGBK(u16 unicode)  //用二分查找算法  
  233. {  
  234.     u32 offset;  
  235.     u16 temp;  
  236.   
  237.     if(unicode<=0X9FA5)  
  238.     {  
  239.         if(unicode>=0X4E00)  
  240.             offset=unicode-0X4E00;//0x1b87      //0X4E00,汉字偏移起点  
  241.         else  
  242.             return 0x2020;      //不能显示的字符就给两个空格填充,否则乱码  
  243.     }     
  244.     else if(unicode>0X9FA5)//是标点符号  
  245.     {  
  246.         if(unicode<0XFF01||unicode>0XFF61)  
  247.             return 0x2020;//没有对应编码  //不能显示的字符就给两个空格填充,否则乱码  
  248.         offset=unicode-0XFF01+0X9FA6-0X4E00;      
  249.     }  
  250.     offset *= 2;  
  251.       
  252.     temp = wGBKs[offset];  
  253.     temp <<= 8;  
  254.     temp += wGBKs[offset+1];  
  255.     return temp;    //返回找到的编码                  
  256. }  
  257.   
  258.   
  259. #endif //GBK_UNICODE_IS_SDCARD  
  260.   
  261.   
  262.   
  263. /************************************************************************************************************************* 
  264. * 函数    :   void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt) 
  265. * 功能    :   将多个GBK编码转换为UNICODE 
  266. * 参数    :   pGBK:GBK编码缓冲区 
  267. *           pUnicode:UNCODE编码缓冲区 
  268. *           cnt:转换编码个数 
  269. * 返回    :   无    
  270. * 依赖    :   OneGBKtoUNICODE 
  271. * 作者    :   cp1300@139.com 
  272. * 时间    :   20130403 
  273. * 最后修改时间 : 20130403 
  274. * 说明    :   需要flash中的码表支持 
  275.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  276. *************************************************************************************************************************/   
  277. void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)  
  278. {  
  279.     while(cnt --)  
  280.     {  
  281.         *pUnicode = OneGBKtoUNICODE(*pGBK ++);  
  282.         pUnicode ++;  
  283.     }  
  284. }  
  285.   
  286.   
  287.   
  288.   
  289. /************************************************************************************************************************* 
  290. * 函数    :   void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt) 
  291. * 功能    :   将多个UNICODE编码转换为GBK 
  292. * 参数    :   pUnicode:UNCODE编码缓冲区 
  293. *           pGBK:GBK编码缓冲区 
  294. *           cnt:转换编码个数 
  295. * 返回    :   无    
  296. * 依赖    :   OneUNICODEtoGBK 
  297. * 作者    :   cp1300@139.com 
  298. * 时间    :   20130403 
  299. * 最后修改时间 : 20130403 
  300. * 说明    :   需要flash中的码表支持 
  301.             GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe 
  302. *************************************************************************************************************************/   
  303. void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)  
  304. {  
  305.     while(cnt --)  
  306.     {  
  307.         *pGBK = OneUNICODEtoGBK(*pUnicode ++);  
  308.         pGBK ++;  
  309.     }  
  310. }  
/*************************************************************************************************************
 * 文件名:	unicode_gbk.c
 * 功能:		汉字编码转换
 * 作者:		cp1300@139.com
 * 创建时间:	2013-04-03
 * 最后修改时间:2013-04-03
 * 详细:		需要码表支持
*************************************************************************************************************/
#include "system.h"
#include "unicode_gbk.h"



#define GBK_UNICODE_IS_SDCARD	0	//GBK,UNICODE编码表在SD卡或其它存储器中





//码表在SD卡中
#if GBK_UNICODE_IS_SDCARD

#include "ff.h"
#define GtoU	"0:/GtoU.sys" 		//GBK 转 UCICODE 编码表位置
#define UtoG	"0:/UtoG.sys"		//UCICODE 转 GBK 编码表位置

static 	FIL   GtoU_File;			//GtoU 文件工作区
static 	FIL   UtoG_File;			//UtoG 文件工作区


/*************************************************************************************************************************
* 函数	:	u8 GBK_UNICODE_Init(void)
* 功能	:	初始化GBK,UNICODE编码表
* 参数	:	无	
* 返回	:	0:初始化成功;其它:初始化失败
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	2013-04-18
* 最后修改时间 : 2013-04-18
* 说明	: 	无
*************************************************************************************************************************/ 
u8 GBK_UNICODE_Init(void)
{
 	FRESULT status;

	status = f_open(&UtoG_File, UtoG, FA_OPEN_EXISTING | FA_READ);	//以只读方式打开UNICODEtoGBK码表,打开失败返回错误
	if(status != FR_OK)	//打开失败
	{
		lcd_printf("open %s error (%d)!\r\n",UtoG, status);
		return 1;
	}

	status = f_open(&GtoU_File, GtoU, FA_OPEN_EXISTING | FA_READ);	//以只读方式打开GBKtoUNICODE码表,打开失败返回错误
	if(status != FR_OK)	//打开失败
	{
		lcd_printf("open %s error (%d)!\r\n",GtoU, status);
		return 1;
	}


	return 0;
}




/*************************************************************************************************************************
* 函数	:	u16 OneGBKtoUNICODE(u16 GBKCode)
* 功能	:	将GBK编码转换为unicode编码
* 参数	:	GBK	
* 返回	:	unicode
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	20120602
* 最后修改时间 : 20120602
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneGBKtoUNICODE(u16 GBKCode)
{
	u8 ch,cl;
	UINT bw;
	u16 data;

	ch = GBKCode >> 8;
	cl = GBKCode & 0x00ff;

	ch -= 0x81;
    cl -= 0x40;
	
	f_lseek(&GtoU_File, (ch*0xbf+cl)*2);						//文件指针调到偏移位置
	if(f_read(&GtoU_File, (u8 *)&data, 2, &bw) != FR_OK)		//读取2字节
	{
	   return 0x1fff;
	}
	
    return (ch<=0x7d && cl<=0xbe) ? data : 0x1fff;



   /*	ch = GBKCode >> 8;
	cl = GBKCode & 0x00ff;

	ch -= 0x81;
    cl -= 0x40;	
    return (ch<=0x7d && cl<=0xbe) ? wUnicodes[ch*0xbf+cl] : 0x1fff;	   */

}



/*************************************************************************************************************************
* 函数	:	u16 OneUNICODEtoGBK(u16 unicode)
* 功能	:	将unicode编码转换为GBK编码
* 参数	:	unicode
* 返回	:	GBK	
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	20120602
* 最后修改时间 : 20120602
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneUNICODEtoGBK(u16 unicode)  //用二分查找算法
{
	u32 offset;
	u16 temp;
	UINT bw;
	u8 buff[2];

	if(unicode<=0X9FA5)
	{
		if(unicode>=0X4E00)
			offset=unicode-0X4E00;//0x1b87		//0X4E00,汉字偏移起点
		else
			return 0x2020;		//不能显示的字符就给两个空格填充,否则乱码
	}	
	else if(unicode>0X9FA5)//是标点符号
	{
		if(unicode<0XFF01||unicode>0XFF61)
			return 0x2020;//没有对应编码	//不能显示的字符就给两个空格填充,否则乱码
		offset=unicode-0XFF01+0X9FA6-0X4E00;    
	}
	offset *= 2;


	f_lseek(&UtoG_File, offset);						//文件指针调到偏移位置
	if(f_read(&UtoG_File, buff, 2, &bw) != FR_OK)	//读取2字节
	{
	   return 0x2020;
	}

	temp = buff[0];
	temp <<= 8;
	temp += buff[1];
	return temp;	//返回找到的编码				 
}












#else								//码表直接在代码中
#include "unicode_gbk_code.h"


/*************************************************************************************************************************
* 函数	:	u8 GBK_UNICODE_Init(void)
* 功能	:	初始化GBK,UNICODE编码表
* 参数	:	无	
* 返回	:	0:初始化成功;其它:初始化失败
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	2013-04-18
* 最后修改时间 : 2013-04-18
* 说明	: 	无
*************************************************************************************************************************/ 
u8 GBK_UNICODE_Init(void)
{
	return 0;
}




/*************************************************************************************************************************
* 函数	:	u16 OneGBKtoUNICODE(u16 GBKCode)
* 功能	:	将GBK编码转换为unicode编码
* 参数	:	GBK	
* 返回	:	unicode
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	20120602
* 最后修改时间 : 20120602
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneGBKtoUNICODE(u16 GBKCode)
{
	u8 ch,cl;

	ch = GBKCode >> 8;
	cl = GBKCode & 0x00ff;

	ch -= 0x81;
    cl -= 0x40;
    return (ch<=0x7d && cl<=0xbe) ? wUnicodes[ch*0xbf+cl] : 0x1fff;

}



/*************************************************************************************************************************
* 函数	:	u16 OneUNICODEtoGBK(u16 unicode)
* 功能	:	将unicode编码转换为GBK编码
* 参数	:	unicode
* 返回	:	GBK	
* 依赖	:	底层读写函数
* 作者	:	cp1300@139.com
* 时间	:	20120602
* 最后修改时间 : 20120602
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneUNICODEtoGBK(u16 unicode)  //用二分查找算法
{
	u32 offset;
	u16 temp;

	if(unicode<=0X9FA5)
	{
		if(unicode>=0X4E00)
			offset=unicode-0X4E00;//0x1b87		//0X4E00,汉字偏移起点
		else
			return 0x2020;		//不能显示的字符就给两个空格填充,否则乱码
	}	
	else if(unicode>0X9FA5)//是标点符号
	{
		if(unicode<0XFF01||unicode>0XFF61)
			return 0x2020;//没有对应编码	//不能显示的字符就给两个空格填充,否则乱码
		offset=unicode-0XFF01+0X9FA6-0X4E00;    
	}
	offset *= 2;
	
	temp = wGBKs[offset];
	temp <<= 8;
	temp += wGBKs[offset+1];
	return temp;	//返回找到的编码				 
}


#endif //GBK_UNICODE_IS_SDCARD



/*************************************************************************************************************************
* 函数	:	void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)
* 功能	:	将多个GBK编码转换为UNICODE
* 参数	:	pGBK:GBK编码缓冲区
* 			pUnicode:UNCODE编码缓冲区
* 			cnt:转换编码个数
* 返回	:	无	
* 依赖	:	OneGBKtoUNICODE
* 作者	:	cp1300@139.com
* 时间	:	20130403
* 最后修改时间 : 20130403
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)
{
	while(cnt --)
	{
		*pUnicode = OneGBKtoUNICODE(*pGBK ++);
		pUnicode ++;
	}
}




/*************************************************************************************************************************
* 函数	:	void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)
* 功能	:	将多个UNICODE编码转换为GBK
* 参数	:	pUnicode:UNCODE编码缓冲区
* 			pGBK:GBK编码缓冲区
* 			cnt:转换编码个数
* 返回	:	无	
* 依赖	:	OneUNICODEtoGBK
* 作者	:	cp1300@139.com
* 时间	:	20130403
* 最后修改时间 : 20130403
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)
{
	while(cnt --)
	{
		*pGBK = OneUNICODEtoGBK(*pUnicode ++);
		pGBK ++;
	}
}

  1. /************************************************************************************************************* 
  2.  * 文件名: unicode_gbk.h 
  3.  * 功能:      汉字编码转换 
  4.  * 作者:      cp1300@139.com 
  5.  * 创建时间:    2013-04-03 
  6.  * 最后修改时间:2013-04-03 
  7.  * 详细:      需要码表支持 
  8. *************************************************************************************************************/  
  9. #ifndef UNICODE_GBK_H_  
  10. #define UNICODE_GBK_H_  
  11. #include "system.h"  
  12.   
  13. u8 GBK_UNICODE_Init(void);  
  14. u16 OneGBKtoUNICODE(u16 GBKCode);  
  15. u16 OneUNICODEtoGBK(u16 unicode);  
  16.   
  17. void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt);   //将多个GBK编码转换为UNICODE  
  18. void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt);   //将多个UNICODE编码转换为GBK  
  19.   
  20.   
  21. #endif /*UNICODE_GBK_H_*/  
/*************************************************************************************************************
 * 文件名:	unicode_gbk.h
 * 功能:		汉字编码转换
 * 作者:		cp1300@139.com
 * 创建时间:	2013-04-03
 * 最后修改时间:2013-04-03
 * 详细:		需要码表支持
*************************************************************************************************************/
#ifndef UNICODE_GBK_H_
#define UNICODE_GBK_H_
#include "system.h"

u8 GBK_UNICODE_Init(void);
u16 OneGBKtoUNICODE(u16 GBKCode);
u16 OneUNICODEtoGBK(u16 unicode);

void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt);	//将多个GBK编码转换为UNICODE
void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt);	//将多个UNICODE编码转换为GBK


#endif /*UNICODE_GBK_H_*/

短信接收

  1. if(SIM900_GetSmsNum() > 0)   //有消息  
  2.                 {  
  3.                     uart_printf("有短信需要读取!\r\n");  
  4.                     SIM900_TestAT(100);  
  5.                     error = SIM900_GetUnreadSMS(SmsPduBuff, PDU_BUFF_SIZE, &cnt);       //读取SIM900所有的未读短信                     
  6.                     if(error == AT_RETURN_OK)  
  7.                     {  
  8.                         p = (char *)SmsPduBuff;                       
  9.                         while(1)                                                        //循环解析所有短信  
  10.                         {  
  11.                             p = (char *)strstr(p, "+CMGL:");  
  12.                             if(p == NULL) break;      
  13.                             else  
  14.                             {  
  15.                                 if(GSM_ParsePDUSMS(p, SMS_Buff,cnt-((u32)p - (u32)SmsPduBuff) , &SMS_Info) ==TRUE)  
  16.                                 {  
  17.                                     uart_printf("\r\n***************************************************\r\n");  
  18.                                     uart_printf("短信索引:%d\r\n",SMS_Info.IndexNum);           //打印短信索引  
  19.                                     uart_printf("电话号码:%s\r\n",SMS_Info.NumBuff);            //打印电话号码  
  20.                                     uart_printf("发送时间:20%d-%d-%d %d:%d:%d\r\n", SMS_Info.Timer.Year, SMS_Info.Timer.Month, SMS_Info.Timer.Day, SMS_Info.Timer.Hour, SMS_Info.Timer.Minute, SMS_Info.Timer.Second);              //打印发送时间  
  21.                                     uart_printf("短信长度:%d\r\n",SMS_Info.SMS_Size);           //打印发送时间      
  22.                                     uart_printf("短信内容:%s\r\n",SMS_Buff);                    //短信内容  
  23.                                     uart_printf("***************************************************\r\n\r\n");   







转载地址:http://blog.csdn.net/cp1300/article/details/28850709

  1.                                       
if(SIM900_GetSmsNum() > 0)	//有消息
				{
					uart_printf("有短信需要读取!\r\n");
					SIM900_TestAT(100);
					error = SIM900_GetUnreadSMS(SmsPduBuff, PDU_BUFF_SIZE, &cnt);		//读取SIM900所有的未读短信					
					if(error == AT_RETURN_OK)
					{
						p = (char *)SmsPduBuff;						
						while(1)														//循环解析所有短信
						{
							p = (char *)strstr(p, "+CMGL:");
							if(p == NULL) break;	
							else
							{
								if(GSM_ParsePDUSMS(p, SMS_Buff,cnt-((u32)p - (u32)SmsPduBuff) , &SMS_Info) ==TRUE)
								{
									uart_printf("\r\n***************************************************\r\n");
									uart_printf("短信索引:%d\r\n",SMS_Info.IndexNum);			//打印短信索引
									uart_printf("电话号码:%s\r\n",SMS_Info.NumBuff);			//打印电话号码
									uart_printf("发送时间:20%d-%d-%d %d:%d:%d\r\n", SMS_Info.Timer.Year, SMS_Info.Timer.Month, SMS_Info.Timer.Day, SMS_Info.Timer.Hour, SMS_Info.Timer.Minute, SMS_Info.Timer.Second);				//打印发送时间
									uart_printf("短信长度:%d\r\n",SMS_Info.SMS_Size);			//打印发送时间	
									uart_printf("短信内容:%s\r\n",SMS_Buff);					//短信内容
									uart_printf("***************************************************\r\n\r\n");	
									

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值