一、对于已经移植好USB驱动的4G模块
为了能测试USB驱动程序,使用华为4G模块进行打电话实验,就这个实验最吸引人,效果最显著,电话相关的AT指令如下:
1-----ATDxxxxxxxxxxx;//最后的分号不能掉
2-----ATH//挂机
3-----ATA//接电话
经过多次实验,最后选择了使用select函数,监听标准输入stdin的变化,一旦有变化,马上开始读入输入的AT指令。
/*
* 测试嵌入式开发板上的华为4G模块的串口测试程序
*
*/
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <errno.h>
#include <termios.h>
#define MAX_BUFF 1024
#define MAX_RED 20
/*
* 对select函数功能进行初始化
*/
fd_set rdfds; /* 先申明一个 fd_set 集合来保存我们要检测的 socket句柄 */
struct timeval tv; /* 申明一个时间变量来保存时间 */
void select_init(void)
{
//int ret; /* 保存返回值 */
FD_ZERO(&rdfds); /* 用select函数之前先把集合清零 */
FD_SET(0, &rdfds); /* 把要检测的句柄socket加入到集合里 */
tv.tv_sec = 3;
tv.tv_usec = 500; /* 设置select等待的最大时间为1秒加500微秒 */
}
//char *menu="1.dial\n 2.dial-off\n 3.GET-TELE\n 4.SEND-MSG\n"
//flag变量代表了这个输入的命令是否改变
//flag==0 ---没有改变
//flag==1 ---改变
int choice,flag=0;
/*
* 时常扫描是否有按键值输入,周期性的去执行
*/
/******************************
static void getopt(int signo)
{
printf("----0.test\n----1.dial\n----2.dial-off\n----3.get-tele\n----4.send-msg\n----5.exit\n");
//scanf("%d",&choice);
do{
//printf("please enter your choice->");
scanf("%d",&choice);
}while(!(choice==0 || choice==1 || choice==2 || choice==3 || choice==4));
}
*******************************/
void menu(void)
{
printf("----0.test\n----1.dial\n----2.dial-off\n----3.get-tele\n----4.send-msg\n----5.exit\n");
do{
printf("please enter your choice->");
scanf("%d",&choice);
}while(!(choice==0 || choice==1 || choice==2 || choice==3 || choice==4 || choice==5));
}
/*
* 串口初始化程序
*/
void serial_init(int fd)
{
struct termios options;
tcgetattr(fd, &options);
//CLOCAL和CREAD分别用于本地连接和接受使能,
//因此,首先要通过位掩码的方式激活这两个选项
options.c_cflag |= ( CLOCAL | CREAD );
//设置数据位为八位
options.c_cflag &= ~CSIZE;
options.c_cflag &= ~CRTSCTS;
options.c_cflag |= CS8;
options.c_cflag &= ~CSTOPB;
options.c_iflag |= IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
//cfsetispeed(&options, B9600);
//cfsetospeed(&options, B9600);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
tcsetattr(fd,TCSANOW,&options);
}
int main(int argc , int **argv)
{
int fd,ret;
int rd,wd,rd_stdin;
char buff[MAX_BUFF],replay[MAX_BUFF],buff_read[MAX_RED]="ATI\r\n";
//signal(SIGALRM,getopt);
fd = open("/dev/ttyUSB0", O_RDWR,0);
if(fd == -1){
printf("can't open ttyUSB0");
return 0;
}
//printf("----0.test\n----1.dial\n----2.dial-off\n----3.get-tele\n----4.send-msg\n----5.exit\n");
//do
//{
// printf("please enter your choice->");
// scanf("%d",&choice);
//}while(!(choice==0 || choice==1 || choice==2 || choice==3 || choice==4));
//buff_read[] = "ATI";
serial_init(fd);
memset(buff,0,sizeof(buff));
strcpy(buff,"ATI\r\n");
wd = write(fd,buff,sizeof(buff));
while(1)
{ /* 检测我们上面设置到集合rdfds里的句柄是否有可读信息 */
select_init();//每次最好初始化一次
ret = select(1, &rdfds, NULL, NULL, &tv);
if(ret < 0)
perror("select");/* 这说明select函数出错 */
else if(ret == 0)
printf("beyond time\n"); /* 说明在我们设定的时间值3秒加500毫秒的时间内,sstdin的状态没有发生变化 */
else
{ /* 说明等待时间还未到1秒加500毫秒,socket的状态发生了变化 */
/*
*ret这个返回值记录了发生状态变化的句柄的数目,
*由于我们只监视了stdin这一个句柄,所以这里一定ret=1,
*如果同时有多个句柄发生变化返回的就是句柄的总和了
*/
printf("ret=%d\n", ret);
/* 这里我们就应该从stdin这个句柄里读取数据了,因为select函数已经告诉我们这个句柄里有数据可读 */
if(FD_ISSET(0, &rdfds)) { /* 先判断一下stdin这外被监视的句柄是否真的变成可读的了 */
/* 读取socket句柄里的数据 */
flag = 1;//说明命令改变
memset(buff_read,0,sizeof(buff_read));
rd_stdin = read(0,buff_read,sizeof(buff_read));
printf("stdin rd_stdin=%d,---%s\n",rd_stdin,buff_read);
}
}
if(flag){
flag = 0;
memset(buff,0,sizeof(buff));
strcpy(buff,buff_read);
strcat(buff,"\r\n");
wd = write(fd,buff,sizeof(buff));
memset(replay,0,sizeof(replay));
rd = read(fd,replay,sizeof(replay));
printf("rd=%d,---%s\n",rd,replay);
}
else{
memset(replay,0,sizeof(replay));
rd = read(fd,replay,sizeof(replay));
printf("rd=%d,---%s\n",rd,replay);
}
}
close(fd);
}
以上测试程序可以实现大多数AT指令的实现,但是还需要添加与短信相关的功能。为了能快速浏览这个
程序框架,大概的总结一下流程-------1.初始化串口传输,设置波特率,数据位。--------2.对select函数进行一些初始化,设置要监听的描述符,和监听超时时间