------------------------------------------------------------------------------------------------------------------------------
交叉編譯器: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 }