?? 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 + -