⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modemgtm900.c

📁 华为GSM modem GTM900B的驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************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 + -