串口应用实例——手机短信发送

发布时间:

百度文库 - 让每个人平等地提升自我!

串口应用实例——手机短信发送
一:简介
PC与手机通过串口连接,通过电脑控制手机发送短信,由于最近几年手机大多都提供USB接口,通过手机USB驱动程序在手机和PC之间建立虚拟串口设备。由于大多数安卓手机和苹果手机很难找到linux下的虚拟驱动软件,所以采用早起的诺基亚手机,使用一个名为Gnokii的手机驱动软件。手机采用NOKIA 6300手机进行操作。

二:AT指令简介
AT AttentionAT指令集是从终端设备(Terminal EquipmentTE数据终端设备(Data Terminal EquipmentDTE向终端适配器(Terminal Adapter TA数据电路终端设备(Data Circuit Terminal EquipmentDCE发送的。通过TATE发送AT指令来控制移动台(Mobile StationMS的功能,GSM 网络业务进行交互。用户可以通过AT指令进行呼叫、短信、电话本、数据业务、传真等方面的控制。90年代初,AT指令仅被用于Modem操作。没有控制移动电话文本消息的先例,只开发了一种叫SMS BlockMode的协议,通过终端设(TE或电脑来完全控制 SMS。几年后,主要的移动电话生产厂商诺基亚、爱立信、摩托罗拉和HP共同为GSM研制了一整套AT指令,其中就包括对SMS的控制。AT指令在此基础上演化并被加入GSM0705标准以及现在的GSM0707标准,完全标准化和比较健全的标准。如:对SMS的控制共有3种实现途径:最初的BlockMode;基于AT指令TextMode;基于AT指令的PDUMode。到现在PDUMode已经取代BlockMode,后者逐渐淡出。GSM模块与计算机之间的通信协议是一些AT指令集,AT指令是以AT作首,字符结束的字符串,AT指令的响应数据包在中。每个指令执行成功与否都有相应的返回。其他的一些非预期的信息(如有人拨号进来、线路无信号等,模块将有对应的一些信息提示,接收端可做相应的处理。

由于本次只用到短信的AT指令所以只介绍AT指令集中的短信收发功能指令 GSM AT 指令集
1 AT+CSMS 选择消息服务。支持的服务有GSM-MOSMS-MTSMS-CB 2 AT+CNMA 新信息确认应答。

3 AT+CPMS 优先信息存储。这个命令定义用来读写信息的存储区域。 4 AT+CMGF 优先信息格式。执行格式有TEXT方式和PDU方式。 5 AT+CSAS 保存设置。保存+CSAS+CSMP的参数。 6 AT+CRES 恢复设置。

7 AT+CSDH 显示文本方式的参数。

8 AT+CNMI 新信息指示。这个命令选择如何从网络上接收短信息。 9 AT+CMGR 读短信。信息从+CPMS命令设定的存储器读取。 10 AT+CMGL 列出存储的信息。 11 AT+CMGS 发送信息。

12 AT+CMGW 写短信息并存储。 13 AT+CMSS 从存储器中发送信息。 14 AT+CSMP 设置文本模式的参数。

15 AT+CMGD 删除短信息。删除一个或多个短信息。 16 AT+CSCA 短信服务中心地址。 17 AT+CSCB 选择单元广播信息类型。 18 AT+WCBM 单元广播信息标识。

19 AT+WMSC 信息状态(是否读过、是否发送等等)修正。 20 AT+WMGO 信息覆盖写入。
1
百度文库 - 让每个人平等地提升自我!

21 AT+WUSS 不改变SMS状态。在执行+CMGR+CMGL后仍保持UNREAD
三:PDU编码简介
目前,发送短消息常用TextPDU(Protocol Data Unit,协议数据单元模式。使用Text模式收发短信代码简单,实现起来十分容易,但最大的缺点是不能收发中文短信;而PDU模式不仅支持中文短信,也能发送英文短信。PDU模式收发短信可以使用3种编码:7-bit8-bitUCS2编码。7-bit编码用于发送普通的ASCII字符,8-bit编码通常用于发送数据消息,UCS2编码用于发送Unicode字符。一般的PDU编码由A B C D E F G H I J K L M十三项组成。

A:短信息中心地址长度,2位十六进制数(1字节 B:短信息中心号码类型,2位十六进制数。
C:短信息中心号码,B+C的长度将由A中的数据决定。 D:文件头字节,2位十六进制数。 E:信息类型,2位十六进制数。 F:被叫号码长度,2位十六进制数。
G:被叫号码类型,2位十六进制数,取值同B H:被叫号码,长度由F中的数据决定。 I:协议标识,2位十六进制数。
J:数据编码方案,2位十六进制数。 K:有效期,2位十六进制数。
L:用户数据长度,2位十六进制数。
M:用户数据,其长度由L中的数据决定。J中设定采用UCS2编码,这里是中英文的Unicode字符。
需要注意的是,PDU串的用户信息长度(TP-UDL,在各种编码方式下意义有所不同。7-bit编码时,指原始短消息的字符个数,而不是编码后的字节数。8-bit编码时,就是字节数。UCS2编码时,也是字节数,等于原始短消息的字符数的两倍。如果用户信息(TP-UD中存在一个头(基本参数的TP-UDHI1,在所有编码方式下,用户信息长度(TP-UDL等于头长度与编码后字节数之和。如果采用GSM 03.42所建议的压缩算法(TP-DCS的高3位为001,则该长度也是压缩编码后字节数或头长度与压缩编码后字节数之和。 Text Mode下,发送及接收到的数据均以ASCII码的形式来表示。PDU Mode下,短信息正文经过十六进制编码后被传送。PDU相当于一个数据包,它由构成消息(SMS的信息组成。作为一种数据单元,它必须包含源/目的地址、保护(有效)时间、数据格式、协议类型和正文,正文长度可达140字节,它们都以十六进制表示。PDU结构根据短消息由移动终端发起或以移动终端为目的而不同。每条消息可以发送140个字节,由于本系统中最长的数据串没有超过140个字节,因此数据均可以用一条消息来发送。
考虑到GSM传输存在时延问题,与卫星传输方式一样,双方的数据收发均只采用自报方式。即:终端站采用定时自报方式主动向后台中心发射数据,后台中心被动接收;当后台中心需要终端站当前的数据或需要对终端站参数进行设置时,后台中心只向该终端站发射相应的命令包,终端站收到该命令时,根据不同的命令以自报方式发送后台中心所要数据或修改相应的参数。
2
百度文库 - 让每个人平等地提升自我!

四:用AT指令发送短信的代码:
#include #include #include #include #include #include #include #include #include
#define STTY_DEV "/dev/ttyS0" #define BUFF_SIZE 512
int Setoption(int fd { struct termios opt; //获得当前串口设置 tcgetattr(fd,&opt; tcflush(fd,TCIOFLUSH; //设置波特率 cfsetispeed(&opt,B19200; cfsetospeed(&opt,B19200; //设置数据位 8 options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; /* Set the timeout options */ options.c_cc[VMIN] = 0; options.c_cc[VTIME] = 10; options.c_cc[VTIME] = 10;
if(0!=tcsetattr(fd, TCSANOW, &options; perror("set baudrate"; return -1; tcflush(fd,TCIOFLUSH; return 0; } int main( { int stty_fd ,n; iconv_t cd; char buffer[BUFF_SIZE]; char phone[20]="86 " char sms_number[20]="+86 " char sms_gb2312[140]="工作愉快
3
百度文库 - 让每个人平等地提升自我!

char sms_utf8[140]; char *sms_in=sms_gb2312; char *sms_out=sms_utf8; int str_len,i,tmp; int sms_utf8,gb2312_len; //打开串口设备 fd=open("/dev/ttyS0", O_RSWR;//只读方式 if(-1==fd { perror("open device"; return 0; } printf("open device OK!\n"; if(0!=Setoption(fd { close (fd;//关闭串口 return 0; }

/*转换电话号码*/ if (phone[0]=='+'{ for (i=0;ii++ phone[i]=phone[i+1]; } phone[i]='\0'; str_len=strlen(phone; if ((strlen(phone%2!=0{ phone[str_len]='F'; phone[str_len+1]='\0'; } for (i=0;i { tmp=phone[i]; phone[i]=phone[i+1]; phone[i+1]=temp; } /*转换短信中心号码*/ if (sms_number[0]=='+' { for(i=0;i sms_number[i]=sms_number[i+1]; } sms_number[i]='\0'; str_len=strlen(sms_number; if ((strlen(sms_number%2!=0{ sms_number[str_len]='F'; sms_number[str_len+1]='\0'; 4
百度文库 - 让每个人平等地提升自我!

5
} for (i=0;i{ tmp=sms_number[i]; sms_number[i]=sms_number[i+1]; sms_number[i+1]=temp; } str_len=strlen(sms_number; for(i=strlen(sms_number+2;i!=0;i-- sms_number[i]=sms_number[i-2]; sms_number[str_len+3]='\0'; strncpy(sms_number,"91",2; temp=strlen(sms_number/2; str_len=strlen(sms_number; for(i=strlen(sms_number+2;i!=0;i-- sms_number[i]=sms_number[i-2];

sms_number[str_len+3]='\0'; sms_number[0]=(char(tmp/10+0x30; sms_number[0]=(char(tmp%10+0x30; /*转换短信内容*/ cd=iconv_open("utf-8","gb2312"; if (0==cd; { perror("creat iconv handle !"; close (fd; return 0; } gb2312_len=strlen(sms_gb2312; utf8_len=140; if (-1==iconv(cd,&sms_in,&gb2312_len, &sms_out,&utf8_len{ perror("convert code"; close(fd; return 0; } iconv_close(cd; /*设置使用PDU模式*/ strcpy(buffer,"AT+CMGF=0\n"; write(fd,buffer,strlen(buffer; n=read(fd,buffer,BUFF_SIZE; if (n<=0{ perror("set pdumode"; close(fd; return 0; } if (0!=strncmp(buffer,"ok",2{
百度文库 - 让每个人平等地提升自我!




perror("set pudmoade"; close(fd; return 0; } /*发送信息*/ sprintf(buffer,"AT+GMGS=%d\n",utf8_len; write(fd,buffer,strlen(buffer; write(fd,sms_utf8,utf8_len; printf("send message ok\n"; close (fd; } 五:实验总结:
root权限运行程序,执行成功后手机会发送短信到指定号码,通过了电脑控制了手机发送短信的功能,并且在做实验过程出现很多问题,首先就是下载的驱动是在windows下面的,linux软件中心找不到,所以通过构建了samba服务器,建立于虚拟机的共享,最终安装上了,刚开始手机给别人发短信过程总是出现问题,只能给自己发短信,最后找了很久原来是PDU编码出现了问题,最后改了下能够顺利实现短信的发送。

6

串口应用实例——手机短信发送

相关推荐