1、简介

SIM900B是一款新型无线模块,属于B2B类型的四频GSM/GPRS模块,采用非常强大的AMR926EJ-S单芯片处理器,可完全兼容于SIM300/340 。其性能稳定,外观小巧,性价比高,能满足您的多种需求。SIM900B采用工业标准接口,工作频率为GSM/GPRS 850/900/1800/1900MHz,可以低功耗实现语音、SMS、数据和传真信息的传输。

2、AT指令集

要与GPRS进行通信,首先要了解AT指令,AT指令集是从终端设备(Terminal Equipment,TE)或数据终端设备(Data Terminal Equipment,DTE)向终端适配器(Terminal Adapter, TA)或数据电路终端设备(Data Circuit Terminal Equipment,DCE)发送的。通过TA,TE发送AT指令来控制移动台(Mobile Station,MS)的功能,与GSM 网络业务进行交互。用户可以通过AT指令进行呼叫、短信、电话本、数据业务、传真等方面的控制。

2.1 、常用AT指令

这里我就列出我在编程当中所用到的一些AT命令,更多的命令详见http://wenku.baidu.com/view/f8168c50f01dc281e53af0d4.html
1、检测SIM卡是否注册上
AT+CPIN?返回值:READY
2、检测SIM卡的信号强度
AT+CSQ返回值:+CSQ 29,99
3、查询模块版本
AT+CGMR返回值:R4A021      CXC1122528 (版本信息)
4、拨打电话
ATD+号码+;
5、发英文短信
AT+CMGF=1/0(PS:1是文本模式;0是PDU模式)
AT+CMGS="号码"
>短信内容(只能是英文或者数字,要发中文,要进行PDU编码,比较麻烦,想学的可以直接百度)
Ctrl+Z(发送)

3、串口

因为我们的开发板是通过串口向GPRS模块发送命令的,所以这里我们先来了解一下串口。在Linux中,它给我们提供了一个termios结构体,这使得我们更方便的在程序中对串口进行初始化。

(更详细的信息请参考:http://baike.sogou.com/v53994134.htm?fromTitle=Termios)

让我们先来看一下termios结构体内部信息:

struct termios {

unsigned short c_iflag;              /* 输入模式标志*/
    unsigned short c_oflag;             /* 输出模式标志*/
    unsigned short c_cflag;             /* 控制模式标志*/
    unsigned short c_lflag;              /*区域模式标志或本地模式标志或局部模式*/
    unsigned char c_line;                /*行控制line discipline */
    unsigned char c_cc[NCC];      /* 控制字符特性*/

};

常用校验位和停止位的设置:

无校验位 8位 Option.c_cflag &= ~PARENB; 
Option.c_cflag &= ~CSTOPB; 
Option.c_cflag &= ~CSIZE; 
Option.c_cflag |= ~CS8;

奇校验位 7位 Option.c_cflag |= ~PARENB; 
Option.c_cflag &= ~PARODD; 
Option.c_cflag &= ~CSTOPB; 
Option.c_cflag &= ~CSIZE; 
Option.c_cflag |= ~CS7;

偶校验位 7位 Option.c_cflag &= ~PARENB; 
Option.c_cflag |= ~PARODD; 
Option.c_cflag &= ~CSTOPB; 
Option.c_cflag &= ~CSIZE; 
Option.c_cflag |= ~CS7;

Space校验 7位 Option.c_cflag &= ~PARENB; 
Option.c_cflag &= ~CSTOPB; 
Option.c_cflag &= &~CSIZE; 
Option.c_cflag |= CS8;

Linux下串口的操作一般分为四个步骤:

1、打开需要使用的设备

在 Linux 下串口文件是位于 /dev 下的

串口一 为 /dev/ttyS0(/dev/ttyUSB0)

串口二 为 /dev/ttyS1(/dev/ttyUSB1)

fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);

2、获取设备的属性

struct termios options;        
tcgetattr(fd, &options);  

3、设置串口

options.c_cflag |= ( CLOCAL | CREAD ); 
options.c_cflag &= ~CSIZE;      
options.c_cflag &= ~CRTSCTS;   
options.c_cflag |= CS8;      
options.c_cflag &= ~CSTOPB; 
options.c_iflag |= IGNPAR;  
options.c_oflag = 0;            
options.c_lflag = 0;         
cfsetispeed(&options, B115200);//设置发送波特率
cfsetospeed(&options, B115200);   //设置接收波特率

