发新帖本帖赏金 36.00元(功能说明)我要提问
返回列表
打印

【原创连载】+和土匪一起玩GPRS模块

[复制链接]
楼主: 我是土匪
手机看帖
扫描二维码
随时随地手机跟帖
61
349264710| | 2015-9-19 23:43 | 只看该作者 回帖奖励 |倒序浏览
我是土匪 发表于 2015-9-6 16:36
浅谈AT用法
一、           扔砖很多人都觉得AT很简单,一个字符串发过去,剩下就是喝茶等结果。土匪今天再 ...

无OS的框架,采用消息队列+软件定时器+状态机,主要是如何判断模块返回的是一个完整的帧,如何不漏掉URC,供外部调用的接口如何处理?坐等楼主的思路。

使用特权

评论回复
62
lib6303c| | 2015-9-20 14:50 | 只看该作者
学习了,真好要使用GPRS模块!:handshake

使用特权

评论回复
63
eternity1120| | 2015-9-21 10:45 | 只看该作者
mark

使用特权

评论回复
64
木棉海| | 2015-9-23 14:39 | 只看该作者
mark,正要用

使用特权

评论回复
65
我是土匪|  楼主 | 2015-9-24 14:07 | 只看该作者
本帖最后由 我是土匪 于 2015-10-10 14:20 编辑

第三章 AT架构浅谈


一、指导思想
前面已经讲过使用AT的原则:前一条AT返回结果后,在发送下一条。
为了安全起见,增加超时机制是有必要的。
二、     应用举例
开门见山,步入正题,如何搭建一个发送AT的比较合理的架构?话题起大了,迟迟没想好如何解释,今天硬着头皮上了,目的是抛砖引玉,是交流贴。
欢迎拍砖,砖块多了,房子才能盖起来。

选择常用的AT为例,假设想连续发送下列AT
l        AT
l        ATE0
l        AT+CMEE=0
l        AT+IPC=0,0
l        AT+CPIN?
l        AT+CSQ
l        AT+CREG?
l        AT+CGREG?
l        AT+CGATT?


使用特权

评论回复
66
我是土匪|  楼主 | 2015-9-24 14:16 | 只看该作者
n      架构1:查询模式
适用于单任务系统,思路就是发送一条AT后,死等,直到返回值回来,根据返回值结果决定重发、发送下一条,或者其它AT.

思路简单,代码结构也简单,不容易出错。但处理URC(unsoliciteresult code)还是要增加串口接收中断的,且处理的实时性可能不够。
还有个问题,有的AT即时回复,有的AT要等一会,甚至三分钟左右,这段时间死等意味着MCU就不能处理其它事情了,大部分情况下不能满足实际使用的。

使用特权

评论回复
67
我是土匪|  楼主 | 2015-9-24 14:18 | 只看该作者
本帖最后由 我是土匪 于 2015-9-24 14:41 编辑

n      架构二:中断方式

个人喜欢用的方式。



使用特权

评论回复
68
我是土匪|  楼主 | 2015-9-24 14:19 | 只看该作者
      架构三:多任务方式
多任务处理起来会更简单,更清晰。


使用特权

评论回复

打赏榜单

21ic小喇叭 打赏了 5.00 元 2015-10-14

69
我是土匪|  楼主 | 2015-9-24 14:19 | 只看该作者
代码在测试中,很快跟进。
感谢大家的支持

使用特权

评论回复
70
我是土匪|  楼主 | 2015-9-24 14:20 | 只看该作者
349264710 发表于 2015-9-19 23:43
无OS的框架,采用消息队列+软件定时器+状态机,主要是如何判断模块返回的是一个完整的帧,如何不漏掉URC ...

欢迎拍砖。

使用特权

评论回复
71
我是土匪|  楼主 | 2015-9-24 14:34 | 只看该作者
zuoxuqi 发表于 2015-9-9 09:51
楼主,期待下文啊

久等啦,工作忙,抱歉啦
欢迎拍砖。

使用特权

评论回复
72
我是土匪|  楼主 | 2015-9-24 14:35 | 只看该作者
wang1979 发表于 2015-9-11 09:52
期待已久,继续期待!

已更新,欢迎拍砖,感谢支持!

使用特权

