Linux下GPRS短信收发编程

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 ;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值