下面是对本例程软件的主要数据结构和核心函数的介绍:
数据结构
// 用户信息编码方式
#define GSM_7BIT 0
#define GSM_8BIT 4
#define GSM_UCS2 8
// 短消息参数结构,编码/解码共用
// 其中,字符串以0结尾
typedef struct
{
char SCA[16]; // 短消息服务中心号码(SMSC地址)
char TPA[16]; // 目标号码或回复号码(TP-DA或TP-RA)
char TP_PID; // 用户信息协议标识(TP-PID)
char TP_DCS; // 用户信息编码方式(TP-DCS)
char TP_SCTS[16]; // 服务时间戳字符串(TP_SCTS), 接收时用到
char TP_UD[161]; // 原始用户信息(编码前或解码后的TP-UD)
char index; // 短消息序号,在读取时用到
} SM_PARAM;
发送短消息
发送按钮对应的函数为CSMSControlDlg::OnSendButton,它读取用户输出并根据目标电话号码和短信息内容形成SM_PARAM(源PDU参数)的内容,接着进行发送:
void CSMSControlDlg::OnSendButton()
{
// TODO: Add your control notification handler code here
//获得用户输入
CString desPhoneNum;
CString smsContent;
GetDlgItemText(IDC_PHONENUM_EDIT,desPhoneNum);
GetDlgItemText(IDC_SMSCONTENT_EDIT,smsContent);
//填充SM_PARAM结构体内容
SM_PARAM smParam;
smParam = CreateSMPARAMStruct(desPhoneNum,smsContent);
//发送短信息
gsmSendMessage(smParam);
}
其中调用的gsmSendMessage函数体现了串口通信的核心内容,它按照第1节阐述的GSM模块发送短消息的串口控制流程进行短信的发送:
BOOL gsmSendMessage(const SM_PARAM *pSrc // pSrc: 源PDU参数指针)
{
int nPduLength; // PDU串长度
unsigned char nSmscLength; // SMSC串长度
int nLength; // 串口收到的数据长度
char cmd[16]; // 命令串
char pdu[512]; // PDU串
char ans[128]; // 应答串
nPduLength = gsmEncodePdu(pSrc, pdu); // 根据PDU参数,编码PDU串
strcat(pdu, "\x01a"); // 以Ctrl-Z结束
gsmString2Bytes(pdu, &nSmscLength, 2); // 取PDU串中的SMSC信息长度
nSmscLength++; // 加上长度字节本身
// 命令中的长度,不包括SMSC信息长度,以数据字节计
sprintf(cmd, "AT+CMGS=%d\r", nPduLength / 2-nSmscLength); // 生成命令
WriteComm(cmd, strlen(cmd)); // 先输出命令串
nLength = ReadComm(ans, 128); // 读应答数据
// 根据能否找到"\r\n> "决定成功与否
if (nLength == 4 && strncmp(ans, "\r\n> ", 4) == 0)
{
WriteComm(pdu, strlen(pdu)); // 得到肯定回答,继续输出PDU串
nLength = ReadComm(ans, 128); // 读应答数据
// 根据能否找到"+CMS ERROR"决定成功与否
if (nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
{
return TRUE;
}
}
return FALSE;
}
读取短消息
点击"接收"按钮会通过gsmReadMessage函数的调用获得所有短消息,最后在列表控件中显示所有短信:
void CSMSControlDlg::OnRecvButton()
{
// TODO: Add your control notification handler code here
SM_PARAM smParam[100];//短信缓冲区
int smsNum;//短信条数
smsNum = gsmReadMessage(smParam);//读取短信
//显示短信
for(int i=0;i<smsNum;i++)
{
m_recvlist.AddString(CString(smsNum[i].TPA)+smsNum[i].TP_UD);
}
}
其中调用的gsmReadMessage函数完成最核心的短信接收功能,它按照第1节阐述的GSM模块接收短消息的串口控制流程进行短信的接收:
// 参数:pMsg 短消息缓冲区,必须足够大
// 返回:短消息条数
int gsmReadMessage(SM_PARAM* pMsg)
{
int nLength; // 串口收到的数据长度
int nMsg; // 短消息计数值
char* ptr; // 内部用的数据指针
char cmd[16]; // 命令串
char ans[1024]; // 应答串
nMsg = 0;
ptr = ans;
sprintf(cmd, "AT+CMGL\r"); // 生成命令,用+CMGL可一次性读出全部短消息
WriteComm(cmd, strlen(cmd)); // 输出命令串
nLength = ReadComm(ans, 1024); // 读应答数据
// 根据能否找到"+CMS ERROR"决定成功与否
if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
{
// 循环读取每一条短消息, 以"+CMGL:"开头
while((ptr = strstr(ptr, "+CMGL:")) != NULL)
{
ptr += 6; // 跳过"+CMGL:"
sscanf(ptr, "%d", &pMsg->index); // 读取序号
ptr = strstr(ptr, "\r\n"); // 找下一行
ptr += 2; // 跳过"\r\n"
gsmDecodePdu(ptr, pMsg); // PDU串解码
pMsg++; // 准备读下一条短消息
nMsg++; // 短消息计数加1
}
}
return nMsg;
}
