www.pudn.com > M26(2M).rar > QuectelM26.c, change:2016-01-20,size:22530b


/*************************************************************************************************** 
	* Copyright (c) 2016, Biohermes 
	* All rights reserved. 
	* 文件名称: QuectelM26.c 
	* 摘 要:    M26模块 
	* 当前版本: V1.0, 易建, 2016-01-05 
	* 更改记录: 无 
***************************************************************************************************/ 
#include "QuectelM26.h" 
#include<stdlib.h> 
 
#define         M26_OK                  0                               //OK 
#define         STRING_ERR              1                               //非预期返回字符串 
#define         CONNECT_ERR             2                               //与模块连接错误 
#define         QUERY_BAUD_ERR          3                               //波特率错误 
#define         CLOSE_SOCKET_ERR        4 
#define         CLOSE_CONTEXT_ERR       5 
#define         SQ_ERR                  6                               //信号查询错误 
#define         REG_ERR                 7                               //网络注册失败 
#define         GREG_ERR                8                               //GPRS附着失败 
#define         SET_CONTEXT_ERR         9 
#define         ACT_CONTEXT_ERR         10 
#define         QUERY_ACT_ERR           11 
#define         SET_SOCKET_ERR          12 
#define         ENTER_DATA_MODE_ERR     13 
#define         QUERY_SOCKET_ERR        14 
#define         RESET_ERR               15 
#define         DEFAULT_ERR             16 
#define         QUERY_PIN_ERR           17                              //无SIM卡,或SIM卡有PIN码 
#define         BACK_TO_TRAN_ACCESS_MODE_ERR    18 
#define         OVER_TIME               19 
 
#define         M26_POWER_ON            P6OUT |= BIT4 
#define         M26_POWER_OFF           P6OUT &= ~BIT4 
 
#define         M26_RESET_ON            P2OUT |= BIT6 
#define         M26_RESET_OFF           P2OUT &= ~BIT6 
 
 
//#define SMS 
#define TCP 
//#define TELL 
 
/*************************************************************************************************** 
//#define       CONTEXT_ID              1                               //Context profile ID 
//#define       APN                     *CMNET*                         //接入点名称 
***************************************************************************************************/ 
static const u8 AT_QICSGP[]   = {"AT+QICSGP=1,*CMNET*\r\n"};            //设置APN 
 
 
/*************************************************************************************************** 
//#define       IPADDRESS               *58.214.239.78*                 //IP 
//#define       REMOTE_PORT             55555                           //远程Port 
//#define       SERVICE_TYPE            *TCP*                           //Service type 
***************************************************************************************************/ 
static const u8 AT_QIOPEN[]   = {"AT+QIOPEN=*TCP*,*58.214.239.78*,55555\r\n"};  //Context profile 
 
 
/*************************************************************************************************** 
//#define       ONE_BLOCK_SIZE          10                              //一次发送数据量,单位字节 
//const u8 AT_QISEND[]   = {"AT+QISEND=CONNECT_ID,ONE_BLOCK_SIZE\r\n"}; 
***************************************************************************************************/ 
static const u8 AT_QISEND[]   = {"AT+QISEND=10\r\n"}; 
 
 
static const u8 AT_AT[]       = {"AT\r\n"};                             //连接测试命令 
static const u8 AT_ATE0[]     = {"ATE0\r\n"};                           //不需要回显 
static const u8 AT_CSQ[]      = {"AT+CSQ\r\n"};                         //查询信号强度 
static const u8 AT_QRST[]     = {"AT+QRST=1,0\r\n"};                    //模块复位 
static const u8 AT_QPOWD[]    = {"AT+QPOWD=0\r\n"};                     //关闭模块 
 
//static const u8 AT_ATV1[]     = {"ATV1\r\n"}; 
//static const u8 AT_IPR_C[]    = {"AT+IPR?\r\n"};                      //查询波特率 
static const u8 AT_CPIN_C[]   = {"AT+CPIN?\r\n"};                     //查询PIN码 
//static const u8 AT_QIACT_C[]  = {"AT+QIACT?\r\n"}; 
//static const u8 AT_AT_F[]     = {"AT&F0\r\n"};                        //模块内部数据恢复初始化 
//static const u8 AT_CMEE[]     = {"AT+CMEE=2\r\n"};                    //显示错误内容 
//static const u8 AT_QIGETERROR[] = {"AT+QIGETERROR\r\n"};              //查询错误原因 
 