评论回复
73
我是土匪|  楼主 | 2015-9-24 14:37 | 只看该作者
ddhex 发表于 2015-9-15 13:42
我一般是这么做的,所有的AT指令集,需要等待的时候,最好的策略其实是利用嵌入式操作系统的信号(信号量或 ...

每条AT都是等待执行结束,才发下一条
结合FIFO,定时器实现。

已更新,欢迎拍砖,欢迎交流。

使用特权

评论回复
74
我是土匪|  楼主 | 2015-9-24 14:38 | 只看该作者
lib6303c 发表于 2015-9-20 14:50
学习了,真好要使用GPRS模块!

欢迎交流

使用特权

评论回复
75
cyw183846168| | 2015-9-24 16:27 | 只看该作者
mark,收藏下,最近一直在研究GPRS与EVDO的通信,学习下

使用特权

评论回复
76
heluo1985| | 2015-9-24 19:22 | 只看该作者
工作会用到,认真听课

使用特权

评论回复
77
我是土匪|  楼主 | 2015-9-29 17:33 | 只看该作者
AT架构代码举例一、     代码举例(中断方式)
下面几条AT是常用的,是很多复杂应用的基础,暂且举例如何发送下面的AT:
l        AT
l        ATE0
l        AT+CMEE=0
l        AT+IPC=0,0
l        AT+CPIN?
l        AT+CSQ
请大家结合前面架构二:中断方式结构图思路一起看代码.
1        GPRS模块开机
2        GPRS模块同单片机同步,验证串口可以正常通信。
3        同步成功后,把要发送的AT放入队列:
charGprsCommonAT_Init(void)
{     
              char At_Cmd_Buff[30] = {0};
              char At_Name_Buff[20] = {0};

              //ATE0
               strcpy(At_Name_Buff, "ATE");
               strcpy(At_Cmd_Buff, "ATE0\r\n");
               AT_InTo_Queue( At_Name_Buff,  At_Cmd_Buff, NULL);

             //AT+CMEE=0
               memset(At_Cmd_Buff, 0x0, sizeof(At_Cmd_Buff));
               memset(At_Name_Buff, 0x0, sizeof(At_Name_Buff));
               strcpy(At_Name_Buff,"AT+CMEE");
               strcpy(At_Cmd_Buff, "AT+CMEE=0\r\n");
                AT_InTo_Queue( At_Name_Buff, At_Cmd_Buff, NULL);

             //AT+IFC=0,0
               memset(At_Cmd_Buff, 0x0, sizeof(At_Cmd_Buff));
               memset(At_Name_Buff, 0x0, sizeof(At_Name_Buff));
               strcpy(At_Name_Buff,"AT+IFC");
               strcpy(At_Cmd_Buff, "AT+IFC=0,0\r\n");
               AT_InTo_Queue( At_Name_Buff, At_Cmd_Buff, NULL);

               //AT+CPIN=0,0
               memset(At_Cmd_Buff, 0x0, sizeof(At_Cmd_Buff));
               memset(At_Name_Buff, 0x0, sizeof(At_Name_Buff));
               strcpy(At_Name_Buff,"AT+CPIN");
               strcpy(At_Cmd_Buff, "AT+CPIN?\r\n");
                AT_InTo_Queue( At_Name_Buff, At_Cmd_Buff, NULL);

               //AT+CSQ
               memset(At_Cmd_Buff, 0x0, sizeof(At_Cmd_Buff));
               memset(At_Name_Buff, 0x0, sizeof(At_Name_Buff));
               strcpy(At_Name_Buff,"AT+CSQ");
               strcpy(At_Cmd_Buff, "AT+CSQ\r\n");     
               AT_InTo_Queue( At_Name_Buff, At_Cmd_Buff, NULL);
}


使用特权

评论回复
78
我是土匪|  楼主 | 2015-9-29 17:38 | 只看该作者
4 启动定时器,检查队列有待发送的AT,且前一条AT执行结束再发送下一条AT:
AtCmdEntity*pCurrentCmd = NULL;

voidAtcTimerHandle(void)
{
    /* No ATC is running */
    if ((NULL == pCurrentCmd) )
    {
        if ((!AtQueueIsEmtpy( )) &&(At_Status == ATC_RSP_FINISH))
        {
            if (AtQueueOut(&pCurrentCmd))
            {
                     At_Status = ATC_RSP_WAIT;
                     Up_TxBuf((char*)pCurrentCmd->atData, strlen(pCurrentCmd->atData));
                     Sent_String(Tx_Buf,strlen(Tx_Buf));
            }
        }
    }
}

使用特权

评论回复
79
我是土匪|  楼主 | 2015-9-29 17:40 | 只看该作者
5  AT返回值的解析和URC的处理:
typedefAtcRspType (*AT_cmdHandle)(bool *urc);
typedef struct
{
    char *name;
    AT_cmdHandle atHandle;
}AtcHandleType;
//AT 列表
AtcHandleType  atCmdTable[ ] =
{
        {"ATE",  AtHandle},
        {"AT+CMEE",  AtHandle},
        {"AT+IFC",  AtHandle},
        {"AT+CPIN",   CpinHandle},
        {"AT+CSQ",  CsqHandle}
};
voidDeal_ATCmd(void)
{
    bool urc= TRUE;
    u16 i = 0;


    if (GPRS_SYNC == Gprs_Status)   
    {
        if (NULL != pCurrentCmd)
        {
            for (i = 0; i <sizeof(atCmdTable)/sizeof(atCmdTable[0]); i++)
            {
                if(!strcmp(pCurrentCmd->atName, atCmdTable.name))
                {
                    At_Status =atCmdTable.atHandle(&urc);
                 
                    if (ATC_RSP_FINISH ==At_Status)
                    {
                        pCurrentCmd = NULL;
                    }
                }
            }
        }
        if (urc)
        {
            Deal_URCHandle();
        }
    }
   
}

使用特权

评论回复
80
我是土匪|  楼主 | 2015-9-29 17:42 | 只看该作者
6 通用型AT返回值的处理
AtcRspType AtHandle( bool *urc)
{
   char *Rsp_Str[ ] = {"OK","ERROR"};
   s16  res = -1;
   char *p;
   
   u8  i = 0;
    p= (char *)Rx_Data.buf;

   while ( '\r' == *p || '\n' == *p)
    {
       p++;
    }
   
   for (i = 0; i < sizeof(Rsp_Str) / sizeof(Rsp_Str[0]); i++)
    {
     if (strstr( p,Rsp_Str))
       {
           res = i;
           break;
       }
    }
   *urc = FALSE;
   switch (res)
    {
       case 0:  /* OK */
       {
           At_Status  = ATC_RSP_FINISH;
       }
       break;
        case 1: /* ERROR */
       {
           At_Status = ATC_RSP_FINISH;
       }
       break;
       default:
          *urc = TRUE;
       break;
    }
   return At_Status;
}

使用特权

评论回复
发新帖 本帖赏金 36.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则