本帖最后由 dvd1478 于 2015-2-2 14:10 编辑
GSM 的英文是 GlobalSys-temForMobileCommunica-tion,即全球移动通信系统,由欧洲标准化委员会设计提出。GSM 系统具有防盗拷贝能力佳、网络容量大、号码资源丰富、 通话清晰、稳定性强不易受干扰、信息灵敏、通话死角少、手机耗电量低等特点。我国自 1994 年底开始建设 GSM 蜂窝移动通信网,其发展势头世人皆叹。目前,中国移动通信拥有世界上网络 规模最大和客户数量最多的GSM移动通信网。
GPRS 是GeneralPacketRadioService 的英文简称,中文为通用无线分组业务。它具有实时在线、按 量计费、快捷登录、高速传输、自如切换的优点。使用 GPRS 上网的方法与 WAP 不同, 用WAP上网就如在家中上网,先“拨号连接”,上网后便不能同时使用该电话线,但用 GPRS 下载资料和通话可以同时进行,即通话继续使用 GSM,而数据的传送便可使用 GPRS。
我们可以简单地理解成为:GSM 是手机语音通话网络,就是打电话发短信的网络;而GPRS 是用手机上网收发数据的网络! 在紧急呼叫机与现下很流行的物联网通讯都有广泛的应用。紧急呼叫机是GSM功能的应用,而物联网是一般都是GPRS的应用。
这里主要是针对这两个功能进行学习与开发,另外一方向是学习mbed的开发的思想。mbed的开发思想是抛开硬件底层,从而面对类的开发。所用的就是C++/C的开发。
而有选用的是SIM900A模块,SIM900A 模块板载 SIMCOM 公司的工业级双频GSM/GPRS 模块:SIM900A,工作频段双频:900/1800Mhz,可以低功耗实现语音、SMS(短 信,不支持彩信)、数据和传真信息的传输。 SIM900A 模块支持 RS232 串口和 LVTTL 串口(即支持 3.3V/5V 系统),并带硬件流控制,支持5V~24V的超宽工作范围,使得本模块可以非常方便的与您的产品进行连接,从而给您的产品提供包括语音、短信和GPRS数据传输等功能。
(1)我是淘宝上选择SIM900A模块,选择时注意不要选太贵的,不值,就算把所有功能引出来,确实方面全方面的学习,但实际上大多数的产品,依我所了解,大都数都是GSM与GPRS的应用。不要选太便宜的,在这方面我就吃过亏了,在功率上并没有处理好或者是信号处理不好,给调试上带我了很大的麻烦。 SIM900A地收发时的瞬间功耗还是很大的,电源上做一些处理,如添加大电容等等。当然初期,调试时可以选择外置电源,这样给给调试带来方便。
(2)判断接线有没问题,其实用一个很简单的方法即可。就是电脑 串口 <===> Nucleo F072RB <===> SIM900A串口,Nucleo 在中间只做一个转发的功能即。在mbed这方面却,做得很方面啦,就是关键的几句即可。
- Serial serial(SERIAL_TX, SERIAL_RX); //<span style="color: rgb(0, 0, 0); font-family: 微软雅黑; background-color: rgb(255, 255, 255);">串口 <===> Nucleo F072RB</span>
- GPRSInterface eth(PA_0, PA_1, 115200, "apn", "username", "password");//<span style="color: rgb(0, 0, 0); font-family: 微软雅黑; background-color: rgb(255, 255, 255);">Nucleo F072RB</span><span style="color: rgb(0, 0, 0); font-family: 微软雅黑; background-color: rgb(255, 255, 255);"> </span><span style="color: rgb(0, 0, 0); font-family: 微软雅黑; line-height: 1.5; background-color: rgb(255, 255, 255);"><span style="background-color: inherit;"> </span><===><span style="background-color: inherit;"> SIM900A串口</span></span>
- int main()
- {
- wait(3);
- bool flag = eth.init();
-
- while(1){
- <font color="#ff0000"> while(eth.serialModem.readable()){
- serial.putc(eth.serialModem.getc());</font>
- }
- <font color="#ff0000"> while(serial.readable()){
- eth.serialModem.putc(serial.getc());</font>
- }
- }
- }
复制代码 (3) 就是SIM900A是自动识串口的波特率的,2400~115200 ,但较高波特率时,要多发几次 AT 命令,并且要有一定的延时。
- bool GPRS::preInit()
- {
- for(int i = 0; i < 2; i++) {
- sendCmd("AT\r\n");
- wait(1);
- }
-
- if(0 != sendCmdAndWaitForResp("AT\r\n","OK",DEFAULT_TIMEOUT,CMD)){
- return false;
-
- }
- if(0 != checkSIMStatus()) {
- return false;
- }
-
- return true;
- }
复制代码
还有很多的心理,不一一写上来的。写代码的,在这方面我还是菜鸟,这里只是显显羞罢了,有什么不足请大家狠狠拍砖。
以下说一下我学习mbed后的思想
Serial 是SIM900A的接口,继承了Serial类,是其子类。代码上只要以下书写即可
- <font color="#000000">class Modem</font>
- <font color="#000000">{</font>
- <font color="#000000">public:</font>
- <font color="#000000"> /** Create Modem Instance</font>
- <font color="#000000"> * @param tx uart transmit pin to communicate with Modem</font>
- <font color="#000000"> * @param rx uart receive pin to communicate with Modem</font>
- <font color="#000000"> * @param baudRate baud rate of uart communication</font>
- <font color="#000000"> */</font>
- <font color="#ff0000"> Modem(PinName tx, PinName rx, int baudRate) : serialModem(tx, rx) </font><font color="#000000">{</font>
- <font color="#000000"> serialModem.baud(baudRate);</font>
- <font color="#000000"> };</font>
-
- <font color="#ff0000"> Serial serialModem;</font>
- <font color="#000000">protected:</font>
-
- 。。。。。。。。。。。
- <font color="#000000">private:</font>
- <font color="#000000">};</font>
复制代码 把低层的接口封装至modem 类中,而上层的GSM 、GPRS继承了modem类。以下书写即可 ,即能
- <font color="#ff0000">class GPRS: public Modem</font>
- {
- 。。。。。。。。。。。
- }
复制代码
GSM 功能已经调试好,而GPRS 还在调试中,好像参赛方案提交的时间快到,我针对GSM功能,做一个简单的紧急呼叫机,设计的思法是这样,任何的操作都有一个按键,拨打接听都是一个按键,保持着 “keep it simple stupid”的思法。
程序流程图
写得很匆忙,C++也是现学现用的,说错的地方,请大学指点指点。方案做得不怎么好,请大学原谅!~
贴了我调试时的代码片段
一、呼叫测试代码
- #if 1
- /*call up*/
- bool flag = eth.init();
- CallAnswer callFlag = CallWait;
- if (flag != NULL) {
- printf(">>> Could not initialise. Halting!\n");
- exit(0);
- }
-
- printf("Call the number \r\n");
- eth.callUp("1008611");
-
- while(1){
- callFlag =eth.callWaitAsk();
- switch(callFlag){
- case CallOk:
- printf("\r\n Is Calling \r\n");
- //printf("\r\n正在呼叫\r\n");
- break;
- case CallBusy:
- printf("\r\n You dial telephone is on the phone, please later again dial \r\n");
- //printf("\r\n你拨打的电话正在通话中,请稍后再拨\r\n");
- break;
- case CallNoAnswer:
- printf("\r\nYou dial telephone temporarily no man answer, please later again dial \r\n");
- //printf("\r\n你拨打的电话暂时无人接听,请稍后再拨\r\n");
- break;
- case CallNoCarrier:
- printf("\r\nEnd of the conversation\r\n");
- //printf("\r\n通话结束\r\n");
- break;
- default:
- printf("\r\n In the middle of, please wait \r\n");
- //printf("\r\n正中进行,请等待\r\n");
- break;
- } // end switch(callFlag)
- wait(1);
- }
- #endif
复制代码 二、发短信测试代码
(这里发了很长时间,原本是自动判断中英文发送的,但是UNICODE GBK双向转换码 即占用很大部分的ROM空间,后面没有使用mbed开法,却没有超出。我想应该是c++占用了很大的ROM空间,最后还是选择舍去了中文的短信的发送,因为这里主要是学习mbed开发的思想)
- #if 1
- #define PHONE_NUMBER "186****2964"
- #define MESSAGE "hello,world"
- /* send message*/
- bool flag = eth.init();
- if (flag != NULL) {
- printf(">>> Could not initialise. Halting!\n");
- exit(0);
- }
-
- printf("start to send message.... \r\n");
-
- eth.sendSMS(PHONE_NUMBER,MESSAGE);
-
- exit(0);
- #endif
复制代码 读短信
- #if 1
- /* read message */
- #define MESSAGE_LENGTH 160
- char message[MESSAGE_LENGTH];
- int messageIndex = 0;
- char phone[16];
- char datetime[24];
- while(1){
- messageIndex = eth.isSMSunread();
- if (messageIndex > 0) { //At least, there is one UNREAD SMS
- eth.readSMS(messageIndex, message, MESSAGE_LENGTH, phone, datetime);
- //In order not to full SIM Memory, is better to delete it
- eth.deleteSMS(messageIndex);
- serial.printf("From number: %s \r\n",phone);
- serial.printf("Datetime: %s \r\n",datetime);
- serial.printf("Recieved Message:" %s "\r\n",message);
- }
- }
- #endif
复制代码
四、自动接电话与读短信
- #if 1
- /*Loop Handle */
- bool flag = eth.init();
- CallAnswer callFlag = CallWait;
- if (flag != NULL) {
- printf(">>> Could not initialise. Halting!\n");
- exit(0);
- }
-
- printf("Call the number \r\n");
-
- while(1){
- callFlag = eth.callWaitAsk();
- switch(callFlag){
- case CallRing:
- eth.answer();
- break;
- case CallSM:
- #define MESSAGE_LENGTH 160
- char message[MESSAGE_LENGTH];
- int messageIndex = 0;
- char phone[16];
- char datetime[24];
- messageIndex = eth.isSMSunread();
- if (messageIndex > 0) { //At least, there is one UNREAD SMS
- eth.readSMS(messageIndex, message, MESSAGE_LENGTH, phone, datetime);
- //In order not to full SIM Memory, is better to delete it
- eth.deleteSMS(messageIndex);
- serial.printf("From number: %s \r\n",phone);
- serial.printf("Datetime: %s \r\n",datetime);
- serial.printf("Recieved Message:" %s "\r\n",message);
- }
- break;
- default:
- break;
- } // end switch(callFlag)
- wait(1);
- }
- #endif
复制代码
五、紧急呼叫机
- #if 1
- const char num[]="551";
- bool flag = eth.init();
- CallAnswer callFlag = CallWait;
- if (flag != NULL) {
- printf(">>> Could not initialise. Halting!\n");
- exit(0);
- }
- flag = false;
- while(1){
- callFlag = eth.callWaitAsk();
- switch(callFlag){
- case CallRing:
- if( mybutton )
- {
- eth.answer();
- flag = true;
- while(flag == true)
- {
- wait(1);
- callFlag = eth.callWaitAsk();
- if(CallNoCarrier==callFlag)
- flag = false;
- }//end while(flag == true)
- }//end if( mybutton )
- break;
- case CallSM:
- #define MESSAGE_LENGTH 160
- char message[MESSAGE_LENGTH];
- int messageIndex = 0;
- char phone[16];
- char datetime[24];
- messageIndex = eth.isSMSunread();
- if (messageIndex > 0) { //At least, there is one UNREAD SMS
- eth.readSMS(messageIndex, message, MESSAGE_LENGTH, phone, datetime);
- //In order not to full SIM Memory, is better to delete it
- eth.deleteSMS(messageIndex);
- serial.printf("From number: %s \r\n",phone);
- serial.printf("Datetime: %s \r\n",datetime);
- serial.printf("Recieved Message:" %s "\r\n",message);
- }
- break;
- default:
- break;
- } // end switch(callFlag)
-
-
- wait(1);
- if( mybutton ){
- eth.callUp((char *)num);
- while(flag == true){
- wait(1);
- switch(callFlag){
-
- case CallOk:
- //printf("\r\n正在呼叫\r\n");
- if( mybutton )
- {
- eth.callDown();
- }//end if( mybutton )
- break;
- case CallBusy:
- //printf("\r\n你拨打的电话正在通话中,请稍后再拨\r\n");
- case CallNoAnswer:
- //printf("\r\n你拨打的电话暂时无人接听,请稍后再拨\r\n");
- wait(10);
- eth.sendSMS((char *)num,"Hello world!\r\n How are you ?\r\n");
- break;
- case CallNoCarrier:
- //printf("\r\n通话结束\r\n");
- default:
- wait(1);
- //printf("\r\n正中进行,请等待\r\n");
- break;
- } // end switch(callFlag)
- }// end while(flag == true)
- }//end if( mybutton )
- }//end while(1)
-
-
-
- #endif
复制代码
SIM900A的库代码:
GPRS的功能还没有调试好,不好意思上传,迟些我搞个GIT 托管代码 才可以。
下一步计划就是做GPRS功能,实现TCP/IP,做一个远程读取现场温度。
==============================================================
以下为我收集的资料一起分享给大家。
上传了官方文档,链接 点击直达调试常用到的软件 传输门
|
Arduino 接口?你用度绑线链接是没有区别的,Nucleo中的Arduino的接口,是为了与Arduino硬件模块接口相对应的。例如拿个Arduino的wifi模块,直接插入Nucleo的Arduino的接口即可以使的。为的就是硬件的兼容性,不必要重新设计。
5.éç«ä¸²å£GSMè°è¯å©æ.
GSM串å£è°è¯å©æ
ç½ç»è°è¯å©æ
PDUçä¿¡ç¼ç å·¥å ·
SIM300串å£å·¥å ·
ç±è¿ªçç信群å
串å£è°è¯å©æ
çµèä¸ææ¶å软件
çä¿¡æµè¯è½¯ä»¶
æ±åUnicodeäºæ¢å°å·¥å ·
SIM900A REACH Test Report Certificate
SIM900A ROHS Certificate Certificate
SIM900A ROHS Test Report Certificate
SIM900A Type Approval Certificate
SIM900A_3C_Certificate Certificate
SIM900A_3Cè¯éªæ¥å Certificate
SIM900A_Specification_V1102 Specification
SIM900A_Supported_MCC_list_V1.00 Application Note
SIM900A_çµç£å ¼å®¹åå¼è¯éªæ¥å Certificate
在供电管脚旁边,得放上个大容量的钽电容,至少是 100uF,还好电压低,选择耐压为 6.3V 这一档的钽电容就可以。
学习,谢谢分享
是啊,我也是这样修改过,稳定一些,你是用什么模块,的好的GSM/GPRS模块介绍一下哟