static const u8 AT_QIFGCNT[]  = {"AT+QIFGCNT=0\r\n"};  
static const u8 AT_QIREGAPP[] = {"AT+QIREGAPP\r\n"}; 
static const u8 AT_CREG_C[]   = {"AT+CREG?\r\n"}; 
static const u8 AT_CGREG_C[]  = {"AT+CGREG?\r\n"}; 
static const u8 AT_QIACT[]    = {"AT+QIACT\r\n"};                       //激活指定Context profile 
static const u8 AT_QICLOSE[]  = {"AT+QICLOSE=0\r\n"};                   //关闭Socket服务 
static const u8 AT_QISTATE[]  = {"AT+QISTATE\r\n"}; 
static const u8 AT_QIDEACT[]  = {"AT+QIDEACT\r\n"};                     //关闭指定Context profile 
 
#ifdef TELL 
static const u8 AT_ATS0[]     = {"ATS0=2\r\n"}; 
#endif 
 
#ifdef SMS 
static const u8 AT_CPMS[] = {"AT+CPMS=*MT*,*MT*,*MT*\r\n"}; 
static const u8 AT_CMGF[] = {"AT+CMGF=1\r\n"}; 
static const u8 AT_CSCS[] = {"AT+CSCS=*GSM*\r\n"}; 
static const u8 AT_CSMP[] = {"AT+CSMP=17,167,0,0\r\n"}; 
static const u8 AT_CNMI[] = {"AT+CNMI=2,1,0,0,0\r\n"}; 
static const u8 AT_CMGS[] = {"AT+CMGS=*13485040690*\r\n"}; 
#endif 
 
struct retstruct 
{ 
    u8 ret1; 
    u8 ret2; 
}s_stRetData; 
 
u16 g_u16OverTimeCnt;                               //超时倒计时计数器,每秒自减1 
u8 RxDataBuff[RX_BUFF_LEN];                         //中断接收数组 
u8 g_u8RxIndexW;                                    //中断接收数组写指针 
static u8 s_u8RxIndexR;                             //中断接收数组读指针 
 
/*************************************************************************************************** 
 * 函 数 名: QuectelM26_SendCmd 
 * 功能描述: M26底层发送命令 
 * 函数说明:  
 * 调用函数: 无 
 * 全局变量: 
 * 输  入: *string 需要发送的字符串指针 
 * 返  回: 无 
***************************************************************************************************/ 
static void QuectelM26_SendCmd(const u8 *string) 
{ 
    u8 i = 0; 
     
    while (string[i] != 0) 
    { 
        if (string[i] == '*') 
        { 
            UCA0_SendByte('"'); 
        } 
        else 
        { 
            UCA0_SendByte(string[i]); 
        } 
        i++; 
    } 
    s_u8RxIndexR = 0; 
    g_u8RxIndexW = 0; 
} 
 
/*************************************************************************************************** 
 * 函 数 名: GetAckData 
 * 功能描述: 比较接收的数据和给定字符串是否相同 
 * 函数说明: 无 
 * 调用函数: 无 
 * 全局变量: 无 
 * 输  入: buff 需要比较的数组, *string给定字符串指针 
 * 返  回: 状态 
***************************************************************************************************/ 
static u8 GetAckData(u8 *string, u16 overtime) 
{ 
    u8 j=0; 
     
    g_u16OverTimeCnt = overtime; 
    while (1) 
    { 
        if (s_u8RxIndexR != g_u8RxIndexW) 
        { 
            if (string[j] == RxDataBuff[s_u8RxIndexR]) 
                j++; 
            else 
                j = 0; 
            if (string[j] == 0) 
                return M26_OK; 
            s_u8RxIndexR++; 
            if (s_u8RxIndexR > RX_BUFF_LEN-1) 
                s_u8RxIndexR = 0; 
        } 
        if (g_u16OverTimeCnt == 0)                      //超时退出 
            return OVER_TIME; 
    } 
} 
 