4、将所设置的参数生效

tcsetattr(fd,TCSANOW,&options);

TCSANOW:   不等数据传输完毕就立即改变属性
TCSADRAIN: 等待所有数据传输结束才改变属性
TCSAFLUSH:   清空输入输出缓冲区才改变属性

4、线程

1、简介

线程是程序中一个单一的顺序控制流程。在单个程序中同时运行多个线程完成不同的工作,称为多线程。线程也有就绪、阻塞和运行三种基本状态。每一个程序都至少有一个线程,那就是程序本身。线程能独立执行,能充分利用和发挥处理机与外围设备并行工作的能力。

2、实例代码

这是一个简单的创建线程的示例代码,能让我们更快的了解如何创建一个线程,这个例子中运用到了互斥锁,互斥锁的作用是用来保证程序在一个时间内只有一个线程运行,这样保证了线程执行的先后顺序,只有当一个线程释放锁之后,另一个上锁的线程才能运行,接下来就是代码:

#include <pthread.h>  
#include <stdio.h>  
 
pthread_mutex_t mutex ;

void *print_msg1(void *agrs ){  
        pthread_mutex_lock(&mutex);
char led;
led=*(char*)agrs;  
if(led=='1')
{
        printf("this is print_msg1,led=%c\n",led);  
}
        usleep(100);  
        pthread_mutex_unlock(&mutex);  
}  
void *print_msg2(void *arg){  
pthread_mutex_lock(&mutex);  
printf("this is print_msg2\n");  
usleep(100);  
pthread_mutex_unlock(&mutex);  
}  
int main(int argc,char** argv){  
        pthread_t id1;  
        pthread_t id2;

pthread_mutex_init(&mutex,NULL);  
        pthread_create(&id2,NULL,(void *)print_msg2,NULL);  
        pthread_create(&id1,NULL,(void *)print_msg1,NULL);  
sleep(1);
        pthread_join(id1,NULL);  
        pthread_join(id2,NULL);  
        pthread_mutex_destroy(&mutex);  
        return 1;
}

5、SIM900B GPRS模块 打电话、发短信、接电话

