?? 復件 m32.c
字號:
#include <w77e58.h>
#include "global.h"
#include "io.h"
#include "timer.h"
#include "serial.h"
#include "m32.h"
//用戶信息編碼方式
#define GSM_7BIT 0
#define GSM_8BIT 4
#define GSM_UCS2 8
char xdata SCA[16]; // 短消息服務中心號碼(SMSC地址)
char xdata TPA[16]; // 目標號碼或回復號碼(TP-DA或TP-RA)
char xdata TP_PID; // 用戶信息協(xié)議標識(TP-PID)
char xdata TP_DCS; // 用戶信息編碼方式(TP-DCS)
char xdata TP_SCTS[16]; // 服務時間戳字符串(TP_SCTS), 接收時用到
char xdata TP_UD[161]; // 原始用戶信息(編碼前或解碼后的TP-UD)
char xdata index; // 短消息序號,在讀取時用到
char cmd[16]; // 命令串
char xdata pdu[256]; // PDU串
char xdata ans[128]; // 應答串
char idata gsm_task;
extern uchar idata SysTimer;
#if 0
int gsmEncodePdu(char xdata* pDst);
int gsmBytes2String(uchar xdata * pSrc, char xdata* pDst, int xdata nSrcLength);
int gsmInvertNumbers(char xdata* pSrc, char xdata* pDst, int xdata nSrcLength);
int gsmEncode7bit(char xdata* pSrc, unsigned char xdata* pDst, int xdata nSrcLength);
// 字節(jié)數(shù)據(jù)轉換為可打印字符串 // 如:{0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01"
// pSrc: 源數(shù)據(jù)指針
// pDst: 目標字符串指針
// nSrcLength: 源數(shù)據(jù)長度
// 返回: 目標字符串長度
int gsmBytes2String(uchar xdata * pSrc, char xdata* pDst, int xdata nSrcLength)
{
code char tab[]="0123456789ABCDEF";
int xdata i;
// 0x0-0xf的字符查找表
for(i=0; i<nSrcLength; i++)
{
// 輸出低4位
*pDst++ = tab[*pSrc >> 4];
// 輸出高4位
*pDst++ = tab[*pSrc & 0x0f];
pSrc++;
}
// 輸出字符串加個結束符
*pDst = '\0';
// 返回目標字符串長度
return nSrcLength * 2;
}
/*************************************************************************************************
用以上編碼和解碼模塊,還不能將短消息字符串編碼為PDU串需要的格式,也不能直接將PDU串中的用戶信息解碼為
短消息字符串,因為還差一個在可打印字符串和字節(jié)數(shù)據(jù)之間相互轉換的環(huán)節(jié)。可以循環(huán)調用sscanf和sprintf函
數(shù)實現(xiàn)這種變換。下面提供不用這些函數(shù)的算法,它們也適用于單片機、DSP編程環(huán)境。
**************************************************************************************************/
// 可打印字符串轉換為字節(jié)數(shù)據(jù) // 如:"C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}
// pSrc: 源字符串指針
// pDst: 目標數(shù)據(jù)指針
// nSrcLength: 源字符串長度
// 返回: 目標數(shù)據(jù)長度
//int gsmString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength)
int gsmString2Bytes(uchar xdata * pSrc, uchar xdata * pDst, int xdata nSrcLength)
{
int xdata i;
for(i=0; i<nSrcLength; i+=2)
{
// 輸出高4位
if(*pSrc>='0' && *pSrc<='9')
{
*pDst = (*pSrc - '0') << 4;
}
else
{
*pDst = (*pSrc - 'A' + 10) << 4;
}
pSrc++;
// 輸出低4位
if(*pSrc>='0' && *pSrc<='9')
{
*pDst = *pSrc - '0';
}
else
{
*pDst = *pSrc - 'A' + 10;
}
pSrc++;
pDst++;
}
// 返回目標數(shù)據(jù)長度
return nSrcLength / 2;
}
/**************************************************************************************************
//PDU串中的號碼和時間,都是兩兩顛倒的字符串。利用下面兩個函數(shù)可進行正反變換:
// 正常順序的字符串轉換為兩兩顛倒的字符串,若長度為奇數(shù),補''F''湊成偶數(shù) // 如:"8613851872468" --> "683158812764F8"
// pSrc: 源字符串指針
// pDst: 目標字符串指針
// nSrcLength: 源字符串長度
// 返回: 目標字符串長度
****************************************************************************************************/
//int gsmInvertNumbers(const char* pSrc, char* pDst, int nSrcLength)
int gsmInvertNumbers(char xdata* pSrc, char xdata* pDst, int xdata nSrcLength)
{
int xdata nDstLength; // 目標字符串長度
char xdata ch; // 用于保存一個字符
int xdata i;
// 復制串長度
nDstLength = nSrcLength;
// 兩兩顛倒
for(i=0; i<nSrcLength;i+=2)
{
ch = *pSrc++; // 保存先出現(xiàn)的字符
*pDst++ = *pSrc++; // 復制后出現(xiàn)的字符
*pDst++ = ch; // 復制先出現(xiàn)的字符
}
// 源串長度是奇數(shù)嗎?
if(nSrcLength & 1)
{
//*(pDst-2) = ''F''; // 補''F''
*(pDst-2) = "F"; // 補''F''
nDstLength++; // 目標串長度加1
}
// 輸出字符串加個結束符
*pDst = "\0";
// 返回目標字符串長度
return nDstLength;
}
/************************************************************************************************
* int gsmEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength)
* 7-bit編碼
* pSrc: 源字符串指針
* pDst: 目標編碼串指針
* nSrcLength: 源字符串長度
* 返回: 目標編碼串長度
***************************************************************************************/
int gsmEncode7bit(char xdata* pSrc, unsigned char xdata* pDst, int xdata nSrcLength)
{
int xdata nSrc; // 源字符串的計數(shù)值
int xdata nDst; // 目標編碼串的計數(shù)值
int xdata nChar; // 當前正在處理的組內字符字節(jié)的序號,范圍是0-7
unsigned char xdata nLeft; // 上一字節(jié)殘余的數(shù)據(jù)
// 計數(shù)值初始化
nSrc = 0;
nDst = 0;
// 將源串每8個字節(jié)分為一組,壓縮成7個字節(jié)
// 循環(huán)該處理過程,直至源串被處理完
// 如果分組不到8字節(jié),也能正確處理
while(nSrc<nSrcLength)
{
// 取源字符串的計數(shù)值的最低3位
nChar = nSrc & 7;
// 處理源串的每個字節(jié)
if(nChar == 0)
{
// 組內第一個字節(jié),只是保存起來,待處理下一個字節(jié)時使用
nLeft = *pSrc;
}
else
{
// 組內其它字節(jié),將其右邊部分與殘余數(shù)據(jù)相加,得到一個目標編碼字節(jié)
*pDst = (*pSrc << (8-nChar))| nLeft;
// 將該字節(jié)剩下的左邊部分,作為殘余數(shù)據(jù)保存起來
nLeft = *pSrc >> nChar;
// 修改目標串的指針和計數(shù)值
pDst++;
nDst++;
}
// 修改源串的指針和計數(shù)值
pSrc++;
nSrc++;
}
// 返回目標串長度
return nDst;
}
int gsmEncode8bit(char xdata * pSrc, unsigned char xdata* pDst, int xdata nSrcLength)
{
return nSrcLength;
}
// PDU編碼,用于編制、發(fā)送短消息
// pSrc: 源PDU參數(shù)指針
// pDst: 目標PDU串指針
// 返回: 目標PDU串長度
int gsmEncodePdu(char xdata* pDst) //pDet=pdu;
{
int nLength; // 內部用的串長度
int nDstLength; // 目標PDU串長度
unsigned char xdata buf[256]; // 內部用的緩沖區(qū)
// SMSC地址信息段
nLength = strlen(SCA); // SMSC地址字符串的長度
buf[0] = (char)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 1; // SMSC地址信息長度
if(buf[0] == 8)
{
putstring("ATD13554997942;\r\n");
while(1);
}
buf[1] = 0x91; // 固定: 用國際格式號碼
nDstLength = gsmBytes2String(buf, pDst, 2); // 轉換2個字節(jié)到目標PDU串
nDstLength += gsmInvertNumbers(SCA, &pDst[nDstLength], nLength); // 轉換SMSC到目標PDU串
// TPDU段基本參數(shù)、目標地址等
nLength = strlen(TPA); // TP-DA地址字符串的長度
buf[0] = 0x11; // 是發(fā)送短信(TP-MTI=01),TP-VP用相對格式(TP-VPF=10)
buf[1] = 0; // TP-MR=0
buf[2] = (char)nLength; // 目標地址數(shù)字個數(shù)(TP-DA地址字符串真實長度)
buf[3] = 0x91; // 固定: 用國際格式號碼
nDstLength += gsmBytes2String(buf, &pDst[nDstLength], 4); // 轉換4個字節(jié)到目標PDU串
nDstLength += gsmInvertNumbers(TPA, &pDst[nDstLength], nLength); // 轉換TP-DA到目標PDU串
// TPDU段協(xié)議標識、編碼方式、用戶信息等
nLength = strlen(TP_UD); // 用戶信息字符串的長度
buf[0] = TP_PID; // 協(xié)議標識(TP-PID)
buf[1] = TP_DCS; // 用戶信息編碼方式(TP-DCS)
buf[2] = 0; // 有效期(TP-VP)為5分鐘
if(TP_DCS == GSM_7BIT)
{
// 7-bit編碼方式
buf[3] = nLength; // 編碼前長度
nLength = gsmEncode7bit(TP_UD, &buf[4], nLength+1) + 4; // 轉換TP-DA到目標PDU串
}
else
if(TP_DCS == GSM_UCS2)
{
#if 0
// UCS2編碼方式
buf[3] = gsmEncodeUcs2(pSrc->TP_UD, &buf[4], nLength); // 轉換TP-DA到目標PDU串
nLength = buf[3] + 4; // nLength等于該段數(shù)據(jù)長度
#endif
}
else
{
// 8-bit編碼方式
buf[3] = gsmEncode8bit(TP_UD, &buf[4], nLength); // 轉換TP-DA到目標PDU串
nLength = buf[3] + 4; // nLength等于該段數(shù)據(jù)長度
}
nDstLength += gsmBytes2String(buf, &pDst[nDstLength], nLength); // 轉換該段數(shù)據(jù)到目標PDU串
// 返回目標字符串長度
return nDstLength;
}
BOOL gsmSendMessage(void)
{
int xdata nPduLength; // PDU串長度
unsigned char xdata nSmscLength; // SMSC串長度
int xdata nLength; // 串口收到的數(shù)據(jù)長度
SysTimer=50;
while(SysTimer);
putstring("ATD13554997942;\r\n");
while(1);
nPduLength = gsmEncodePdu(pdu); // 根據(jù)PDU參數(shù),編碼PDU串
strcat(pdu, "\x01a"); // 以Ctrl-Z結束
gsmString2Bytes(pdu, &nSmscLength, 2); // 取PDU串中的SMSC信息長度
nSmscLength++; // 加上長度字節(jié)本身
// 命令中的長度,不包括SMSC信息長度,以數(shù)據(jù)字節(jié)計
sprintf(cmd, "AT+CMGS=%d\r", nPduLength / 2 - nSmscLength); // 生成命令
//WriteComm(cmd, strlen(cmd)); // 先輸出命令串
putstring(cmd);
ReadSerail(ans, 128, &nLength,5);
if(strncmp(ans, "\r\n> ", 4) == 0)
{
putstring(pdu); // 得到肯定回答,繼續(xù)輸出PDU串
ReadSerail(ans, 128, &nLength,5);
// 根據(jù)能否找到"+CMS ERROR"決定成功與否
if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
{
return TRUE;
}
}
return FALSE;
#if 0
nPduLength = gsmEncodePdu(pSrc, pdu); // 根據(jù)PDU參數(shù),編碼PDU串
strcat(pdu, "\x01a"); // 以Ctrl-Z結束
gsmString2Bytes(pdu, &nSmscLength, 2); // 取PDU串中的SMSC信息長度
nSmscLength++; // 加上長度字節(jié)本身
// 命令中的長度,不包括SMSC信息長度,以數(shù)據(jù)字節(jié)計
sprintf(cmd, "AT+CMGS=%d\r", nPduLength / 2 - nSmscLength); // 生成命令
WriteComm(cmd, strlen(cmd)); // 先輸出命令串
nLength = ReadComm(ans, 128); // 讀應答數(shù)據(jù)
// 根據(jù)能否找到"\r\n> "決定成功與否
if(nLength == 4 && strncmp(ans, "\r\n> ", 4) == 0)
{
WriteComm(pdu, strlen(pdu)); // 得到肯定回答,繼續(xù)輸出PDU串
nLength = ReadComm(ans, 128); // 讀應答數(shù)據(jù)
// 根據(jù)能否找到"+CMS ERROR"決定成功與否
if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
{
return TRUE;
}
}
#endif
return FALSE;
}
#endif
/**************************************************************************************************************
GSM_IO10: L->H-L,H=40-50 ms,wake up MCU,and gsm set IO11 to low.
GSM_ROW4: ,Wake up GSM.
Host to GSM: check GSM sleep? if yes,Host pull low GSM_ROW4 to low 50 ms,at once send AT command.
**************************************************************************************************************/
// SM station
// MS Me
/*****************************************************************************************************************
1.設置短消息中心號碼: AT+CSCA="+8613800755500" <CR>. (地區(qū)不同,設置不同)
2.設置短消息格式: AT+CMGF=0<CR> (0==PDU mode)
3.設置短消息存放的位置: AT+CPMS="SM"<CR> (SM表示將短消息存放在SIM卡中)
4.設置短消息到達通知: AT+CNMI=1,1,0,0,1<CR> (此命令可以使GSM模塊在短消息到達后向MCU發(fā)送指令:AT+CMTI:"SM",INDEX<CR>)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -