Nucleo开发板方案设计——GSM/GPRS
本帖最后由 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)判断接线有没问题,其实用一个很简单的方法即可。就是电脑 串口 <===> NucleoF072RB<===> SIM900A串口,Nucleo 在中间只做一个转发的功能即。在mbed这方面却,做得很方面啦,就是关键的几句即可。
Serial serial(SERIAL_TX, SERIAL_RX);//<span style="color: rgb(0, 0, 0); font-family: 微软雅黑; background-color: rgb(255, 255, 255);">串口 <===> NucleoF072RB</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);">NucleoF072RB</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;
int messageIndex = 0;
char phone;
char datetime;
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;
int messageIndex = 0;
char phone;
char datetime;
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;
int messageIndex = 0;
char phone;
char datetime;
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接口的很少。 功耗有多大 ? 一直也想弄这个GPRS远程,学习下,感谢分享! 感谢分享!顶一个 这模块在连网时的电流确实大。
在供电管脚旁边,得放上个大容量的钽电容,至少是 100uF,还好电压低,选择耐压为 6.3V 这一档的钽电容就可以。 谢谢分享 学习,谢谢分享
学习,谢谢分享 多谢分享!:)