📄 at.c
字号:
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&AT命令处理&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//*文件名称:AT.c
//*文件作用:AT命令处理
//*文件作者:翟 鹏
//*创建日期:2004年5月
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
#include <include.h>
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&私有算法函数部分&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//***********************************************************************************************************************
//函数作用:把hex串高低4位对调
//参数说明:
//注意事项:
//返回说明:
//***********************************************************************************************************************
static void swap_low4_and_high4(uchar *hex, uchar length)
{
uchar i;
uchar temp;
if(length&0x01)length++;//修正奇偶
length>>=1;//转化为字节数
for(i=0;i<length;i++)
{
temp=hex[i*2];
hex[i*2]=hex[i*2+1];
hex[i*2+1]=temp;
}
}
//***********************************************************************************************************************
//函数作用:把7位数据转化成8位数据
//参数说明:
//注意事项:
//返回说明:
//***********************************************************************************************************************
static uchar Char2Bcd(uchar *hex)
{
uchar i;
uchar j;
if(*hex>'9')i=*hex-0x37;
else i=*hex-0x30;
i<<=4;
hex++;
if(*hex>'9')j=*hex-0x37;
else j=*hex-0x30;
i=i|(j&0x0f);
return i;
}
static void bit7_to_bit8(uchar *Src, uchar *Dec)
{
uint i,j;
uint MoveTemp;
i=0;
while(Src[2*i]!=0)
{
Src[i]=Char2Bcd(Src+2*i);
i++;
}
Src[i]=0;
i=0;j=0;
do{
if( (j%8) ==0 )
{
Dec[j]=Src[i]&0x7f;
j++;
continue;
}
MoveTemp=Src[i]>>(8-j%8);
Dec[j]=MoveTemp+(Src[i+1]<<(j%8));
Dec[j]=0x7f&Dec[j];
i++;j++;
}while(Dec[j-1]!=0);
}
//***********************************************************************************************************************
//函数作用:把8位数据转化成7位数据
//参数说明:
//注意事项:
//返回说明:
//***********************************************************************************************************************
static void Bcd2Char(uchar *hex, uchar bcd)//bcd码转化成两个字节表示的hex
{
uchar i;
i=bcd>>4; // Msb
if(i>9)i+=0x37;
else i+=0x30;
*hex++=i;
i=bcd&0x0f; // Lsb
if(i>9)i+=0x37;
else i+=0x30;
*hex=i;
}
//***********************************************************************************************************************
//函数作用:处理PDU格式的短信息
//参数说明:PDU数据缓冲区 dst_no--对方号码 datetime--日期时间 content--短信内容
//注意事项:
//返回说明:
//***********************************************************************************************************************
static uchar dispose_PDU(uchar *buf, uchar *dst_no, uchar *datetime)
{
uchar *buf_backup=buf;
uchar i;
uchar length;
uchar data_coding;//编码类型
//得到短信中心号码长度 并跳过---(0891683108200205F0)
hex_to_char(buf,&length);//得到长度
buf+=2;//跳过长度字节
buf+=(length<<1);//跳过短信中心号码
//跳过PDU类型---(24)
buf+=2;
//得到对方号码 并跳过---(0D91683108026344F0)
hex_to_char(buf,&length);//得到长度
buf+=2;//跳过长度字节---(0D)
buf+=2;//跳过类型字节---(91)
swap_low4_and_high4(buf,length);//号码高低字节转化---(8613802036440F)
if(buf[0]==0x38 && buf[1]==0x36)//跳过国家代码---(86)
{
buf+=2;
length-=2;
}
mem_copy(dst_no,buf,length);//拷贝对方号码
dst_no[length]=0;//添加结束符
if(length&0x01)length++;//修正奇偶
buf+=length;//跳过对方号码---(683108026344F0)
//跳过PID和DCS 00和08
buf+=2;//跳过PID---(00)
hex_to_char(buf,&data_coding);//得到编码类型
buf+=2;//跳过DCS---(08或00)
//得到发送日期时间---(40214251029000) 定长---14字节
swap_low4_and_high4(buf,14);//高低字节转化---(041224152009)
for(i=0;i<6;i++)
{
mem_copy(datetime,buf,2);//拷贝年
datetime+=3;buf+=2;
}
*(datetime-1)=0;//添加结束符
buf+=2;//跳过毫秒
//得到内容长度 并跳过
hex_to_char(buf,&length);//得到长度
buf+=2;//跳过长度
//根据编码类型判断是否需要PDU字节转换
if(data_coding==0x00)bit7_to_bit8(buf,buf_backup);//英文---PDU编码进行7转8
else str_copy(buf_backup,buf);//中文----unicode字符串直接拷贝
return data_coding;
}
//命令消息定义
#define AT_CMD_HEAD "AT" //命令头
#define AT_CMD_END "\r\n" //命令尾
#define AT_MSG_READY "RDY" //模块复位成功的信息
#define AT_MSG_SIMOK "+CPIN: READY" //SIM卡成功的信息
#define AT_MSG_LOGINOK "+CREG: " //登陆成功的信息
#define AT_MSG_SMSRECEIVE "+CMT" //收到短信的信息
#define AT_MSG_RING "RING" //收到来电的信息
#define AT_MSG_NOCARR "NO CARR" //对方挂机
#define AT_MSG_CLIP "+CLIP" //收到来电显示的信息
#define AT_MSG_IPSTATE "STATE:" //IP致命错误提示
#define AT_MSG_OK "OK" //命令正确的信息
#define AT_MSG_SENDOK "SEND OK" //IP发送成功的信息
#define AT_MSG_CONNECTOK "CONNECT OK" //IP连接成功的信息
#define AT_MSG_CLOSEOK "CLOSE OK" //IP连接关闭成功的信息
#define AT_MSG_SHUTOK "SHUT OK" //移动场景关闭成功的信息
#define AT_MSG_SIGNAL "+CSQ" //信号强度信息
#define AT_MSG_ERROR "ER" //命令错误的信息
#define AT_MSG_SENDFAIL "SEND FAIL" //发送失败的信息
#define AT_MSG_CONNECTFAIL "CONNECT FAIL" //连接失败的信息
//命令发送字符串定义
#define AT_CMD_DISECHO "E0" //禁止回显命令行
#define AT_CMD_CREG "+CREG=1" //主动提供网络注册信息
#define AT_CMD_SMSPDU "+CMGF=0" //设置短信息为PDU模式
#define AT_CMD_SMSTOCOMM "+CNMI=2,2,2,1,0" //短消息直接从串口输出
#define AT_CMD_GSMCHARSET "+CSCS=\"GSM\"" //设置GSM字符集
#define AT_CMD_TCPIPRECEIVEHINT "+CIPHEAD=1" //设置TCPIP接收数据包头提示
#define AT_CMD_TCPIPSENDHINT "+CIPSPRT=0" //关闭TCPIP数据发送时的> 提示
#define AT_CMD_FIXLOCALPORT "+CIPFLP=0" //取消固定本地端口
#define AT_CMD_SIGNAL "+CSQ" //信号强度
#define AT_CMD_CLOCK "+CCLK" //时钟
#define AT_CMD_APNSETUP "+CSTT=" //设置APN
#define AT_CMD_IPACTIVE "+CIICR" //激活移动场景
#define AT_CMD_GETLOCALIP "+CIFSR" //获得本地IP地址
#define AT_CMD_CONNECT "+CIPSTART" //创建连接
#define AT_CMD_IPSENDDATA "+CIPSEND=" //发送数据
#define AT_CMD_CONFIGDNS "+CDNSCFG" //配置DNS
#define AT_CMD_DISCONNECT "+CIPCLOSE" //关闭连接
#define AT_CMD_SHUTDOWN "+CIPSHUT" //关闭移动场景
#define AT_CMD_SMSCENTERNO "+CSCA" //短消息中心号
#define AT_CMD_SENDSMS "+CMGS=" //发送短信
#define AT_CMD_DIAL "D" //拨号
#define AT_CMD_SENDDTMF "+VTS=" //双音频拨号
#define AT_CMD_PLAYDTMF "+CLDTMF=" //播放双音频
#define AT_CMD_ANSWER "A" //应答电话
#define AT_CMD_HANGUP "H" //挂断电话
#define AT_CMD_SWITCHAUDIO "+CHFA=" //切换音频通道
#define AT_CMD_VOLUME "+CLVL=" //音量控制
#define AT_CMD_MIC "+CMIC=" //MIC增益控制
//回应字定义
#define AT_ACK_OK 0x80
#define AT_ACK_ERROR 0xA0
//缓冲区定义
uchar xdata at_receive_buffer[AT_RECEIVE_BUF_SIZE];//接收缓冲区
static uint xdata at_buf_point=0;//接收缓冲区指针
static uchar xdata at_ack=0;//回应字
static uchar xdata sms_coding=0;//短信息编码类型
static uchar xdata sms_no[16];//短信对方号码
static uchar xdata sms_datetime[18]="00/00/00,00:00:00";//短信日期时间
static uchar xdata clip_no[21]="???????????";//来电显示号码
//状态位定义
static bit at_reset=1;//需要复位 第一次需要复位
static bit simok=0;//sim卡准备好
static bit loginok=0;//登陆网络标志
static bit smsin=0;//收到短消息
static bit ring=0;//来电话
static bit calling=0;//是否通话状态
//***********************************************************************************************************************
//函数作用:接收消息
//参数说明:
//注意事项:
//返回说明:如果接受到了完整包 返回1
//***********************************************************************************************************************
static uchar at_get_msg(void)
{
uchar temp;
//接收直到没有数据
while(AT_RECEIVE_CHAR(&temp))
{
dog();
if(temp=='\r')//判断结束符号
{
//如果缓冲区有内容
if(at_buf_point)
{
at_receive_buffer[at_buf_point]=0;//添加结束符
at_buf_point=0;//清缓冲区指针
return 1;
}
}
else if(temp=='\n')//过滤垃圾字符
{
}
else //正常字符
{
at_receive_buffer[at_buf_point++]=temp;//向缓存送数据
if(at_buf_point>=AT_RECEIVE_BUF_SIZE-1)at_buf_point=0;//判断是否超长
}
}
return 0;
}
//***********************************************************************************************************************
//函数作用:等待数据包---用于接收短消息内容
//参数说明:
//注意事项:
//返回说明:如果接受到了完整包 返回1
//***********************************************************************************************************************
static uchar at_wait_packet(void)
{
uchar over_flag=0;
uchar temp;
uint wait_time=30000;//超时3s
while(wait_time--)
{
dog();
//接收数据
if(AT_RECEIVE_CHAR(&temp))
{
if(temp=='\r')//判断结束符号
{
//如果缓冲区有内容
if(at_buf_point)
{
at_receive_buffer[at_buf_point]=0;//添加结束符
at_buf_point=0;//清缓冲区指针
if(over_flag)return 0;
return 1;
}
}
else if(temp=='\n')//过滤垃圾字符
{
}
else //正常字符
{
at_receive_buffer[at_buf_point++]=temp;//向缓存送数据
if(at_buf_point>=AT_RECEIVE_BUF_SIZE-1)
{
at_buf_point=0;//判断是否超长
over_flag=1;
}
}
}
}
at_buf_point=0;//清缓冲区指针
return 0;
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&消息列表处理函数&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//函数作用:收到OK
static void receive_ok(void)
{
at_ack=AT_ACK_OK;
}
//函数作用:收到ERROR
static void receive_error(void)
{
at_ack=AT_ACK_ERROR;
}
//函数作用:收到SEND OK
static void receive_sendok(void)
{
at_ack=AT_ACK_OK;
}
//函数作用:收到短信息到达提示
static void receive_smsreceive(void)
{
if(!at_wait_packet())return;//读取数据
sms_coding=dispose_PDU(at_receive_buffer,sms_no,sms_datetime);//解析PDU
smsin=1;//送标志
//if(at_debug==1)//调试信息
//{
// print_line(sms_no);
// print_line(at_receive_buffer);
//}
}
//函数作用:收到来电提示
static void receive_ring(void)
{
ring=1;
calling=1;
}
//函数作用:收到来电显示
static void receive_clip(void)
{
//送标志
ring=1;
calling=1;
//纪录来电号码
if(at_receive_buffer[7]!='\"')return;//判断是否开通了来电显示
if(at_receive_buffer[8]=='\"')return;//判断是否开通了来电显示
str_char_copy(clip_no,&at_receive_buffer[8],'\"');
}
//函数作用:收到对方挂机的信息
static void receive_nocarr(void)
{
//送标志
ring=0;
calling=0;//通话标志
//清号码
str_copy(clip_no,"???????????");
}
//函数作用:收到CSQ
static void receive_signal(void)
{
at_ack=AT_ACK_OK;
}
//函数作用:收到注册网络成功的提示
static void receive_loginok(void)
{
if(at_receive_buffer[7]=='1' || at_receive_buffer[7]=='5')loginok=1;//送标志
else if(at_receive_buffer[7]=='0')if(loginok)at_reset=1;//中途脱网 送复位标志
}
//函数作用:收到SIM卡准备好
static void receive_smsok(void)
{
if(simok)at_reset=1;
simok=1;
}
//命令列表
typedef struct
{
uchar *cmdstr;
void (*callback)(void);
}at_msglist_t;//消息列表数据结构
static at_msglist_t code at_msglist[]=
{
{AT_MSG_OK,receive_ok},
{AT_MSG_ERROR,receive_error},
{AT_MSG_SENDOK,receive_sendok},
{AT_MSG_SMSRECEIVE,receive_smsreceive},
{AT_MSG_RING,receive_ring},
{AT_MSG_CLIP,receive_clip},
{AT_MSG_NOCARR,receive_nocarr},
{AT_MSG_SIGNAL,receive_signal},
{AT_MSG_LOGINOK,receive_loginok},
{AT_MSG_SIMOK,receive_smsok},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -