AT命令和multiplexer protocol && Linux和android平台的GSM/GPRS模块测试
AT命令的存在,使得网络通信简化成串口控制,通过一组命令就可以完成设备的初始化、呼叫、短信、传真。几个名词解释:
DTE(Data Terminal Equipment)数据终端设备。通常是一个智能设备,如PC机,嵌入式主机,手机等,用于发送AT命令和PPP命令。
DCE(Data Circuit Terminal )数据电路终端,用于与外界建立通讯的链路。
DTE与DCE之间用串口相连。比如PC机用串口接入拨号MODEM时,PC机是DTE,拨号MODEM是DCE。
有关AT命令的详细用法参见http://www.rosoo.net/a/201011/10451.html。
multiplexer protocol是GSM中比较重要的协议,在GSM 07.10中对该协议做了详细的描述。说它重要是因为它是衔接手机(TE)和模组(MS)之间的纽带,TE和MS通信,一般是通过一个串口进行,问题在于串口只有一个,而通信的数据类型却有很多种。比如AT Command、voice、 fax、 data、 SMS、CBS、 phonebook、电量状态、GPRS和USSD 等等。multiplexer protocol就是用来解决这个问题的:让不同类型的数据在一个串口上传输,而不至于发生紊乱。
multiplexer protocol采用的方法是把一个串口模拟成多个串口,对上层应用程序来说,每一个虚拟的串口和普通串口几乎没有差别,只是每个虚拟串口都只能传输特定类型的数据。下面moto的定义:
VOICE_CALL "/dev/mux0"
SMS_MO "/dev/mux1"
SMS_MT "/dev/mux2"
PHONEBOOK "/dev/mux3"
MISC "/dev/mux4"
CSD "/dev/mux5"
GPRS1 "/dev/mux6"
GPRS2 "/dev/mux7"
CSD "/dev/mux8"
GPRS1 "/dev/mux9"
GPRS2 "/dev/mux10"
LOGGER_CMD "/dev/mux11"
LOGGER_DATA "/dev/mux12"
TEST_CMD "/dev/mux13"
AGPS "/dev/mux14"
NET_MONITOR "/dev/mux15"
mux具体参见:http://www.rosoo.net/a/201101/10739.html
====================Linux和android平台的GSM/GPRS模块测试===========
这里记录一种在普通的LINUX或安卓智能手机平台上,用快捷的方法测试MODEM模块的驱动是否正常工作。需要注意的是:程序的运行依赖于交叉编译器版本,必须是带串口操作库函数的编译器,比如2008q3。编译完成后执行,即可显示一系列待输入选项,进行测试项目。
(1)主函数
// this is a test about GPRS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h> // set baud rate,交叉编一起必须带这种库
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#define FUNC_RUN 0
#define FUNC_NOT_RUN 1
//测试项目
#define SIMPLE_TEST 1
#define READ_SIM_CARD_ID 2
#define GSM_GPRS_SIGNAL 3
#define MAKE_A_CALL 4
#define WAIT_A_CALL 5
#define SHORT_MESSAGE 6
#define POWER_MANAGE 7
#define FUNC_QUIT 8
//短消息测试子项目
#define SEND_SHORT_MESSAGE 1
#define READ_SHORT_MESSAGE 2
#define CONFIG_SHORT_MESSAGE_ENV 3
#define QUIT_SHORT_MESSAGE 4
#define DEVICE_TTYS "/dev/s3c2410_serial1" //modem分配的UART口
#define MAX_LEN_OF_SHORT_MESSAGE 140
#define RECEIVE_BUF_WAIT_1S 1
#define RECEIVE_BUF_WAIT_2S 2
#define RECEIVE_BUF_WAIT_3S 3
#define RECEIVE_BUF_WAIT_4S 4
#define RECEIVE_BUF_WAIT_5S 5
int main(void)
{
int fd;
printf("\nGSM/GPRS TESTS\n\n");
fd = open(DEVICE_TTYS, O_RDWR); //打开TTY设备
if (fd == -1)
{
printf("open device %s error\n",DEVICE_TTYS);
}
else
{
init_ttyS(fd); // init device
func_GSM(fd); // GSM/GPRS functions
if (close(fd)!=0)
printf("close device %s error",DEVICE_TTYS);
}
return 0;
}
配置tty的函数
void init_ttyS(int fd)
{
struct termios options;
bzero(&options, sizeof(options)); // clear options
cfsetispeed(&options,B115200); // setup baud rate
cfsetospeed(&options,B115200);
options.c_cflag |= (CS8 | CREAD);
options.c_iflag = IGNPAR;
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &options);
}
MODEM测试模块主函数
void func_GSM(int fd)
{
int flag_func_run;
int flag_select_func;
ssize_t ret;
flag_func_run = FUNC_RUN;
while (flag_func_run == FUNC_RUN)
{
print_prompt(); // print select functions txt
scanf("%d",&flag_select_func); // user input select
getchar();
switch(flag_select_func)
{
case SIMPLE_TEST : {GSM_simple_test(fd); break;}
case READ_SIM_CARD_ID : {GSM_read_sim_card_id(fd); break;}
case GSM_GPRS_SIGNAL : {GSM_gprs_signal(fd); break;}
case MAKE_A_CALL : {GSM_call(fd); break;}
case WAIT_A_CALL : {GSM_wait_call(fd); break;}
case SHORT_MESSAGE : {GSM_short_mesg(fd); break;}
case POWER_MANAGE : {GSM_Power_Manage(fd); break;} //break退出switch,但不会退出while
case FUNC_QUIT :
{
flag_func_run = FUNC_NOT_RUN;
printf("Quit GSM/GPRS function. byebye\n");
break;
}
default :
{
printf("please input your select use 1 to 7\n");
}
}
}
}
给出的文本提示选项:
void print_prompt(void)
{
printf ("Select what you want to do:\n");
printf ("1 : Simple Test\n");
printf ("2 : Read SIM CARD ID\n");
printf ("3 : Test GSM/GPRS signal\n");
printf ("4 : Make A Call\n");
printf ("5 : Wait A Call\n");
printf ("6 : Short message\n");
printf ("7 : Power manage\n");
printf ("8 : Quit\n");
printf (">");
} // end print_prompt
(2)各个测试子选项AT命令控制细节:case SIMPLE_TEST
void GSM_simple_test(int fd)
{
char *send_buf="at\r";
GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);
}
屏幕回显:
at
OK
(3)用到的公共函数
发送AT命令并读结果
void GSM_GPRS_send_cmd_read_result(int fd, char *send_buf, int rcv_wait)
{
char rcv_buf[2048];
if((send_buf==NULL) || (send_GSM_GPRS_cmd(fd,send_buf))){ // send success , then read
bzero(rcv_buf,sizeof(rcv_buf));
if (read_GSM_GPRS_datas(fd,rcv_buf,rcv_wait)){
printf ("%s\n",rcv_buf);
}
else{
printf ("read error\n");
}
}
else{
printf("write error\n");
}
}
发送AT命令
int send_GSM_GPRS_cmd(int fd, char *send_buf)
{
ssize_t ret;
ret = write(fd,send_buf,strlen(send_buf));
if (ret == -1)
{
printf ("write device %s error\n", DEVICE_TTYS);
return -1;
}
return 1;
}
读AT应答的结果
int read_GSM_GPRS_datas(int fd, char *rcv_buf,int rcv_wait)
{
int retval;
fd_set rfds;
struct timeval tv;
int ret,pos;
tv.tv_sec = rcv_wait; // wait 2.5s
tv.tv_usec = 0;
pos = 0; // point to rceeive buf
while (1) {
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
retval = select(fd+1 , &rfds, NULL, NULL, &tv);
if (retval == -1){ //超时
perror("select()");
break;
}
else if (retval)
{ //判断是否还有数据
ret = read(fd, rcv_buf+pos, 2048);
pos += ret; //读出的数据长度
if (rcv_buf[pos-2] == '\r' && rcv_buf[pos-1] == '\n'){ //如果读到字符串末尾
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
retval = select(fd+1 , &rfds, NULL, NULL, &tv);
if (!retval) break; // no datas, break
}
}
else{
printf("No data\n");
break;
}
}
return 1;
}
(4)接2,读SIM卡EF-CCID,case READ_SIM_CARD_ID
void GSM_read_sim_card_id(int fd)
{
char *send_buf="at+ccid\r";
GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);
}
屏幕回显:
at+ccid
89860076190753501064
(5)获得网络参数case GSM_GPRS_SIGNAL
void GSM_gprs_signal(int fd)
{
char *send_buf="at+creg?\r"; //网络注册
GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);
send_buf="at+cgreg?\r";
GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);
send_buf="at+csq\r"; //信号质量
GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);
send_buf="at+cops?\r"; //运营商信息
GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);
}
屏幕回显:
at+creg?
+CREG: 0,1
OK
at+cgreg?
+CGREG: 0,1
OK
at+csq
+CSQ: 25,0
OK
at+cops?
+COPS: 0,0,"CHINA MOBILE"
OK
(6)拨号case MAKE_A_CALL
void GSM_call(int fd)
{
char send_buf[17]; //发送缓冲区
char *send_cmd_ath = "ath\r"; //挂机命令
int i;
// input telephone number
bzero(send_buf,sizeof(send_buf));
send_buf[0]='a';
send_buf[1]='t';
send_buf[2]='d';
send_buf[16] = '\0';
printf("please input telephone number:");
i = 3;
while (1)
{
send_buf[i]=getchar(); //从标准输入设备“键盘”获取输入
if (send_buf[i]=='\n') break;
i++;
}
send_buf[i]=';'; //发送命令后加符号;
send_buf[i+1]='\r';
// end input telphone number
// send cmd
GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S); //拨号
//quit call
printf("press ENTER for quit:");
getchar(); //按任意键退出拨号
// send cmd
GSM_GPRS_send_cmd_read_result(fd,send_cmd_ath,RECEIVE_BUF_WAIT_1S); //挂机
}
屏幕回显:
please input telephone number:112
112
atd112;
OK
(7)等待电话case WAIT_A_CALL
void GSM_wait_call(int fd)
{
char rcv_buf[2048];
char *send_cmd_ath = "ath\r"; //挂机
int wait_RING;
wait_RING = 10; //等待10次
while (wait_RING!=0)
{
bzero(rcv_buf,sizeof(rcv_buf));
if (read_GSM_GPRS_datas(fd,rcv_buf,RECEIVE_BUF_WAIT_1S)){
printf ("%s\n",rcv_buf); //等待应答
}
else{
printf ("read error\n");
}
wait_RING--;
}
GSM_GPRS_send_cmd_read_result(fd,send_cmd_ath,RECEIVE_BUF_WAIT_1S);
printf("quit wait_call\n");
}
屏幕回显如下:有电话拨入则显示RING
No data
RING
No data
No data
No data
RING
No data
No data
No data
RING
ath
OK
quit wait_call
(8)短信息服务case SHORT_MESSAGE
void GSM_short_mesg(int fd)
{
int flag_sm_run, flag_sm_select;
flag_sm_run = FUNC_RUN;
while (flag_sm_run == FUNC_RUN)
{
printf ("\n Select:\n");
printf ("1 : Send short message \n");
printf ("2 : Read all short message \n");
printf ("3 : Config short message env\n"); //短消息中心
printf ("4 : quit\n");
printf (">");
scanf("%d",&flag_sm_select); //输入选择选项
getchar(); //等待键盘输入
switch (flag_sm_select)
{
case SEND_SHORT_MESSAGE : { GSM_Send_Message(fd); break; }
case READ_SHORT_MESSAGE : { GSM_Read_Message(fd); break; }
case CONFIG_SHORT_MESSAGE_ENV : { GSM_Conf_Message(fd); break; }
case QUIT_SHORT_MESSAGE : { flag_sm_run = FUNC_NOT_RUN; break; }
default :
{
printf("please input your select use 1 to 3\n");
}
}
}
printf ("\n");
} // end GSM_send_mesg
A,首先配置短信息中心
void GSM_Conf_Message(int fd)
{
char *send_buf="at+cmgf=1\r"; //设定SMS的控制方式
char *send_center_buf="at+csca=\"+8613800755500\"\r"; //短信服务中心地址
GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);
// set short message center number
GSM_GPRS_send_cmd_read_result(fd,send_center_buf,RECEIVE_BUF_WAIT_1S);
printf("end config short message env\n");
}
回显:
at+cmgf=1
OK
at+csca="+8613800571500"
OK
end config short message env
B, 发送信息
void GSM_Send_Message(int fd)
{
char cmd_buf[23];
char short_message_buf[MAX_LEN_OF_SHORT_MESSAGE];
int i;
char rcv_buf;
bzero(cmd_buf,sizeof(cmd_buf));
bzero(short_message_buf,sizeof(short_message_buf));
printf ("send short message:\n");
cmd_buf[0]='a';
cmd_buf[1]='t';
cmd_buf[2]='+';
cmd_buf[3]='c';
cmd_buf[4]='m';
cmd_buf[5]='g';
cmd_buf[6]='s';
cmd_buf[7]='=';
cmd_buf[8]='"'; //AT+CMGS发送短信息命令
printf ("please input telephone number:");
i = 9;
while (1)
{
cmd_buf[i]=getchar();
if (cmd_buf[i]=='\n') break;
i++; //输入号码
}
cmd_buf[i]='"';
cmd_buf[i+1]='\r';
cmd_buf[i+2]='\0'; //加上结束符
// send cmd : at+cmgs="(telephone number)"
GSM_GPRS_send_cmd_read_result(fd,cmd_buf,RECEIVE_BUF_WAIT_1S);
// input short message
printf("please input short message:");
i = 0;
while(i < MAX_LEN_OF_SHORT_MESSAGE-2)
{
short_message_buf[i] = getchar();
if (short_message_buf[i]=='\n') break;
i++;
}
short_message_buf[i] = 0x1A;
short_message_buf[i+1] = '\r';
short_message_buf[i+2] = '\0';
// send short message
GSM_GPRS_send_cmd_read_result(fd, short_message_buf,RECEIVE_BUF_WAIT_4S);
printf("\nend send short message\n");
}
回显:
send short message:
please input telephone number:13800138000
at+cmgs="13800138000"
OK
please input short message:teset
teset
teset
OK
C,读SIM卡的短信息
void GSM_Read_Message(int fd)
{
char *send_buf="at+cmgl=\"ALL\"\r"; //读出SIM卡的短信息
char rcv_buf[2048];
GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_3S);
printf("end read all short message\n");
}
回显:
at+cmgl="ALL"
+CMGL: 1,"REC READ","+8613800138000",,"11/03/17,21:44:39+32" 后面接着显示大量信息。完毕。
更多推荐
所有评论(0)