/*************************************************************************************************** 
 * 函 数 名: ExpectReceData 
 * 功能描述: 比较接收的数据和给定字符串是否相同,然后接收剩下的数据 
 * 函数说明: ret结构暂时只包括两个返回值。 
 * 调用函数: 无 
 * 全局变量: 无 
 * 输  入: *string给定字符串指针, overtime超时时间, ret接收数据值结构体 
 * 返  回: 状态 
***************************************************************************************************/ 
static u8 ExpectReceData(u8 *string, u16 overtime, struct retstruct* ret) 
{ 
    u8 i = 0, j = 0, k = 0; 
    u8 str[2][5];               //接收ascii码字符串缓存,暂只接收两个数据 
     
    g_u16OverTimeCnt = overtime; 
    while (1)                   //先判断前面固定字符串是否正确 
    { 
        if (s_u8RxIndexR != g_u8RxIndexW) 
        { 
            if (string[j] == RxDataBuff[s_u8RxIndexR]) 
                j++; 
            else 
                j = 0; 
            s_u8RxIndexR++; 
            if (s_u8RxIndexR > RX_BUFF_LEN-1) 
                s_u8RxIndexR = 0; 
            if (string[j] == 0) 
                break; 
        } 
        if (g_u16OverTimeCnt == 0)                      //超时退出 
            return OVER_TIME; 
    } 
    i = 0; 
    j = 1;                  //数据存放从第二个字节开始,第一个字节存放个数 
    while (1) 
    { 
        if (s_u8RxIndexR != g_u8RxIndexW) 
        { 
            if (RxDataBuff[s_u8RxIndexR] == ',') 
            { 
                str[i][0] = j - 1;              //保存接收到的字符个数 
                j = 1; 
                i++; 
            } 
            else if (RxDataBuff[s_u8RxIndexR] == '\r') 
            { 
                k = 1; 
            } 
            else if (RxDataBuff[s_u8RxIndexR] == '\n') 
            { 
                if (k) 
                { 
                    str[i][0] = j - 1;          //\r\n为结束符 
                    break; 
                } 
                else 
                { 
                    i = 0; 
                    j = 1; 
                } 
            } 
            else 
            { 
                str[i][j] = RxDataBuff[s_u8RxIndexR]; 
                j++; 
            } 
            s_u8RxIndexR++; 
            if (s_u8RxIndexR > RX_BUFF_LEN-1) 
                s_u8RxIndexR = 0; 
        } 
        if (g_u16OverTimeCnt == 0)                      //超时退出 
            return OVER_TIME; 
    } 
    if (str[0][0] == 2) 
        ret->ret1 = (str[0][1]-'0')*10 + (str[0][2]-'0'); 
    else 
        ret->ret1 = (str[0][1]-'0'); 
    if (str[1][0] == 2) 
        ret->ret2 = (str[1][1]-'0')*10 + (str[1][2]-'0'); 
    else 
        ret->ret2 = (str[1][1]-'0'); 
    return M26_OK; 
} 
 
/*************************************************************************************************** 
 * 函 数 名: QuectelM26_CheckNet 
 * 功能描述: 检测网上是否已经连通 
 * 函数说明: 无 
 * 调用函数: 无 
 * 全局变量: 无 
 * 输  入: 无 
 * 返  回: 处理结果 
***************************************************************************************************/ 
u8 QuectelM26_CheckNet(void) 
{ 
    u8 ret; 
    QuectelM26_SendCmd(AT_QISTATE);                                     //查询Socket服务状态 
    ret = ExpectReceData("\r\n+QISTATE: ", 60, &s_stRetData); 
    if (ret != M26_OK) 
        return QUERY_SOCKET_ERR; 
    else 
        return M26_OK; 
 
} 
 