假如说,你能了解上面我所介绍的内容,那么看懂这个代码并不是上面难事,而且,还能再我代码的基础上进行改善
/*引进编译所需要的头文件
#include <termios.h>       
#include <pthread.h>
#include <stdio.h>         
#include <stdlib.h>         
#include <unistd.h>        
#include <fcntl.h>        
#include <string.h>        
#include <sys/types.h>      
#include <sys/stat.h> 

pthread_mutex_t mutex ;  //定义一个互斥锁
int choice=0; //定义全局变量

//存储短信信息的结构体
struct message_info
{                         
char phnum[16];          
char message[128];    
};

//用来接电话的线程
void* thread_get_RING(void* arg)
{
char  reply[100];
int fd;

        fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);    
    if (-1 == fd)
        {
                perror("Can't Open Serial Port");
        }
//一直检测串口是否有RING 这个字符串  PS:如果向GPRS模块打电话,串口回返回RING 字符串
while(1)
{
memset(reply,0,sizeof(reply));
                read(fd,reply,sizeof(reply));//读取串口信息
                if(strstr(reply,"RING"))
                {
                        printf("=====================================================\n");
                        printf("      you have a call in,please input :\n");
                        printf("           4 to connect\n");
                        printf("           5 to hang up\n");
                        printf("=====================================================\n");

pthread_mutex_lock(&mutex);//上锁
                        switch(choice)
                        {
                                case 4: get_up_phone(fd) ;break;
                                case 5: hang_up_phone(fd) ; break;
                }
pthread_mutex_unlock(&mutex);//解锁
}
}
}

//初始化串口函数
void serial_init(int fd)      
{              
struct termios options;        
tcgetattr(fd, &options);   
options.c_cflag |= ( CLOCAL | CREAD ); 
options.c_cflag &= ~CSIZE;      
options.c_cflag &= ~CRTSCTS;   
options.c_cflag |= CS8;      
options.c_cflag &= ~CSTOPB; 
options.c_iflag |= IGNPAR;  
options.c_oflag = 0;            
options.c_lflag = 0;         
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);       
tcsetattr(fd,TCSANOW,&options);
}

//挂断电话的函数
int hang_up_phone(int fd)
{
        getchar(); //PS:吃掉缓冲区中的回车符
        char buff[10];
        char reply[20];
        int nwrite;
        int nread;

memset(buff,0,sizeof(buff));
        memset(reply,0,sizeof(reply));

strcat(buff,"ath\r");
        nwrite=write(fd,buff,sizeof(buff)); //向串口发送AT命令
        printf("nwrite=%d,%s,\n",nwrite,buff);
        sleep(1);
        nread=read(fd,reply,sizeof(reply)); //读取返回值
        printf("nread=%d,%s\n",nread,reply); //打印返回值的信息
}

//接电话的函数
int get_up_phone(int fd)
{
getchar();
        char buff[10];
        char reply[20];
        int nwrite;
        int nread;

memset(buff,0,sizeof(buff));
        memset(reply,0,sizeof(reply));

strcat(buff,"ata\r");
        nwrite=write(fd,buff,sizeof(buff));
        printf("nwrite=%d,%s,\n",nwrite,buff);
        sleep(1);
        nread=read(fd,reply,sizeof(reply));
        printf("nread=%d,%s\n",nread,reply);
}

//获取用户所拨打的手机号函数
int get_phonenumber(int fd,char *phnum)
{
        getchar();
        int counter=0;
        char phonenum[20]={'\0'};
        printf("please enter the phone number who do you want to call:\n");
        gets(phnum);
        while(strlen(phnum) != 12)
        {
                if(counter >= 3)                                                  
                {
                        printf("conter out !\n");
                        return -1;
                }
                printf("number shuld be --11-- bits ! enter agin :\n");
               gets(phnum);
                counter ++;
        }
        strcat(phonenum,"atd");
        strcat(phonenum,phnum);
        strcat(phonenum,";\r");
        called(fd,phonenum);
}

//拨打电话的函数
int called(int fd,char *atd)
{
        int nread,nwrite;
        char buff[100];
        char reply[100];
        char hang_up;

memset(buff,0,sizeof(buff));
        memset(reply,0,sizeof(reply));
        strcpy(buff,"at\r");
        nwrite=write(fd,buff,strlen(buff));
        printf("nwrite=%d,%s\n",nwrite,buff);
        sleep(1);
        nread=read(fd,reply,strlen(reply));
        printf("reply=%d,%s\n",nread,reply);
        memset(buff,0,sizeof(buff));
        memset(reply,0,sizeof(reply));
        strcat(buff,atd);
        nwrite=write(fd,buff,sizeof(buff));
        printf("nwrite=%d,%s\n",nwrite,buff);
        sleep(1);
        nread=read(fd,reply,sizeof(reply));
        printf("nread=%d,%s\n",nread,reply);

printf("==================================\n");
        printf("if you want to hang up this dialog,\n please enter 2\n");
        printf("==================================\n");

hang_up=getchar();
        if(hang_up=='2')
        {
                hang_up_phone(fd);
        }
}

//发送信息的函数
int send(int fd,char *cmgf,char *cmgs,char *message)    
{               
int nread,nwrite;            
char buff[128];            
char reply[128];      
memset(buff,0,sizeof(buff));
strcpy(buff,"at\r");
nwrite = write(fd,buff,strlen(buff));
printf("nwrite=%d,%s\n",nwrite,buff); 
memset(reply,0,sizeof(reply));         
sleep(1);              
nread = read(fd,reply,sizeof(reply));  
printf("nread=%d,%s\n",nread,reply);     
memset(buff,0,sizeof(buff));          
strcpy(buff,"AT+CMGF=");          
strcat(buff,cmgf);          
strcat(buff,"\r");           
nwrite = write(fd,buff,strlen(buff));  
printf("nwrite=%d,%s\n",nwrite,buff);
memset(reply,0,sizeof(reply));        
sleep(1);           
nread = read(fd,reply,sizeof(reply));         
printf("nread=%d,%s\n",nread,reply);    
memset(buff,0,sizeof(buff));             
strcpy(buff,"AT+CMGS=");             
strcat(buff,cmgs);               
strcat(buff,"\r");         
nwrite = write(fd,buff,strlen(buff));    
printf("nwrite=%d,%s\n",nwrite,buff);    
memset(reply,0,sizeof(reply));       
sleep(1);             
nread = read(fd,reply,sizeof(reply));  
printf("nread=%d,%s\n",nread,reply);     
memset(buff,0,sizeof(buff));       
strcpy(buff,message);         
nwrite = write(fd,buff,strlen(buff));   
printf("nwrite=%d,%s\n",nwrite,buff);    
memset(reply,0,sizeof(reply));         
sleep(1);              
nread = read(fd,reply,sizeof(reply));     
printf("nread=%d,%s\n",nread,reply);   
}

//获取用户所输入的短信收件人
int send_en_message(int fd,struct message_info info)    
{            
getchar(); 
char cmgf[] = "1";      
int conter = 0;         
char cmgs[16] = {'\0'};      
printf("enter recever phnumber :\n");       
fgets(info.phnum,15,stdin);           
while(strlen(info.phnum) != 12)
{                    
if(conter >= 3)
{                  
printf("conter out !\n");         
return -1;                 
}                     
printf("number shuld be --11-- bits ! enter agin :\n");      
fgets(info.phnum,11,stdin);      
conter ++;           
}       
printf("enter you message !\n");       
fgets(info.message,128,stdin);              
strcat(info.message,"\x1a");  
strcat(cmgs,"\"");
strcat(cmgs,info.phnum);
strcat(cmgs,"\"");   
send(fd,cmgf,cmgs,info.message);   
}

int main()       
{             
int ret;
int fd;      
char phnum[15];
struct message_info info;     
pthread_t id;

pthread_mutex_init(&mutex,NULL);  //初始化互斥锁

fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);    //打开串口设备    
if (-1 == fd)
{                
perror("Can't Open Serial Port");          
}            
serial_init(fd); //初始化串口

ret=pthread_create(&id,NULL,(void *)thread_get_RING,NULL);//创建线程
usleep(100);
        if(ret!=0)
        {
                printf("create thread failed!!\n");
                exit (1);
        }

printf("\n============================================\n");       
printf("\tthis is a gprs test program !\n");              
printf("\tcopyright fj@farsight 2016\n");            
printf("============================================\n");      
printf("enter your selete :\n");        
printf("1.send english message.\n");                   
printf("2.call to someone. \n");
        printf("3.exit.\n");
while(1)
        {
                pthread_mutex_lock(&mutex); //上锁
scanf("%d",&choice);

switch(choice)
                {
                        case 1: send_en_message(fd,info);         break;
                        case 2: get_phonenumber(fd,phnum);        break;
                        case 3: printf("Quite!!\n");              break;
                        default : printf("Quite!!\n");            break;
                }

pthread_mutex_unlock(&mutex);//解锁
sleep(1);

printf("\n============================================\n");
                printf("\tthis is a gprs test program !\n");
                printf("\tcopyright for huangan 2016\n");
                printf("============================================\n");
                printf("enter your selete :\n");
                printf("1.send english message.\n");
                printf("2.call to someone. \n");
                printf("3.exit.\n");
        }
pthread_join(id,NULL); //等待线程的结束
pthread_mutex_destroy(&mutex);  //毁掉互斥锁
close(fd);              //关闭设备
return 0; 
}

6、总结

这个模块我玩了十天,在这个过程中我学到了很多东西,但是遇到的问题也是很多的,比如刚开始都不知道线程的工作原理,也不知道如何创建线程,这是最难的,但是经过各种百度,请教同学,终于是把这个模块完成,后面还有PPP拨号上网,这个将在后面介绍

SIM900B GPRS模块————打电话、发短信、接电话相关推荐

  1. linux 下GPRS模块使用sim900打电话发短信

    ---------------------------------------------  主机操作系统:Centos 6.7 开发板平台: FL2440  Linux内核版本: linux-3.0 ...

  2. sim900GPRS使用C语言打电话发短信

    --------------------------------------------- 主机操作系统:Centos 6.5 交叉编译器环境:arm-linux-gcc-4.5.4 开发板平台: F ...

  3. SIM71004G模块使用Linux C语言实现打电话发短信

    为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长. 一.实验目的: SIM71004G模块使用Linux C语言实现打电话发短信. 二 ...

  4. android 发送短信 广播 demo,向Android模拟器打电话发短信的简单方法

    在开发android应用程序时,有时候需要测试一下向android手机拨打电话发送短信时该应用程序的反应.譬如编写一个广播接收器,来提示用户有短信收到或者处理短信,就需要向该手机发送短信来进行测试.这 ...

  5. android虚拟机接收真实短信,向Android模拟器打电话发短信的简单方法

    在开发android应用程序时,有时候需要测试一下向android手机拨打电话发送短信时该应用程序的反应.譬如编写一个广播接收器,来提示用户有短信收到或者处理短信,就需要向该手机发送短信来进行测试.这 ...

  6. Qt下面利用4G 模块SIM7600发短信调试总结

    项目需要在基于Qt的界面下发送短信,选用4G模块SIM7600通过AT指令发送短信,和小伙伴调了一天多,终于可以了,下面简单总结一下调试过程中遇到的问题和学习到的经验,供大家参考,少走弯路. 1.在网 ...

  7. 向Android模拟器打电话发短信的简单方法

    在开发android应用程序时,有时候需要测试一下向android手机拨打电话发送短信时该应用程序的反应.譬如编写一个广播接收器,来提示用户有短信收到或者处理短信,就需要向该手机发送短信来进行测试.这 ...

  8. 手把手教你如何在安卓平台上实现打电话发短信的功能

    首发地址 http://www.eoeandroid.com/thread-228079-1-1.html 1 案例目的 本案例通过一个简单通讯工具来巩固android的activity.Linear ...

  9. android 拨打多个电话号码,和多号如何使用副号打电话/发短信

    和多号副号不能开机?和多号副号不能发短信打电话?那估计是你的设置有问题吧,想要知道和多号如何使用副号打电话/发短信么?那就往下看和多号副号使用方法教程吧!相信通过小编的点拨大家都能轻松使用和多号副号哦 ...

最新文章

  1. MySQL源码包安装
  2. python做股票系统_GitHub - hetingqin/stock: stock,股票系统。使用python进行开发。
  3. python中round函数参数_python中关于round函数的小坑
  4. function click_click事件的累加问题解决
  5. win7安装nodejs 高版本不支持 换低版本
  6. iPhone 14系列升级巨大:两款Pro版或将配置4800万像素镜头
  7. android Viewpager HorizontalScrollView 实现分页栏拖拽
  8. Kaldi AMI数据集脚本学习3---run_ihm.sh stage 1~3
  9. aix 查看防火墙状态_AIX系统自带防火墙
  10. ansys_apdl使用教程
  11. 基于 TI 方案 CC2540 低功耗无线蓝牙模块详解
  12. 安装FlexPro和设置FlexPro许可证管理器
  13. 基带信号传输之码间串扰
  14. 屏蔽电脑上所有的广告推送(亲测可用)
  15. VS Code 多光标快捷键
  16. 2021年3月PHP免费自学最全教程来了
  17. c语言雷克子波函数表达式,雷克子波频率研究
  18. 软考高级-信息系统管理师之质量管理(最新版)
  19. 【限时删除】一个惊艳的神器,可全网爬取各种资源..........
  20. 万由nas系统安装MySQL_【不折腾】VM虚拟机安装体验万由U-NAS系统

热门文章

  1. coldfusion_ColdFusion中的一周:5月21日至27日:迟到总比不到好
  2. 怒了!国产游戏开发三年,上线一天就被台湾黑客搞到停服!
  3. python小知识|if x、if not x、while True的用法,还在困扰着你吗?(补加:关于None的小知识)
  4. datax 模板_DataX引擎
  5. 起底▍Spring Boot/Cloud背后豪华的研发团队 ——独角兽公司Pivotal
  6. 兮米安装包制作工具绿色版
  7. 掌上英雄联盟APP利用Charles下载图片
  8. 异常检测中的评价指标——TPR/FPR/P/A/F/R
  9. VR安全教育:打破“说教式”教育模式,让安全常伴
  10. Swift5 字典转JSON