我是土匪
发表于 2015-9-29 17:40
5AT返回值的解析和URC的处理:typedefAtcRspType (*AT_cmdHandle)(bool *urc);typedef struct{ char *name; AT_cmdHandle atHandle;}AtcHandleType;//AT 列表AtcHandleTypeatCmdTable[ ] = { {"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); i++) { if(!strcmp(pCurrentCmd->atName, atCmdTable.name)) { At_Status =atCmdTable.atHandle(&urc); if (ATC_RSP_FINISH ==At_Status) { pCurrentCmd = NULL; } } } } if (urc) { Deal_URCHandle(); } } }
我是土匪
发表于 2015-9-29 17:42
6 通用型AT返回值的处理AtcRspType AtHandle( bool *urc){ char *Rsp_Str[ ] = {"OK","ERROR"}; s16res = -1; char *p; u8i = 0; p= (char *)Rx_Data.buf;
while ( '\r' == *p || '\n' == *p) { p++; } for (i = 0; i < sizeof(Rsp_Str) / sizeof(Rsp_Str); 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;}
我是土匪
发表于 2015-9-29 17:44
本帖最后由 我是土匪 于 2015-9-30 11:20 编辑
7 个性化AT返回值解析:CSQ应用举例AtcRspType CsqHandle( bool *urc){ char *Rsp_Str[ ] = {"OK","ERROR","+CSQ:"}; s16res = -1; u8 i = 0; char *p = (char *)Rx_Data.buf; u8 rssi = 0; u8 ber = 0;
while ( '\r' == *p || '\n' == *p) { p++; }
for (i = 0; i < sizeof(Rsp_Str) / sizeof(Rsp_Str); i++) { if (strstr( p,Rsp_Str)) { res = i; break; } }
*urc = FALSE; switch (res) { case 0:/* OK */ { if(SevrerConnectStatus == FALSE) { if (Csq_Ok) { //connectto server } else { bsp_StartTimer(CSQ_TIMER_ID,CSQ_TIMERPERIOD, (bspTimerHandler)AT_GetCSQ);
} }
At_Status= ATC_RSP_FINISH; } break; case 1:/* ERROR */ { bsp_StartTimer(CSQ_TIMER_ID,CSQ_TIMERPERIOD, (bspTimerHandler)AT_GetCSQ);
At_Status = ATC_RSP_FINISH;
} break; case 2: /* +CSQ: */ {
p += strlen("+CSQ:"); while (' ' == *p) { p++; }
while (*p >= '0' && *p <= '9') {
rssi *= 10; rssi += *p++ - '0'; }
while ((' '== *p) || (',' == *p)) { p++; } while (*p >= '0' && *p <= '9') {
ber *= 10; ber += *p++ - '0';
}
if (rssi > MIN_CSQ) { Csq_Ok = TRUE;
}
break; default: *urc = TRUE; break; }
} returnAt_Status;}
我是土匪
发表于 2015-9-29 17:45
8 URC解析框架void Deal_URCHandle(void){ static char Closed_count = 0; char *p = (char *)Rx_Data.buf; s16urcType = -1; u8 i= 0;static char count_pdp = 0; char *UrcTable[ ] = { "CONNECT OK", "ALREADYCONNECT", "CONNECT FAIL", "SERVER OK", "SERVER ERROR", "REMOTE IP:", "CLOSED", "+PDP: DEACT", "+CIPRXGET:1", "RING", "NO CARRIER", "NO DIALTONE", "BUSY", "NO ANSWER", "OK", "+CPIN: NOT READY" "+CREG: " "+CGREG: " }; while ('\r' == *p || '\n'== *p) { p++; } for (i = 0; i < sizeof(UrcTable)/sizeof(UrcTable); i++) { if (strstr(p, UrcTable)) { urcType = i; break; } } switch (urcType) { case 0: /* CONNECT OK */ { } break; case 1:/* ALREADY CONNECT */ { } break; case 2: /* CONNECT FAIL */ { } break; case 3: /* SERVER OK */ { } break; case 4: /* SERVER ERROR */ { } break; case 5:/* REMOTE IP: */ { } break; case 6: /* CLOSED */ { } break; case 7: /* +PDP: DEACT */ { } break; case8: /* +CIPRXGET: 1 */ { } break; case 9: /* RING */ { } break; case 10:/* NO CARRIER */ case 11:/* NO DIALTONE */ case 12:/* BUSY */ case 13:/* NO ANSWER */ { } break; case 14:/* OK */ { } break; case15: //+CPIN: NOT READY { } break; default: break; } }
我是土匪
发表于 2015-9-29 17:47
9 主函数举例:void main(void){ PowerOn_Sys(); Hardware_Init(); enableInterrupts(); Param_Init(); bsp_InitTimer(); PowerOn_GPRS(); while(1) { bsp_TimerOutHandler(); if((GPRS_SYNC== Gprs_Status) && (!Gprs_Init_Flag)) { GprsCommonAT_Init();//单次执行的任务 /********************************************************** AT执行过程: 入FIFO ->出FIFO,发送给模块 -> 等返回值 ->执行结束 AT发送给模块到执行结束这段时间,称之为 ATC_RSP_WAIT,余下过程称为ATC_RSP_FINISH 只有在ATC_RSP_FINISH状态下才能发送AT给模块 ************************************************************/ bsp_StartAutoTimer(AT_TIMER_ID, AT_TIMERPERIOD,(bspTimerHandler)AtcTimerHandle); At_Status =ATC_RSP_FINISH; Gprs_Init_Flag = 1; } //RX,判断开机成功与否 if(Rx_Flag) { Rx_Flag = 0; Deal_Rx_FromGprs(); //解析AT返回值、URC } } }
我是土匪
发表于 2015-9-29 17:48
如上代码架构参考了官方的二次开发的例子。
经过测试,可以正常工作。
欢迎交流。
六安飞雨
发表于 2015-9-29 18:13
顶
来与君
发表于 2015-9-30 00:44
楼主上了干货,顶^^^^^^
andy93762
发表于 2015-10-3 18:19
顶下楼主,很精彩
mcumail
发表于 2015-10-6 09:01
占座学习,最近我也在研究sim900A,用的是STC的单片机,主要是发短信,有时成功又时失败
我是土匪
发表于 2015-10-8 09:41
mcumail 发表于 2015-10-6 09:01
占座学习,最近我也在研究sim900A,用的是STC的单片机,主要是发短信,有时成功又时失败 ...
要看每条AT的返回值,根据返回值分析。
如果你有多个串口,可以将运行信息打印出来,实时输出,便于分析定位。
我是土匪
发表于 2015-10-10 14:22
本帖最后由 我是土匪 于 2015-11-5 13:42 编辑
第四章DTMF实现远程开门
前言最近,土匪所在小区改造,所有楼下的门锁变成了电话开门,这让我想起刚刚毕业时进入第一家公司的一段经历:当时去电力机房安装监控设备,有些很小的独立的机房会在村落旁边或者在庄稼地附近,费尽周折找到一个无人值守的机房,一个小灵通过去,输入几个密码门就打开了。第一次见到这么神奇的高科技,很是惊叹。
今天才知道这里用的是DTMF(dual-tone multifrequency)技术。想了解DTMF理论,度娘讲解的非常详细,这里不废话。
我是土匪
发表于 2015-10-10 14:27
本帖最后由 我是土匪 于 2015-10-10 14:48 编辑
步入正题如何接收DTMF音?用GPRS如何做到电话开门?拿SIM900A为例说明,GPRS实现到电话开门功能,手机拨打拨快,建立语音通信后,手机键盘按键,模块能识别到即为成功。l 其思路就是被叫方首先使能DTMF侦测功能,之后建立语音通信。l 再此基础上,主叫方通过电话键盘发送DTMF音,接收方(这里指SIM900A)会通过URC上报DTMF识别的字符。l 下图为思路:
l AT操作流程:
我是土匪
发表于 2015-10-10 14:29
本帖最后由 我是土匪 于 2015-10-10 14:49 编辑
发送DTMF参照AT命令:AT+VTS建立语音通信后,模块通过AT+VTS实现DTMF的发送,比如:AT+VTS=4 OKAT+VTS=* OK模块发送,手机听筒能听到声音,这就成功了。
我是土匪
发表于 2015-10-10 14:50
注意事项:并不是所有版本都支持DTMF,需要咨询原厂。DTMF成功率不是100%。出现问题时重复操作即可。
至此,一个包含远程电话开门功能的GPRS部分就完成了,DTMF部分也就结束了。
zuoxuqi
发表于 2015-10-19 16:45
楼主继续啊
我是土匪
发表于 2015-10-19 16:53
本帖最后由 我是土匪 于 2015-10-20 10:34 编辑
;P以为没有人关注,准备短信部分。
xinyipcb
发表于 2015-10-19 20:49
不错的信息。
JLennon
发表于 2015-10-20 14:08
一直在关注。
来与君
发表于 2015-10-20 22:59
100楼是我的……