/*************************************************************************************************** 
 * 函 数 名: QuectelM26_ResetModule 
 * 功能描述: 模块复位 
 * 函数说明: 无 
 * 调用函数: 无 
 * 全局变量: 无 
 * 输  入: 无 
 * 返  回: 处理结果 
***************************************************************************************************/ 
u8 QuectelM26_ResetModule(void) 
{ 
    u8 ret; 
    QuectelM26_SendCmd(AT_QRST); 
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return RESET_ERR; 
    else 
        return M26_OK; 
} 
 
/*************************************************************************************************** 
 * 函 数 名: QuectelM26_PowerDown 
 * 功能描述: 模块复掉电 
 * 函数说明: 无 
 * 调用函数: 无 
 * 全局变量: 无 
 * 输  入: 无 
 * 返  回: 处理结果 
***************************************************************************************************/ 
u8 QuectelM26_PowerDown(void) 
{ 
    u8 ret; 
    QuectelM26_SendCmd(AT_QPOWD); 
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return RESET_ERR; 
    else 
        return M26_OK; 
} 
 
/*************************************************************************************************** 
 * 函 数 名: QuectelM26_Init 
 * 功能描述: 模块初始化 
 * 函数说明: 无 
 * 调用函数: 无 
 * 全局变量: 无 
 * 输  入: 无 
 * 返  回: 处理结果 
***************************************************************************************************/ 
u8 QuectelM26_Init(void) 
{ 
    u8 ret=0 ,i=50; 
     
    M26_POWER_OFF; 
    Delay(60000);  
    Delay(60000); 
    M26_POWER_ON; 
    Delay(1000); 
    M26_RESET_ON; 
    Delay(60000);  
    Delay(60000);  
    Delay(60000);   
    M26_RESET_OFF; 
    Delay(1000); 
    Delay(60000);  
    Delay(60000);  
    Delay(60000);  
    Delay(60000);  
    Delay(60000);  
    while (i--)                                                          //连续发送10次,判断是否能连通 
    { 
        QuectelM26_SendCmd(AT_AT); 
        ret = GetAckData("AT\r\r\nOK\r\n", 2);                        //有回送和不回送两种可能 
        if (ret == M26_OK) 
            break; 
    } 
    if (ret != M26_OK) 
        return CONNECT_ERR;                                             //10次失败则认为连接失败 
    /* 
    QuectelM26_SendCmd(AT_AT_F);                                        //回复默认值 
    ret = GetAckData("AT&F0\r\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return DEFAULT_ERR; 
    */ 
    Delay(1000); 
    QuectelM26_SendCmd(AT_ATE0);                                        //设置为不回送模式 
    ret = GetAckData("ATE0\r\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return CONNECT_ERR; 
    /* 
    QuectelM26_SendCmd(AT_ATV1);                                        //确认返回”OK“ 
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return CONNECT_ERR; 
 
    QuectelM26_SendCmd(AT_CMEE);                                        // 
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return CONNECT_ERR; 
     
    QuectelM26_SendCmd(AT_IPR_C);                                       //查询波特率 
    ret = ExpectReceData("\r\n+IPR: ", 60); 
    if (ret != M26_OK) 
        return QUERY_BAUD_ERR; 
    */ 
    QuectelM26_SendCmd(AT_CPIN_C);                                      //查询SIM卡是否有PIN码 
    ret = GetAckData("\r\n+CPIN: READY\r\n\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return QUERY_PIN_ERR; 
     
    ret = QuectelM26_ConnectNet();                                      //连接网络 
    if (ret != M26_OK) 
        return ret; 
    return M26_OK; 
} 
 
/*************************************************************************************************** 
 * 函 数 名: QuectelM26_ConnectNet 
 * 功能描述: 模块连接网络 
 * 函数说明: 无 
 * 调用函数: 无 
 * 全局变量: 无 
 * 输  入: 无 
 * 返  回: 处理结果 
***************************************************************************************************/ 
u8 QuectelM26_ConnectNet(void) 
{ 
    u8 ret, i;   
     
    i = 0; 
    while (1) 
    { 
        Delay(1000); 
        QuectelM26_SendCmd(AT_CSQ);                             //查询当前信号强度 
        ret = ExpectReceData("\r\n+CSQ: ", 60, &s_stRetData); 
        if (ret==M26_OK && s_stRetData.ret1!=99 && s_stRetData.ret2!=99) 
            break; 
        /* 
        i++; 
        if (i > 50) 
            return SQ_ERR;                                      //信号查询失败 
        */ 
    } 
    i = 0; 
    while (1) 
    { 
        Delay(10000); 
        QuectelM26_SendCmd(AT_CREG_C);                          //查询注册状态 
        ret = ExpectReceData("\r\n+CREG: ", 60, &s_stRetData); 
        if (ret==M26_OK && s_stRetData.ret1==0 && (s_stRetData.ret2==1||s_stRetData.ret2==5)) 
            break; 
        i++; 
        if (i > 100) 
            return REG_ERR;                                     //网络注册失败 
    } 
     
/********************************************** TCP **********************************************/ 
    #ifdef TCP 
    i = 0; 
    while (1) 
    { 
        Delay(10000); 
        QuectelM26_SendCmd(AT_CGREG_C);                         //GPRS附着状态 
        ret = ExpectReceData("\r\n+CGREG: ", 60, &s_stRetData); 
        if (ret==M26_OK && s_stRetData.ret1==0 && (s_stRetData.ret2==1||s_stRetData.ret2==5)) 
            break; 
        i++; 
        if (i > 100) 
            return GREG_ERR;                                    //GPRS附着失败 
    } 
     
    Delay(1000); 
    QuectelM26_SendCmd(AT_QIFGCNT);                             //设置当前场景 
    ret = GetAckData("\r\nOK\r\n", 120); 
    if (ret != M26_OK) 
        return SET_CONTEXT_ERR; 
     
    Delay(1000); 
    QuectelM26_SendCmd(AT_QICSGP);                              //设置APN 
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return SET_CONTEXT_ERR; 
 
    Delay(1000); 
    QuectelM26_SendCmd(AT_QIDEACT);                             //关闭Context_profile服务 
    ret = GetAckData("\r\nDEACT OK\r\n", 190); 
    if (ret != M26_OK) 
        return CLOSE_CONTEXT_ERR; 
 
    Delay(1000); 
    QuectelM26_SendCmd(AT_QIREGAPP);                            //启动任务并设置接入点 APN、用户名和密码。 
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return ACT_CONTEXT_ERR; 
     
    Delay(1000); 
    QuectelM26_SendCmd(AT_QIACT);                               //激活移动场景 
    ret = GetAckData("\r\nOK\r\n", 300); 
    if (ret != M26_OK) 
        return ACT_CONTEXT_ERR; 
     
    Delay(1000); 
    QuectelM26_SendCmd(AT_QIOPEN);                              //启动Socket服务,连接服务器 
    ret = GetAckData("\r\nOK\r\n\r\nCONNECT OK", 120); 
    if (ret != M26_OK) 
        return SET_SOCKET_ERR; 
    else 
        return M26_OK; 
    #endif 
 
/********************************************** SMS **********************************************/ 
    #ifdef SMS 
    Delay(1000); 
    QuectelM26_SendCmd(AT_CPMS);                                      
    ret = GetAckData("\r\n+CPMS: ", 60); 
    if (ret != M26_OK) 
        return ACT_CONTEXT_ERR; 
     
    Delay(1000); 
    QuectelM26_SendCmd(AT_CMGF);                                      
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return ACT_CONTEXT_ERR; 
     
    Delay(1000); 
    QuectelM26_SendCmd(AT_CSCS);                                      
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return ACT_CONTEXT_ERR; 
     
    Delay(1000); 
    QuectelM26_SendCmd(AT_CSMP);                                      
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return ACT_CONTEXT_ERR; 
     
    Delay(1000); 
    QuectelM26_SendCmd(AT_CNMI);                                      
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return ACT_CONTEXT_ERR; 
    else 
        return M26_OK; 
    #endif 
 
/********************************************** TELL **********************************************/ 
    #ifdef TELL 
    Delay(1000); 
    QuectelM26_SendCmd(AT_ATS0);                                      
    ret = GetAckData("\r\nOK\r\n", 60); 
    if (ret != M26_OK) 
        return ACT_CONTEXT_ERR; 
    else 
        return M26_OK; 
    #endif 
} 
 
/*************************************************************************************************** 
 * 函 数 名: QuectelM26_CloseNet 
 * 功能描述: 模块关闭网络 
 * 函数说明: 无 
 * 调用函数: 无 
 * 全局变量: 无 
 * 输  入: 无 
 * 返  回: 处理结果 
***************************************************************************************************/ 
u8 QuectelM26_CloseNet(void) 
{ 
    u8 ret; 
    QuectelM26_SendCmd(AT_QICLOSE);                                     //关闭Socket服务 
    ret = GetAckData("\r\nCLOSE OK\r\n", 90); 
    if (ret != M26_OK) 
        return CLOSE_SOCKET_ERR; 
     
    QuectelM26_SendCmd(AT_QIDEACT);                                     //关闭Context_profile服务 
    ret = GetAckData("\r\nDEACT OK\r\n", 90); 
    if (ret != M26_OK) 
        return CLOSE_CONTEXT_ERR; 
    else 
        return M26_OK; 
} 
 
/*************************************************************************************************** 
 * 函 数 名: QuectelM26_SendBlock 
 * 功能描述: 模块发送数据 
 * 函数说明: 无 
 * 调用函数: 无 
 * 全局变量: 无 
 * 输  入: buff 输入缓存数据,num发送的数据数 
 * 返  回: 处理结果 
***************************************************************************************************/ 
u8 QuectelM26_SendData(u8 *buff, u16 num) 
{ 
    u8 ret; 
    QuectelM26_SendCmd(AT_QISEND);                                      //设置本次发送字节数 
    ret = GetAckData("\r\n> ", 60); 
    if (ret != M26_OK) 
        return ret;  
 
    for (u16 i=0; i<num; i++) 
        UCA0_SendByte(buff[i]);                                         //发送数据 
     
    ret = GetAckData("\r\nSEND OK\r\n", 60);                            //数据发送状态 
    if (ret != M26_OK) 
        return CONNECT_ERR; 
    else 
        return M26_OK; 
} 
 
#ifdef SMS 
u8 QuectelM26_SendMsg(u8 *string) 
{ 
    u8 ret, i; 
     
    QuectelM26_SendCmd(AT_CMGS);                                        //设置本次发送字节数 
    ret = GetAckData("\r\n> ", 60); 
    if (ret != M26_OK) 
        return ret;  
 
    while (1) 
    { 
        if (string[i] != 0) 
            UCA0_SendByte(string[i]);                                   //发送数据 
        else 
        { 
            UCA0_SendByte(0x1a);                                        //发送数据 
            break; 
        } 
        i++; 
    } 
     
    ret = GetAckData("\r\n+CMGS: \r\n", 60);                            //数据发送状态 
    while(1); 
} 
#endif 
 
/*************************************************************************************************** 
 * 函 数 名: QuectelM26_Demo 
 * 功能描述: M26测试demo 
 * 函数说明: 
 * 调用函数: 无 
 * 全局变量: 
 * 输  入: 
 * 返  回:  
***************************************************************************************************/ 
void QuectelM26_Demo(void) 
{ 
    u8 i = 0; 
    u8 buff[10]; 
    u16 j; 
 
    #ifdef TCP 
    g_u16OverTimeCnt = 0; 
    while (1) 
    { 
        if (g_u16OverTimeCnt == 0) 
        { 
             
            for (j=0; j<10; j++) 
                buff[j] = i; 
            QuectelM26_SendData(buff, 10);                                  //发送数据 
            i++; 
            g_u16OverTimeCnt = 1; 
        } 
    } 
    #endif 
     
    #ifdef SMS 
    QuectelM26_SendMsg("Biohermes Hengshang Send this sms to you, wish you have a good day.This is a test sms, if you get it, please tell LinTao");  
    #endif 
     
     
     
}