📄 modemgtm900.c
字号:
/****************************************Copyright(c)**************************
**
**
**--------------文件信息-------------------------------------------------------
**文 件 名: modemGTM900.c
**创 建 人: 杨林军
**最 新 版 本: 1.0
**最后修改日期:
**描 述: 华为modemGTM900模块的驱动,包含GPRS。
**
**--------------历史版本信息---------------------------------------------------
** 创建人: 杨林军
** 版 本: 1.0
** 日 期:
** 描 述: 原始版本
**
**--------------当前版本修订---------------------------------------------------
** 修改人:
** 日 期:
** 描 述:
**
**-----------------------------------------------------------------------------
******************************************************************************/
#define MODEM_GLOBAL
#include "config.h"
#include <stdlib.h>
#define GSM_8BIT 0x04
#define GSM_7BIT 0x00
static void TaskEXTUARTARcv(void *pdata);
INT8U SMSDelCnt;
//static INT32U gResetHot; //热启动标志
INT8U modemState,modemStatePrv;
#define GPRSBUF_LEN 512
#ifndef EXTUARTATASK_STK_SIZE
#define EXTUARTATASK_STK_SIZE 1024
#endif
static OS_STK TaskEXTUARTAStk[EXTUARTATASK_STK_SIZE];
/*******************************************************************************
* 设置Modem状态
*
* Description: 设置Modem状态
*
* Arguments : enum state
*
* Returns : 无
*******************************************************************************/
void setModemStat(INT8U mState)
{
modemStatePrv = modemState;
modemState = mState;
}
/*******************************************************************************
* 查询Modem状态
*
* Description: 查询Modem状态
*
* Arguments : enum state
*
* Returns : 无
*******************************************************************************/
INT8U GetModemStat(void)
{
#if EQUIP_TYPE == SLAVE
return MODEM_SMS; //对于从设备,总是设定modem状态为sms状态
#endif
return modemState;
}
/*******************************************************************************
* Description: modem initialize
*
* Arguments : none
*
* Returns : none
*
* Note :
*******************************************************************************/
void ModemInit(void)
{
INT8U err;
setModemStat(MODEM_INVALID);
FlagModemSmsRcv = 0;
SMSDelCnt = 0;
SMSSendDelay = 0;
SmsSendSpan = 5;
DataFlag = 0;
while(EXTUARTAInit(9600,UART_NONE) == FALSE);
err = OSTaskCreate(TaskEXTUARTARcv,(void *)0, //创建扩展串口A接收任务
&TaskEXTUARTAStk[EXTUARTATASK_STK_SIZE-1],
EXTUART_RCV_TASK_PRIO);
while(err != OS_NO_ERR);
ResetSem = OSSemCreate(NULL);
while( ResetSem == NULL);
}
/*
********************************************************************************
** 函数名称: resetModem
** 功能描述: Modem复位函数,完成对modem的复位和一些默认配置方式配置
GTM900B似乎不支持热复位,AT+CFUN的第二个参数没有1。
** 输 入: *pdata
** 输 出: 无
**
** 全局变量:
** 调用模块:
********************************************************************************
*/
void resetModem(void)
{
INT8U err,i = 0;
#ifdef DEBUG_MODEM
printf("\r\nModem reset.%s, line %u\n",__FILE__, __LINE__ );
#endif
for(i = 0;i < 5; i++)
{
{
memset(ModemInfo,0,10); //信源信息清0
ModemInfo[6] = 0X80;
// SetupBaudA(9600,UART_NONE);
MCR_Uart_A |= 0x0a; // A口RTS写"1",引脚出"0",Modem断电
IO0DIR |= 1 << 17; //P0.17设置为输出,P0.17控制IGT
IO0SET = 1 << 17; //IGT高电平
OSTimeDly(OS_TICKS_PER_SEC); //延时1s
IO0CLR = 1 << 17; //低电平
OSTimeDly(OS_TICKS_PER_SEC/200); //延时5ms
MCR_Uart_A &= 0x09; // A口RTS写"0",引脚出"1",Modem上电
OSTimeDly(OS_TICKS_PER_SEC/20); //延时50ms
IO0SET = 1 << 17; //IGT高电平
OSTimeDly(OS_TICKS_PER_SEC/5); //延时200ms
OSTimeDlyHMSM(0,0,10,0);//延时10秒
OSSemPend(EXTUARTSemShareA,0,&err);
EXTUARTWriteA((INT8U *)ST_M_IPR,strlen((const char *)ST_M_IPR)); //set modem baudrate
#ifdef DEBUG_MODEM
printf("send AT command: %s \n", ST_M_IPR);
#endif
EXTUARTPutchA(0x0a);
OSTimeDly(OS_TICKS_PER_SEC/2);
SetupBaudA(9600,UART_NONE);
EXTUARTPutchA('\r');
EXTUARTWriteA((INT8U *)ST_M_ATAT,strlen((const char *)ST_M_ATAT)); //test AT command
OSTimeDly(OS_TICKS_PER_SEC/20);
while(OSSemAccept(ResetSem) != NULL);
OSTimeDly(OS_TICKS_PER_SEC/20);
EXTUARTWriteA((INT8U *)ST_M_V0S0,strlen((const char *)ST_M_V0S0)); //设置回显,应答方式,接听铃响次数
OSSemPost(EXTUARTSemShareA);
OSSemPend(ResetSem, OS_TICKS_PER_SEC*3, &err);
if(err == OS_TIMEOUT)
{
setModemStat(MODEM_INVALID);
#ifdef DEBUG_MODEM
printf("Modem no echo。%s, line %u\n",__FILE__, __LINE__ );
#endif
MCR_Uart_B = 0x08; // B口DTR写"0",引脚出"1",Modem断电
return;
}
setModemStat(MODEM_INITIALIZING);
#ifdef DEBUG_MODEM
printf("Modem initializing %s, line %u\n",__FILE__, __LINE__ );
#endif
OSTimeDlyHMSM(0,0,5,0);//延时10秒
}
OSSemPend(EXTUARTSemShareA,0,&err);
OSTimeDlyHMSM(0,1,0,0); //延时1分钟
while(OSSemAccept(ResetSem) != NULL);
EXTUARTWriteA((INT8U *)ST_EN_BAND,strlen((const char *)ST_EN_BAND)); //设置modem工作频段 自动锁频到GSM900
#ifdef DEBUG_MODEM
printf("send AT command: %s \n", ST_EN_BAND);
#endif
OSSemPend(ResetSem, OS_TICKS_PER_SEC *30, &err);
if(err == OS_TIMEOUT)
continue;
EXTUARTWriteA((INT8U *)ST_M_COPS,strlen((const char *)ST_M_COPS));
#ifdef DEBUG_MODEM
printf("send AT command: %s \n", ST_M_COPS);
#endif
OSSemPend(ResetSem, OS_TICKS_PER_SEC *30, &err);
if(err == OS_TIMEOUT)
continue;
EXTUARTWriteA((INT8U *)ST_M_CLIP,strlen((const char *)ST_M_CLIP)); //设置显示主叫识别
OSSemPend(ResetSem, OS_TICKS_PER_SEC * 4, &err);
if(err == OS_TIMEOUT)
{
continue;
}
EXTUARTWriteA((INT8U *)ST_SMS_CMGF,strlen((const char *)ST_SMS_CMGF)); //设置短信格式
OSSemPend(ResetSem, OS_TICKS_PER_SEC * 4, &err);
if(err == OS_TIMEOUT)
{
continue;
}
EXTUARTWriteA((INT8U *)ST_SMS_CPMS,strlen((const char *)ST_SMS_CPMS));//设置短信存储位置
#ifdef DEBUG_MODEM
printf("send AT command: %s \n", ST_SMS_CPMS);
#endif
OSSemPend(ResetSem, OS_TICKS_PER_SEC * 4, &err);
if(err == OS_TIMEOUT)
{
continue;
}
EXTUARTWriteA((INT8U *)ST_SMS_CNMI,strlen((const char *)ST_SMS_CNMI));//设置收到短信后modem主动向CPU发送收到的短信
OSSemPend(ResetSem, OS_TICKS_PER_SEC * 6, &err);
if(err == OS_TIMEOUT)
{
continue;
}
EXTUARTWriteA((INT8U *)"AT+CNMI?\r",9);
break;
}
if(i < 5)
{
setModemStat(MODEM_SMS);
#ifdef DEBUG_MODEM
printf("Modem reset sucessfully.%s, line %u\n",__FILE__, __LINE__ );
#endif
OSTimeDly(OS_TICKS_PER_SEC/10);
}
else
{
//gResetHot = 0;
#ifdef DEBUG_MODEM
printf("Modem reset failed %s, line %u\n",__FILE__, __LINE__ );
#endif
}
OSSemPost(EXTUARTSemShareA);
}
/*******************************************************************************
**函数名称:void ReadTel(PS_X_PACKET *pkt)
**函数功能:提取电话号码,包括接入码和国家代码
**arguments: src 短消息源地址
dest 号码存放地址
*******************************************************************************/
void ReadTel(INT8U *src,INT8U *Dest)
{
INT16U i = 0;
INT8U j = 0;
memset(Dest,0x00,20);
while((src[i] != '"' ) && (i < 30)) //找第一个引号"
{
i ++;
}
if(i < 30)
{
i ++;
for(j = 0; j < 20; j ++) //copy包括接入码和国家区号的电话号码
{
Dest[j] = src[i++];
if((src[i] < 0x30) || (src[i] > 0x39))
break;
}
}
}
/******************************************************************************
** 函数名称: ModemSMSPro
** 功能描述: 对接收到的短信进行处理,解码 这个函数其实应该放到app中
******************************************************************************/
BOOLEAN ModemSMSPro(X_PACKET *pkt,INT8U flag)
{
INT8U i,j,tmplen,smsIndex[1][4];
INT8U *ptr,*ptr1;
DATACONV crc;
i = 5;
if(flag == 1)
{
memset(pkt->Info.telNum,0x00,20);
ReadTel(&pkt->pBuf[5],pkt->Info.telNum);
}
else
{
while((pkt->pBuf[i] < 0x30) || (pkt->pBuf[i] > 0x39))
i ++;
for(j = 0; j < 3; j ++) //读取本条短信的索引号
{
smsIndex[SMSDelCnt][j] = pkt->pBuf[i ++];
if(pkt->pBuf[i] == ',') //逗号截至
{
smsIndex[SMSDelCnt][j + 1] = '\r';
smsIndex[SMSDelCnt][j + 2] = '\0';
break;
}
}
SMSDelCnt ++;;
i += 6;
while(pkt->pBuf[i] != ',' )
{
i ++;
}
i ++;
ReadTel(&pkt->pBuf[i],pkt->Info.telNum);
//读到一条短信后立刻删除本条短信
// OSSemPend(EXTUARTSemShareA,0,&i);
// EXTUARTWriteA((INT8U *)ST_SMS_CMGD,strlen((const char *)ST_SMS_CMGD));
// EXTUARTWriteA(smsIndex,strlen((const char *)smsIndex));
// OSSemPost(EXTUARTSemShareA);
}
ptr = (INT8U *)strchr((const char *)&pkt->pBuf[20],'X'); //查找内容中的起始字符'X'
if(ptr != NULL)
{
ptr ++;
ptr1 = (INT8U *)strchr((const char *)ptr,'X'); //查找内容中的结束字符'X'
if(ptr1 != NULL)
{
tmplen = (INT8U)(ptr1 - ptr);
tmplen = (tmplen/2) * 2;
if(tmplen >= 28) //命令包除头尾标志外的最短长度
{
Ascii2ToHex(&pkt->pktCmd.version,ptr,24);
if(pkt->pktCmd.cmdId == 0x61)
{
memcpy(pkt->pBuf,ptr+24,30);
Ascii2ToHex(&pkt->pBuf[30],ptr+54,6);
tmplen = (tmplen - 30) / 2 - 2 + 30; //长度不包括CRC
}
else
{
Ascii2ToHex(pkt->pBuf,ptr+24,tmplen - 24);
tmplen = tmplen/2 - 2; //长度不包括CRC
}
pkt->Info.bufLen = tmplen; //该长度仅表示AP层协议包长度,不包括CRC
ptr1 = &pkt->pktCmd.version;
crc.chr[0] = *(ptr1 + tmplen);
crc.chr[1] = *(ptr1 + tmplen + 1);
if(crc.wrd[0] == calculateCRC(&pkt->pktCmd.version,tmplen))
{
if(AuthPcktBuf(pkt) == FALSE)
{
#ifdef DEBUG_MODEM
printf("error phone number,discard %s, line %u\n",__FILE__, __LINE__ );
#endif
return FALSE;
}
pkt->Info.bufLen -= 2;
return TRUE;
}
else
{
#ifdef DEBUG_MODEM
printf("message CRC error %s, line %u\n",__FILE__, __LINE__ );
#endif
}
}
}
}
#ifdef DEBUG_MODEM
printf("message content error\n");
#endif
return FALSE;
}
/*
********************************************************************************
** 函数名称: ReadEquipInfo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -