#include "AT.h"
#include "uart.h"
#include <string.h>
#include <stdlib.h>
static void lora_recv_proc(u8 *buf,u16 len);
static u16 get_at_queue_idle_space(void);
AT_QUEUE_t at_queue;
/* 0 buzy */
/* 1 clear */
/* 2 reset */
/* 3 队列缓存从头开始 */
volatile u8 at_flag=0;
/*测试模块是否正常*/
void at_cmd_test(void)
{ // atstr len type retrynum otime noAck
write_cmd_to_queue("AT\r\n", 4, 1, 30, 100, 0);
write_cmd_to_queue("ATI\r\n", 5, 2, 5, 100, 0);
}
/*获取队列剩余空间*/
static u16 get_at_queue_idle_space(void)
{
u16 ret=0;
if(at_queue.rear_addr>at_queue.front_addr)
{
ret=QUEUE_SPACE-at_queue.rear_addr+at_queue.front_addr;
}
else if(at_queue.rear_addr<at_queue.front_addr)
{
ret=at_queue.front_addr-at_queue.rear_addr;
}
else if(at_queue.rear_addr==at_queue.front_addr)
{
ret=QUEUE_SPACE;
}
return ret;
}
/*清空队列*/
void clear_at_queue(void)
{
u16 i=0;
for(i=0;i<QUEUE_SPACE;i++){
at_queue.buf[i]=0;
}
at_queue.used_buff_space=0;
at_queue.front=0;
at_queue.rear=0;
at_queue.front_addr=0;
at_queue.rear_addr=0;
at_flag=0;
}
/*
写队列
base 建议10ms调用一次,调用时间间隔为超时计数时间间隔,超时时间=调用间隔*otime
atstr 命令缓存指针
len 命令长度
type 命令标识
retryNum 重发次数
otime AT指令发送后计时 达到超时时间计数一次 如果达到retryNum的值,则直接下一步
noAckOtime AT指令发送后开始计时,超过该设定值,则直接下一步
*/
void write_cmd_to_queue(u8 *atstr,u16 len,u8 type,u8 retryNum,u16 otime,u16 noAckOtime)
{
u16 i=0;
if(len<get_at_queue_idle_space()) //如果放得下才写队列,放不下就扔了
{
if(at_queue.front==((at_queue.rear+1)%AT_CMD_MAXNUM)) //队列消息数量达到限制,就覆盖掉最先写入的数据
{
at_queue.front=(at_queue.front+1)%AT_CMD_MAXNUM;
}
//--- add
for(i=0;i<len;i++)
{
at_queue.buf[(at_queue.rear_addr+i)%QUEUE_SPACE]=atstr[i]; //将命令写入队列
}
at_queue.at_cmd_info[at_queue.rear].len=len;
at_queue.at_cmd_info[at_queue.rear].offset=at_queue.rear_addr;
at_queue.at_cmd_info[at_queue.rear].oTime=otime;
at_queue.at_cmd_info[at_queue.rear].retryNum=retryNum;
at_queue.at_cmd_info[at_queue.rear].type=type;
at_queue.at_cmd_info[at_queue.rear].noAckOtime=noAckOtime;
at_queue.rear_addr=(at_queue.rear_addr+len)%QUEUE_SPACE;
at_queue.rear=(at_queue.rear+1)%AT_CMD_MAXNUM; //队列尾+1
at_flag|=1<<1;
}
}
/*读队列并发送AT命令,包括超时处理*/
void read_cmd_queue_and_send(void)
{
u16 i=0;
if(at_queue.front!=at_queue.rear)
{
if((at_flag&1<<0)==0)
{
at_flag|=1<<0;
at_queue.cmd.len =at_queue.at_cmd_info[at_queue.front].len;
at_queue.cmd.offset =at_queue.at_cmd_info[at_queue.front].offset;
at_queue.cmd.oTime =at_queue.at_cmd_info[at_queue.front].oTime;
at_queue.cmd.retryNum =at_queue.at_cmd_info[at_queue.front].retryNum;
at_queue.cmd.type =at_queue.at_cmd_info[at_queue.front].type;
at_queue.cmd.noAckOtime =at_queue.at_cmd_info[at_queue.front].noAckOtime;
//取要发送的数据
for(i=0;i<at_queue.cmd.len;i++)
{
at_queue.txbuf[i]=at_queue.buf[(i+at_queue.cmd.offset)%QUEUE_SPACE];
}
HAL_UART_Transmit(&huart3, (uint8_t *)at_queue.txbuf,at_queue.cmd.len, 0xffff);//串口,以阻塞模式发送
at_queue.otime=0;
at_queue.retryNum=0;
at_queue.noAckOtime=0; //计数清零
//----
at_queue.front_addr=(at_queue.front_addr+at_queue.cmd.len)%QUEUE_SPACE;
at_queue.front=(at_queue.front+1)%AT_CMD_MAXNUM; //队列头+1
}
}
else
{
if(at_flag&1<<1)
{
at_flag&=~(1<<1);
clear_at_queue();
}
}
if(at_flag&1<<0) //如果有指令刚发出,在等待回复
{
if(at_queue.cmd.oTime)
{
at_queue.otime++; //节拍计时,节拍基准为读队列函数调用时间间隔
if(at_queue.otime>at_queue.cmd.oTime) //计时时间到
{
at_queue.otime=0;
if(at_queue.cmd.retryNum) //如果有重发次数
{
if(at_queue.retryNum<at_queue.cmd.retryNum) //如果没有达到重发次数上限
{
at_queue.retryNum++;
if(at_flag&1<<2){ //如果复位
at_flag&=~(1<<0);
}
else{ //不复位则重发
HAL_UART_Transmit(&huart3, (uint8_t *)at_queue.txbuf,at_queue.cmd.len, 0xffff);//串口,以阻塞模式发送
}
}
else //异常,重发达到上限,指令得不到想要的响应
{
at_queue.retryNum=0;
//---几个特殊处理
if(0) //
{
}
else if(at_queue.cmd.type==100) //关机指令得不到回复
{
// gsmPwrOff;
// gsmPkyOff;
// at_queue.flag.busy=0;
// mSystem.nbMWorks=2; //关机模式
}
else //一般指令没响应时
{
at_flag&=~(1<<0);
}
}
}
else //如果没有重发要求
{
at_flag&=~(1<<0);
//特殊处理
if(at_queue.cmd.type==0)
{
}
}
}
}
if(at_queue.cmd.noAckOtime) //如果有总超时时间限制
{
at_queue.noAckOtime++;
if(at_queue.noAckOtime>=at_queue.cmd.noAckOtime) //超时处理
{
at_queue.noAckOtime=0;
at_flag&=~(1<<0);
}
}
}
}
/*测试at及检查版本信息,根据不同版本选择对应处理程序*/
void at_recv_proc(u8 *buf,u16 len)
{
char *p;
p=(char*)buf;
if(at_queue.cmd.type==1) //AT
{
if((strstr(p,"AT\r\n"))||(strstr(p,"\r\nOK\r\n")))
{
at_flag&=~(1<<0);
}
}
else if(at_queue.cmd.type==2) //ATI
{
if(strstr(p,"EC600S")) //可以根据版本信息不同,在此处执行对应初始化函数
{
at_flag&=~(1<<0);
at_queue.modType=MOD_EC600S;
}
else if(strstr(p,"+ATI:"))
{
at_flag&=~(1<<0);
at_queue.modType=MOD_LORA;
}
}
else{ //得到版本信息后,在此处执行对应的处理程序
switch(at_queue.modType)
{
case MOD_EC600S:
// ec600RxProc(buf,len);
break;
case MOD_LORA:
lora_recv_proc(buf,len);
break;
default:break;
}
}
}
/*AT接收处理*/
void at_recv_proc2(u8 *buf,u16 len) //框架及示例
{
u8 tmp=0,tcpstatus=0;
u16 xlen=0;
char *p,*q;
p=(char*)buf;
/*一般情况*/
switch(at_queue.cmd.type)
{
case 3:if(strstr(p,"OK")) //AT
at_flag&=~(1<<0);
break;
case 4:if(strstr(p,"OK")) //ATE0
at_flag&=~(1<<0);
break;
case 5: //CPIN?
if(strstr(p,"+CPIN: READY"))
{
at_flag&=~(1<<0);
}
break;
default: break;
}
/*特殊情况*/
q=strstr(p,"+QIOPEN:");
if(q)
{
p=q+8; //0
tmp=strtol(p,&p,10); //将0转化为长整型给tmp,将p指向p的下一个字符(逗号)
p++; //将p指向下一个字符
tcpstatus=strtol(p,&p,10); //将第二个零转为长整型给tcpstayus
if(tcpstatus==0) //连接成功是0
{
at_flag&=~(1<<0);
}
else //连接不成功
{
at_flag&=~(1<<0);
}
}
q=strstr(p,"+QIURC:");
if(q)
{
p=q+8;
if(strncmp(p,"\"closed\"",8)==0)
{
q=p+9;
tmp=strtol(q,0,10);
if(tmp==1)
{
}
}
else if(strncmp(p,"\"recv\"",6)==0)
{
q=p+7;
tmp=strtol(q,&q,10);
q++;
xlen=strtol(q,&q,10);
q+=2;
// setRxData((u8*)q,xlen,tmp);
}
else if(strncmp(p,"\"pdpdeact\"",10)==0)
{
clear_at_queue();
}
}
}
/*lora模块接收处理*/
static void lora_recv_proc(u8 *buf,u16 len)
{
char *p;
p=(char*)buf;
/*一般情况*/
switch(at_queue.cmd.type)
{
case 3:if(strstr(p,"OK")) //设置通信模式
at_flag&=~(1<<0);
break;
case 4:if(strstr(p,"OK")) //设置发送频点
at_flag&=~(1<<0);
break;
case 5:if(strstr(p,"OK")) //设置接收频点
at_flag&=~(1<<0);
break;
case 6:if(strstr(p,"OK")) //关闭接收反转
at_flag&=~(1<<0);
break;
case 7:if(strstr(p,"OK")) //关闭发送反转
at_flag&=~(1<<0);
break;
case 8:if(strstr(p,"OK")) //长期休眠
at_flag&=~(1<<0);
break;
case 9:if(strstr(p,"OK")) //接收窗口时间
at_flag&=~(1<<0);
break;
case 10:if(strstr(p,"OK")) //AES加密
at_flag&=~(1<<0);
break;
default: brea

游楽场
- 粉丝: 89
最新资源
- 国产AI大模型驱动高端装备制造智能化升级路径探索.docx
- 互联网环境下大学语文翻转课堂实践研究.docx
- 会计信息系统的安全性与合规性保障.docx
- 互联网上网服务营业场所安全管理指南.docx
- 环境监测大数据驱动下的生态保护预警体系构建.docx
- 机器学习与大语言模型技术在新型电力系统故障诊断中的应用研究进展.docx
- 机器学习在催化科学理论构建中的应用研究.docx
- 机器学习在多胞结构优化中的应用.docx
- 基于大数据的社区老年健康服务系统优化策略研究.docx
- 基于云平台的实习管理信息系统的架构设计研究.docx
- 基于数据挖掘的城市灾害链传播预警模型与路径优化研究.docx
- 计算机网络安全:大专论文写作指导与案例分析.docx
- 跨平台资源协同计算策略的算法优化研究.docx
- 开放式创新理论在中国大数据时代的发展逻辑.docx
- 利用Simpleware软件进行数字岩心建模及数值分析的综合解决方案探讨.docx
- 粒子滤波算法在救援机器人路径规划中的应用与优化研究.docx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈



评论4