GPRS简述
GPRS模块发送短消息分为两种方式:
1.文本方式
2.PDU模式发送
其中文本方式发送较为简单,但是只能发送英文信息。PDU模式发送相对比较麻烦(数据处理)。
一.AT指令
GPRS需要用到的AT指令
模块开机后应该执行下面初始化流程
AT // 测试串口通讯是否正常
OK //返回Ok说明串口正常 ,返回ERROR说明串口未连通
AT+CPIN? // 查询是否检测到SIM卡
+CPIN: READY
OK
AT+CSQ // 查询信号质量
+CSQ: 18,0
OK
AT+CREG? // 查询模块是否注册网络
+CREG: 0,1
OK
AT+CGATT? // 查询模块是否GPRS
+CGATT: 1
OK
//以上全部正常再进行其它功能操作
二、 文本模式下发送短信流程
文本模式下发送信息基本分三步骤:
//测试:
//1.设置发送模式
AT+CMGF=1//CMGF为0是以PDU模式发送,为1则是以文本方式发送。
//2.接收方电话号码
AT+CMGS=18883765xxx
//3.输入内容
\>hello world !
在编程的时候,如果文本发送结束以后,需要按“ctrl+z”作为结束符,它的ascii码是“0x1a”。所以可以发送16进制1A(在串口助手中勾选HEX点发送)。
每次发送AT指令后,系统会自动回复OK作为应答,因此我们需要对OK做接受信号。
三.拨打电话功能实现
=====================================================
AT //首先测试
OK
/*拨打电话:*/
ADT18883765xxx; //拨打电话成功,注意AT指令不区分大小写,注意电话号码后面要加上分号“;”(英文格式的分号;)
ADT18883765xxx; //拨号成功
OK //电话拨通后会显示一个“OK”提示
OK //电话被接听后,又会显示一个“OK”提示
NO CARRIER //没人接听
RING
RING
RING //每“嘟”一声,就会出现一个“RING”命令提示(可能不显示)
ERROR //对方挂断
/*接听对方电话:*/
ATA
RING //对方拨号过来,显示“RING(红灯亮)”提示--戴上耳机(优美的音乐响起)
/*挂断电话*/
ATH; //挂断对方打过来的电话
OK
/*重拨上一次电话*/
ATDL;
OK
四.串口编程
我们知道在Windows系统下只需要串口连接发送AT指令集。
1.Linux下编程工作准备
那我在Linux下就需要移植USB的驱动并,配置串口驱动。移植CH341,PL2303,CP210X驱动。在make menuconfig下移植驱动。
设备产生/dev/ttyUSBx的设备节点,open_port()。
交叉编译与测试程序内进行设置串口设置。
串口配置函数
```C
void USB_UART_Config(char* path, int baud_rate);
int open_port(char *com_port);
int set_com_config(int fd, int baud_rate, int data_bits, char parity, int stop_bits){
struct termios new_cfg, old_cfg;
int speed;
/*保存原有串口配置*/
if (tcgetattr(fd, &old_cfg) != 0){
perror("tcgetattr");
return -1;
}
new_cfg =old_cfg;
/*配置为原始模式*/
cfmakeraw(&new_cfg);
new_cfg.c_cflag &= ~CSIZE;
/*设置波特率*/
switch (baud_rate){
case 2400:{
speed = B2400;break; }
case 4800:{
speed = B4800; break;}
case 9600:{
speed = B9600;break;}
case 19200:{
speed = B19200;break;}
case 38400:{
speed = B38400;break;}
default:
case 115000:{
speed = B115200;break;}
}
cfsetispeed(&new_cfg, speed);//设置输入速度
cfsetospeed(&new_cfg, speed);
/*设置数据位*/
switch (data_bits){
case 7:{
new_cfg.c_cflag |= CS7;break;}
default:
case 8:{
new_cfg.c_cflag |= CS8;break;}
}
/*设置奇偶校验位*/
switch (parity)
{
default:
case 'n':
case 'N':{
new_cfg.c_cflag &= ~PARENB;
new_cfg.c_iflag &= ~INPCK;
break; }
case 'o':
case 'O':{
new_cfg.c_cflag |= (PARODD |PARENB);
new_cfg.c_iflag |= INPCK;
break;}
case 'e':
case 'E':{
new_cfg.c_cflag |= PARENB;
new_cfg.c_cflag &= ~PARODD;
new_cfg.c_iflag |= INPCK;
break;}
case 's':
case 'S':{
new_cfg.c_cflag &= ~PARENB;
new_cfg.c_cflag &= ~CSTOPB;
break;}
}
/*设置停止位*/
switch (stop_bits)
{
default:
case 1:{
new_cfg.c_cflag &= ~CSTOPB;break;}
case 2:{
new_cfg.c_cflag |= CSTOPB;break;}
}
/*设置等待时间和最小接收字符*/
new_cfg.c_cc[VTIME] = 0;
new_cfg.c_cc[VMIN] = 1;
tcflush(fd, TCIFLUSH);
if ((tcsetattr(fd, TCSANOW, &new_cfg)) != 0){
perror("tcsetattr");
return -1;
}
return 0;
}
打开串口节点
```C
int open_port(char *com_port)
{
int fd;
/*打开串口*/
fd = open(com_port, O_RDWR|O_NOCTTY|O_NDELAY);
if (fd < 0){
perror("open serial port");
return -1;
}
/*恢复串口阻塞状态*/
if (fcntl(fd, F_SETFL, 0) < 0){
perror("fcntl F_SETFL\n");
}
/*判断是否为终端设备*/
if (isatty(fd) == 0){
perror("This is not a terminal device");
}
return fd;
}
USB配置
```C
void USB_UART_Config(char* path, int baud_rate){
int fd;
fd = open_port(path);
if(fd < 0){
printf("open %s failed\n",path);
return ;
}
if (set_com_config(fd, baud_rate, 8, 'N', 1) < 0){
perror("set_com_config");
return ;
}
close(fd);
return ;
}
```c
在这里插入代码片
2.实现Linux编程收发封装
全局变量设置
#include "data_global.h"
#include "linuxuart.h"
extern struct msg msgbuf;
extern pthread_mutex_t mutex_sms;
extern pthread_cond_t cond_sms;
extern char recive_phone[12];
extern char center_phone[12];
extern char *message;
int gprs_fd; //GPRS管道符
void call_tel(char *tel); //打电话
void send_message(char *tel,char *msg); //发短息
pthread_sms线程
void *pthread_sms(void *arg){
printf("pthread_sms\n");
while(1){
pthread_mutex_lock(&mutex_sms);
pthread_cond_wait(&cond_sms,&mutex_sms);
if ((gprs_fd = open_port(GPRS_DEV)) < 0){
perror("open_port");
return ;
}
printf("gprs_fd :%d.\n",gprs_fd);
if (set_com_config(gprs_fd, 9600, 8, 'N', 1) < 0){
perror("set_com_config");
return;
}
sleep(1);
call_tel(recive_phone);
//send_message(recive_phone,message);
close(gprs_fd);
pthread_mutex_unlock(&mutex_sms);
}
}
打电话
void call_tel(char *tel)
{
printf("enter call_tel .....\n");
int n=0,ret=0,num=0;
char end=26;
char buff[128]={0};
memset(buff,0,128);//测试串口是否正常工作,尽可能的多判断返回值
strcpy(buff,"AT\n"); //发送AT进行测试
write (gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128); //读取“OK”消息
if(strncmp(buff,"OK",2)){
printf("serial port connected success \n");
}else{
printf("serial port connected failed \n");
}
sleep(1);
printf("tel ......\n");
memset(buff,0,128);
sprintf(buff,"ATD%s;",recive_phone); //打电话------>从Html中抓取的打给的电话
strcat(buff,"\n");
printf("buff :%s.\n",buff);
write (gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128);
printf("read from gprs 拨打:%s\n",buff);
sleep(15); //15s之后挂断
printf("挂断.....");
memset(buff,0,128);//挂断电话
strcpy(buff,"ATH;");
strcat(buff,"\n");
write (gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128);
printf("read from gprs 挂断:%s\n",buff);
sleep(15);
printf("重拨....\n");
memset(buff,0,128);//测试串口是否正常工作,尽可能的多判断返回值
strcpy(buff,"ATDL;");
strcat(buff,"\n");
write (gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128);
printf("read from gprs 重拨:%s\n",buff);
sleep(10);
return ;
}
发送消息
void send_message(char *tel,char *msg)
{
printf("enter send_message .....\n");
int n=0,ret=0,num=0;
char end=26;
char buff[128]={0};
memset(buff,0,128);//测试串口是否正常工作,尽可能的多判断返回值
strcpy(buff,"AT\n");
write (gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128);
if(strncmp(buff,"OK",2)){
printf("serial port connected success \n");
}else{
printf("serial port connected failed \n");
}
usleep(10000);
memset(buff,0,128);
strcpy(buff,"AT+CPIN?\n");//查询是否检测到SIM卡
write (gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128);
printf("set coding type success,SIM卡成功检测到.\n");
usleep(10000);
memset(buff,0,128);
strcpy(buff,"AT+CMGF=1\n"); //设置短信发送模式
write (gprs_fd,buff,strlen(buff)); // CMGF :0(默认):PDU模式 1:文本模式
read(gprs_fd,buff,128);
if(strncmp(buff,"OK",2)){
printf("set message type success \n");
}else{
printf("set message type failed\n");
}
usleep(100000);
memset(buff,0,128);
strcpy(buff,"AT+CSCS?\n"); //查询短信编码方式 , CSCS编码设置 短信相关常用主要是GSM、UCS2编码格式
write (gprs_fd,buff,strlen(buff)); // 模块会根据SIM卡自动设置短消息中心号码,只做查询即可
read(gprs_fd,buff,128);
printf("the coding type is \n");
usleep(100000);
memset(buff,0,128);
strcpy(buff,"AT+CSMP=17,167,0,240\n"); //参数4:241 短信存在sim卡中 240直接在终端显示
write (gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128);usleep(10000);
printf("message save at sim card!\n");
usleep(100000);
memset(buff,0,128);
strcpy(buff,"AT+CMGDA=6\n"); //删除之前发送的信息与指令
write (gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128);
if(strncmp(buff,"OK",2)){
printf("delect message success!\n");
}else{
printf("delect failed!\n");
}
memset(buff,0,128);
printf("recive_phone :%s strlen %d sizeof%d.\n"
,recive_phone,strlen(recive_phone),sizeof(recive_phone)/sizeof(recive_phone[0]));
sprintf(buff,"AT+CMGS=\"%s\"",recive_phone); //发送短信
strcat(buff,"\n");
write (gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128);
if(strncmp(buff,">",1))
{
if(message=='\0')
{
printf("please input the message information :");
scanf("%s",buff);
//strcpy(buff,"hello boy,come on!.\n");
write(gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128);
write(gprs_fd,&end,1);
read(gprs_fd,buff,128);
}else{
strcpy(buff,message);
write(gprs_fd,buff,strlen(buff));
read(gprs_fd,buff,128);
write(gprs_fd,&end,1);
read(gprs_fd,buff,128);
}
n=strlen(buff);
if(strncmp(&buff[n-1],"O",1)&&strncmp(&buff[n],"K",1)){
printf("send message success :%s\n",msg);
}else{
printf("send message failed\n");
}
sleep(1);
}else{
printf("send message failed!\n");
}
sleep(2);
return ;
}