------------------------------------------------------------------------------------------------------------------------------
交叉编译器: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 <[email protected]> 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 }