首页 > 技术文章 > linux下GPRS模块的应用程序

xiaohexiansheng 2016-08-05 13:58 原文

------------------------------------------------------------------------------------------------------------------------------

交叉编译器:arm-linux-gcc-4.5.4

Linux内核版本:Linux-3.0

主机操作系统:Centos 6.5

开发板:FL2440

GPRS:SIM900A

在开发SIM900模块之前,开发板已经加载了linux内核以及文件系统,并且开发板串口已经使能。并且一定要注意的是:要有一张没有欠费的电话卡!

------------------------------------------------------------------------------------------------------------------------------

参考文档

http://www.cnblogs.com/thinkinglife/p/3986006.html

 

一、GPRS模块简介

GPRS模块,是具有GPRS数据传输功能的GSM模块。GPRS模块就是一个精简版的手机,集成GSM通信的主要功能于一块电路板上,具有发送短消息、通话、数据传输等功能。GPRS模块相当于手机的核心部分,如果增加键盘和屏幕就是一个完整的手机。普通电脑或者单片机可以通过RS232串口与GPRS模块相连,通过AT指令控制GPRS模块实现各种基于GSM的通信功能。 制作串口线将  GPRS模块的串口和开发板的串口连接起来(我连接的是开发的第二个串口,因为第一个串口连接PC了)。

 

二、打开GPRS模块

这个地方介绍GPRS的打开方式看起来有些傻逼,不过第一次拿到GPRS模块并且没有任何人指导的情况下可能真的不会打开。

首先插上手机卡,必须是以前的大卡,如果是小卡的话也可以,需要对准之后放上去才能工作。然后拨动GPRS模块的拨码开关,在GPRS模块的最下方,一个很明显很大的拨码开关。最后在拨码开关的左上方有一个黑色的小按钮SW1,按下按钮让让SIM开始工作,搜索网络这时发光二极管D3会闪烁。

 

三、AT命令 

GPRS模块在Linux环境下操作不需要移植任何东西,只需要在Linux下用AT命令通过串口读取、写入信息就可以实现对GPRS模块的操作。AT命令的使用方法网上有许多,这里就不一一解释了,没有太多意义。只简单的介绍一下打电话发短信必要的命令就可以了。

以下都是在开发板上的操作:

#microcom -t 15000 -s 115200 /dev/ttyS0      //linux下的串口调试软件microcom

-t 单位毫秒,无操作自动退出时间。

ttyS0 要操作的串口。

接下来的命令都是往串口中写的了。

AT    //检测串口是否OK,若返回OK表示是可以用的

打电话:

atd***********;    //后面的***********是电话号码,【注意】“;”一定要有

ath    //挂断电话

当有电话来时,串口会打印RING。如果GPRS模块上插有耳机,可以听到提示来电的声音。

ata    //接通电话

ath    //挂断电话

发短信:

AT+CMGF=1    //选择短消息格式 1对应文本格式 0对应PDU模式,支持中文,中文短信发送时候需要转码。

AT+CMGS="GSM"    //设置字符格式为GSM模式,可不用设置

at+cmgs="***********"    //***********是11位手机号

输入之后回车显示一个 >  提示输入文本,这个时候输入文本。注意:输入文本完毕之后不敲回车而是敲ctrl+z表示输入完毕。

接受短信:

AT+CNMI=3,2    //设置GPRS为来短信提示新短信状态

 

三、C程序实现打电话发短信接电话收短信功能

开始的时候写了两个程序:一个是打电话发短信的,一个是接电话接短信的。因为这两个程序不能同时运行,所以后来想要整合在一起的时候一直想的是用双线程或双进程,每个进程各自运行一个程序。后来想模仿手机打电话的功能:一般我们的手机都是处于接电话与接短信的状态,如果手机想要打电话或者发短信则按相应按键进入相应函数。那么我的程序也可以这样实现,让程序一直跑在接电话与接短信的状态,一旦键盘上有想要打电话与发短信的输入则进入打电话发短信的函数。

  1 /*********************************************************************************
  2  *      Copyright:  (C) 2016 2013dianxin_3
  3  *                  All rights reserved.
  4  *
  5  *       Filename:  kbhit.c
  6  *    Description:  This file 
  7  *                 
  8  *        Version:  1.0.0(08/04/2016)
  9  *         Author:  xiaohexiansheng <1392195453@qq.com>
 10  *      ChangeLog:  1, Release initial version on "08/04/2016 01:23:17 PM"
 11  *                 
 12  ********************************************************************************/
 13 #include <termios.h>
 14 #include <string.h>
 15 #include <sys/types.h>
 16 #include <sys/stat.h>
 17 #include <stdio.h>
 18 #include <termios.h>
 19 #include <unistd.h>
 20 #include <fcntl.h>
 21 
 22 #define len_message 128
 23 #define len_number 16
 24 #define len_swap 32
 25 
 26 //信息结构体,包括号码和信息
 27 struct message_info                
 28 {
 29     char phnu[len_number];
 30     char message[len_message];
 31 };
 32 
 33 //初始化串口
 34 void serial_init(int fd)        
 35 {
 36     struct termios options;
 37     tcgetattr(fd, &options);
 38     options.c_cflag |= (CLOCAL | CREAD);
 39     options.c_cflag &= ~CSIZE;
 40     options.c_cflag &= ~CRTSCTS;
 41     options.c_cflag |= CS8;
 42     options.c_cflag &= ~CSTOPB;
 43     options.c_iflag |= IGNPAR;
 44     options.c_oflag  = 0;
 45     options.c_lflag  = 0;
 46 
 47     cfsetispeed(&options, B115200);                //根据自己的波特率进行相应更改
 48     cfsetospeed(&options, B115200);
 49     tcsetattr(fd, TCSANOW, &options);
 50 };
 51 
 52 //非阻塞判断函数,用于判断键盘上有没有输入
 53 int kbhit(void)                    
 54 {
 55     struct termios oldt, newt;
 56     int ch;
 57     int oldf;
 58     tcgetattr(STDIN_FILENO, &oldt);
 59     newt = oldt;
 60     newt.c_lflag &= ~(ICANON | ECHO);
 61     tcsetattr(STDIN_FILENO, TCSANOW, &newt);
 62     oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
 63     fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
 64     ch = getchar();
 65     tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
 66     fcntl(STDIN_FILENO, F_SETFL, oldf);
 67     if(ch != EOF)
 68     {
 69         ungetc(ch, stdin);
 70         return 1;
 71     }
 72     return 0;
 73 }
 74 
 75 
 76 //发短信的函数
 77 int send(int fd, char *cmgf, char *cmgs, char *message)            
 78 {
 79     int nwrite;
 80     int nread;
 81     char buff[len_message];            //用于向串口中写数据的buff
 82     char replay[len_message];        //用于读串口中数据的buff
 83 
 84     memset(buff, 0, len_message);
 85     strcpy(buff, "AT\r");
 86     nwrite = write(fd, buff, strlen(buff));        //将buff中的数据写入串口
 87     printf("nwrite = %d, %s\n", nwrite, buff);
 88 
 89     memset(replay, 0, len_message);
 90     sleep(1);
 91     nread = read(fd, replay, sizeof(replay));    //读取串口中的数据到replay
 92     printf("nread = %d, %s\n", nread, replay);
 93 
 94     memset(buff, 0, len_message);
 95     strcpy(buff, "AT+CMGF=");
 96     strcat(buff, cmgf);
 97     strcpy(buff, "\r");
 98     nwrite = write(fd, buff, strlen(buff));
 99     printf("nwrite = %d, %s\n", nwrite, buff);
100 
101     memset(replay, 0, len_message);
102     sleep(1);
103     nread = read(fd, replay, sizeof(replay));
104     printf("nread = %d, %s\n", nread, replay);
105 
106     memset(buff, 0, len_message);
107     strcpy(buff, "AT+CMGS=");
108     strcat(buff, cmgs);
109     strcat(buff, "\r");
110     nwrite = write(fd, buff, strlen(buff));
111     printf("nwrite = %d, %s\n", nwrite, buff);
112 
113     memset(replay, 0, len_message);
114     sleep(1);
115     nread = read(fd, replay, sizeof(replay));
116     printf("nread = %d, %s\n", nread, replay);
117 
118     memset(buff, 0, len_message);
119     strcpy(buff, message);
120     nwrite = write(fd, buff, strlen(buff));
121     printf("nwrite = %d, %s\n", nwrite, buff);
122 
123     memset(replay, 0, len_message);
124     sleep(1);
125     nread = read(fd, replay, sizeof(replay));
126     printf("nread = %d, %s\n", nread, replay);
127     
128     return 0;
129 }
130 
131 int send_en_message()
132 {
133     int fd;
134     struct message_info info;
135     fd = open("/dev/ttyS1",O_RDWR|O_NOCTTY|O_NDELAY);
136     
137     if(fd < 0)
138     {
139         perror("Can not open ttyS1!\n");
140     }
141     getchar();                        //读取缓冲区中的一个回车,不然下面读取缓冲区数据的时候会出错
142     char cmgf[] = "1";
143     char cmgs[16] = {'\0'};
144     int conter = 0;
145 
146     printf("Please enter your number:\n");
147     fgets(info.phnu, (len_number-1), stdin);
148     while(strlen(info.phnu) != 12)
149     {
150         if(conter == 3)
151         {
152             printf("contr out!\n");
153             return -1;
154         }
155         printf("Your number is not standard,please enter again.\n");
156         fgets(info.phnu, (len_number - 1), stdin);
157         conter++;
158     }
159     printf("Enter your message:\n");
160     fgets(info.message, (len_message), stdin);
161     strcat(info.message, "\x1a");
162     strcat(cmgs, "\"");
163     strcat(cmgs, info.phnu);
164     cmgs[12] = (char){'\"'};
165 
166     send(fd, cmgf, cmgs, info.message);
167     close(fd);
168 
169     return 0;
170 }
171 
172 void send_ch_message()                    //这里没有支持发送中文短信
173 {
174     printf("send_ch_message.\n");
175 }
176 
177 int call(int fd, char *atd)
178 {
179     int nread;
180     int nwrite;
181     char buff[len_message];
182     char replay[len_message];
183 
184     memset(buff, 0, len_message);
185     strcpy(buff, "at\r");
186     nwrite = write(fd, buff, strlen(buff));
187     printf("nwrite = %d, %s\n", nwrite, buff);
188 
189     memset(replay, 0, len_message);
190     sleep(1);
191     nread = read(fd, replay, sizeof(replay));
192     printf("nread = %d, %s\n", nread, replay);
193 
194     memset(buff, 0, strlen(buff));
195     strcpy(buff, "atd");
196     strcat(buff, atd);
197     strcat(buff, "\r");
198     nwrite = write(fd, buff, strlen(buff));
199     printf("nwrite = %d, %s\n", nwrite, buff);
200 
201     memset(replay, 0, len_message);
202     sleep(1);
203     nread = read(fd, replay, sizeof(replay));
204     printf("nread = %d, %s\n", nread, replay);
205 
206     printf("Enter 4 to Hang up!\n");
207     char choice = getchar();
208     getchar();
209     switch(choice)
210     {
211         case'4':
212             memset(buff, 0, len_number);
213             strcpy(buff, "ath\r");
214             nwrite = write(fd, buff, strlen(buff));
215             printf("nwrite = %d, %s\n", nwrite, buff);
216 
217             memset(replay, 0, len_number);
218             sleep(1);
219             nread = read(fd, replay, sizeof(replay));
220             printf("nread = %d, %s\n", nread, replay);
221         default:
222             break;
223     }
224     return 0;
225 }
226 
227 //打电话的函数
228 int call_phone()
229 {
230     int fd;
231     int conter = 0;
232     char atd[16] = {'\0'};
233     struct message_info info;
234 
235     fd = open("/dev/ttyS1",O_RDWR|O_NOCTTY|O_NDELAY);
236     {
237         perror("Can not open ttyS1!\n");
238     }
239 
240     getchar();
241     printf("Enter your phonenumber:\n");
242     fgets(info.phnu, (len_number - 1), stdin);
243     while(strlen(info.phnu) != 12)
244     {
245         if(conter == 3)
246         {
247             printf("conter out!\n");
248             return -1;
249         }
250         printf("Your number is not standard,please enter again.\n");
251         fgets(info.phnu, (len_number - 1), stdin);
252         conter++;
253     }
254     strcat(atd, info.phnu);
255     atd[11] = (char){';'};
256     call(fd, atd);
257     close(fd);
258     return 0;
259 }
260 
261 //来电时拒接电话的函数
262 int refuse(int fd)
263 {
264     int nwrite;
265     int nread;
266     char buff[len_number];
267     char replay[len_number];
268 
269     getchar();
270     memset(buff, 0, len_number);
271     strcpy(buff, "ath\r");
272     nwrite = write(fd, buff, strlen(buff));
273     printf("nwrite = %d, %s\n", nwrite, buff);
274 
275     memset(replay, 0, len_number);
276     sleep(1);
277     nread = read(fd, replay, sizeof(replay));
278     printf("nread = %d, %s\n", nread, replay);
279 
280     return 0;
281 }
282 
283 //来电时接电话的函数
284 int receive(int fd)
285 {
286     char replay[len_number];
287     char buff[len_number];
288     int nwrite;
289     int nread;
290     int choice;
291 
292     getchar();
293     memset(buff, 0, len_number);
294     strcpy(buff, "ata\r");
295     nwrite = write(fd, buff, strlen(buff));
296     printf("nwrite = %d, %s\n", nwrite, buff);
297 
298     memset(replay, 0, len_number);
299     sleep(1);
300     nread = read(fd, replay, sizeof(replay));
301     printf("nread = %d, %s\n", nread, replay);
302 
303     printf("Enter 4 to Hang up!\n");
304     choice = getchar();
305     getchar();
306     switch(choice)
307     {
308         case'4':
309             memset(buff, 0, len_number);
310             strcpy(buff, "ath\r");
311             nwrite = write(fd, buff, strlen(buff));
312             printf("nwrite = %d, %s\n", nwrite, buff);
313 
314             memset(replay, 0, len_number);
315             sleep(1);
316             nread = read(fd, replay, sizeof(replay));
317             printf("nread = %d, %s\n", nread, replay);
318         default:
319             break;
320     }
321     return 0;
322 }
323 
324 //等待电话来的函数
325 int waitphone(void)
326 {
327     int i = 4;
328     int fd;
329     int choice;
330     int nwrite;
331     int nread;
332     char replay[len_number];
333     char str[] = "\n\nRING";
334     char buff[len_number];
335 
336     fd = open("/dev/ttyS1",O_RDWR|O_NOCTTY|O_NDELAY);
337     if(fd < 0)
338     {
339         perror("Can not open ttyS1!\n");
340     }
341 
342     serial_init(fd);
343     memset(buff, 0, len_number);
344     strcpy(buff, "at\r");
345     nwrite = write(fd, buff, strlen(buff));
346     printf("nwrite = %d, %s\n", nwrite, buff);
347 
348     while(i)
349     {
350         memset(replay, 0, len_number);
351         sleep(1);
352         nread = read(fd, replay, sizeof(replay));
353         printf("nread = %d, %s\n", nread, replay);
354 
355         memset(replay, 0, len_number);
356         sleep(2);
357         nread = read(fd, replay, sizeof(replay));
358         if(!(strncmp(replay, str, 6)))
359         {
360             printf("there is a ring.\n");
361             printf("1.to receive.\n");
362             printf("2.to refuse.\n");
363 
364             choice = getchar();
365             switch(choice)
366             {
367                 case'1':
368                     receive(fd);
369                     break;
370                 case'2':
371                     refuse(fd);
372                     break;
373                 default:
374                     break;
375             }
376         }
377         i--;
378     }
379     close(fd);
380     return 0;
381 }
382 
383 //设置为来短信提示状态
384 int message(void)
385 {
386     int fd;
387     int nwrite;
388     char buff[len_number];
389     char replay[len_message];
390 
391     fd = open("/dev/ttyS1",O_RDWR|O_NOCTTY|O_NDELAY);
392     if(fd < 0)
393     {
394         perror("Can not open ttyS1!\n");
395     }
396     serial_init(fd);
397     memset(buff, 0, len_number);
398     strcpy(buff, "AT+CNMI=3,2\r");
399     nwrite = write(fd, buff, strlen(buff));
400     sleep(1);
401     memset(replay, 0, len_message);
402     read(fd, replay, sizeof(replay));
403     close(fd);
404 }
405 
406 int main(void)
407 {
408     printf("Please enter your choice:\n");
409     printf("1:for english message.\n");
410     printf("2:for chinese message.\n");
411     printf("3:for a call.\n");
412     printf("enter nothing for a waiting.\n");
413     message();
414     while(1)
415     {
416 //如果键盘没有输入,则一直处在等待接电话的状态中
417 //一旦键盘有输入则读取键盘输入并判断是打电话还是发短信
418         while(!kbhit())
419         {
420             waitphone();
421             sleep(1);
422         }
423         char choice = getchar();        //一旦键盘有输入则接收键盘输入并根据输入选择进入某个函数。
424         switch(choice)
425         {
426             case'1':
427                 send_en_message();
428                 break;
429             case'2':
430                 send_ch_message();
431                 break;
432             case'3':
433                 call_phone();
434                 break;
435             default:
436                 break;
437         }
438     }
439     return 0;
440 }

推荐阅读