开源第四周
这几天做的主要就是sim900模块了,这个模块其实是个很有意思的模块,加上控制器和显示器基本算是一个小手机了,可以语音通话,发送短信,最主要的是还可以GPRS上网,所以很适合拿来做数据传输节点。我们用的模块是已经封装好了的模块,模块内部集成了各种指令,只需要用户调用各种指令就可以自动实现各种功能了。这个模块需要配合一张2G的sim卡来配合打电话发短信以及上网功能的实现。
模块指令的格式基本为AT+" ",发送完指令后模块会向返回一个反馈信息,例如拨打电话指令发送成功后会返回“OK”,如果不成功则返回“ERROR”。向模块发送AT指令在我理解有三种方式,第一种是电脑加连接线硬串口连接输入AT指令;第二种使用软串口通过电脑端向模块发送指令;第三种通过程序写入控制器,控制器程序向模块发送指令。
模块的功能大概分为三种:打电话、发信息、GPRS上网。打电话的功能非常简单,只需要一个简单的<ATD"电话号码";>就可以实现功能了,而发信息和打电话则要复杂得多了。
短信步骤:
1、需要设置发送模式,选择文本格式还是PUD模式;
2、设置文本发送模式的参数;
3、设置为 UCS2 编码字符集;
4、将所需发送的内容和电话号码转换为UNICODE 编码;
5、发送: AT+CMGS=“电话号码UNICODE 编码”,等待返回‘>’字符;
6、等到返回'>'字符后,输入内容的UNICODE 编码,再发送一个十六进制的OX1A发送信息。
上网的设置更加复杂,进行 GPRS 通信,实现模块与电脑的
TCP 和 UDP 数据传输。这里将要用到的指令有: 10 余条 AT 指令。需要选择联网模式、设置协议、设置端口、设置IP、等待返回‘>’字符输入内容、设置数据中心等等。
这里有些常用的AT指令:
测试信号质量,用串口发送下面的指令:
AT+CSQ
此时会收到形如下面这样的回复消息:
+CSQ: 11,0
OK
拨打电话(这条指令后的分号不可少),可以把下面指令里的10086,替换成其他号码。
ATD10086;(回车)
挂断电话
ATH
接听电话
ATA
发送短信
首先设置成文本模式:
AT+CMGF=1
设置使用模块默认的国际标准字母字符集发送短信
AT+CSCS?
发送目标号码
AT+CMGS=”10086″(回车)
此时系统会出现“>”提示符,直接输入短信内容
> YE
这条短信的目的是发送给10086,用来查询余额。
0x1A (16进制发送)
发送成功以后会收到系统如下提示,后面的数字表示发送短信的编号。
+CMGS: 115
OK
接收短信
如果接收到了短信,则系统会在串口输出如下的提示,后面的数字表示短信收件箱里的短信数目:
+CMTI: “SM”,2
发送如下AT指令,后面的数字是短信索引号。由于使用的是IRA编码,中文短信不能显示,可以发英文短信用来测试。
AT+CMGR=2
还有一些代码:
int val; //定义变量val
#define MAXCHAR 81 //recive buff max char
char aa[MAXCHAR]; //recive gsm model back signal
int j=0; //recive index
int g_timeout=0; //handing time
char ATE0[]="ATE0";
char CREG_CMD[]="AT+CREG?";
char SMS_send[]="AT+CMGS=18";
char ATCN[]="AT+CNMI=2,1";
char CMGF0[]="AT+CMGF=0";
char CMGF1[]="AT+CMGF=1";
char CMGR[12]="AT+CMGR=1";
char CMGD[12]="AT+CMGD=1";
/*************************************************/
#define SEND_MESSA_TO_YOUR "at+cmgs=\"18382117086\"\r\n" //发短信接收的手机号码
#define SEND_MESSA_CONTENT "http://shop69712475.taobao.com \n openjumper " //短信内容
#define CALL_YOU_TELNUMBER "ATD18382117086;\r\n" //打电话接受的手机号码
/*************************************************/
int readSerial(char result[])
{
int i = 0;
while (Serial.available() > 0)
{
char inChar = Serial.read();
if (inChar == '\n')
{
result[i] = '\0';
Serial.flush();
return 0;
}
if(inChar!='\r')
{
result[i] = inChar;
i++;
}
}
}
void clearBuff(void)//打电话发短信清除指令
{
for(j=0;j<MAXCHAR;j++)
{
aa[j]=0x00;
}
j=0;
}
int Hand(char *s)//发短信打电话发短信调用指令
{
delay(200);
clearBuff();
delay(300);
readSerial(aa);
if(strstr(aa,s)!=NULL) //检测单片机和模块的连接
{
g_timeout=0;
clearBuff();
return 1;
}
if(g_timeout>50)
{
g_timeout=0;
return -1;
}
g_timeout++;
return 0;
}
void send_english(void) //发短信
{
clearBuff();
Serial.println(CMGF1);
delay(500);
while(Hand("OK")==0);
clearBuff();
Serial.println(SEND_MESSA_TO_YOUR);
delay(500);
while(Hand(">")==0);
Serial.println(SEND_MESSA_CONTENT); //发短信内容
delay(100);
Serial.print("\x01A"); //发送结束符号
delay(10);
delay(1000);
while(Hand("OK")==0);
}
void send_call(void) //打电话
{
clearBuff();
Serial.println(CALL_YOU_TELNUMBER); //打电话
delay(2000);
while(Hand("OK")==0);
}
void setup (void)
{
Serial.begin(115200);//设置波特率为115200
// Serial.println("serial port [ok]!");
}
void loop (void)
{
send_english(); //发短信
delay(1000);
send_call(); //打电话
while(1);
}
这一周感觉各种问题缠身,进度被卡住了。虽然脑子里的思路比较清晰,但是总被各种跳出来的拦路虎给难住了。
最近进度被有些慢,前几天终于把无线串口弄明白了,能够初步将无线串口发送而来的数据进行处理或者转发了,以前没想到这一点,总以为就是把数据显示出来就ok了。但是我果然还是很傻很天真,现实远远不是这样,显示出来远远不够。于是我就使用软串口来读取和处理数据。
现在能把数据传到节点的节点控制器控制了,但是但是,让我很痛苦的就是gsm900模块了,现在感觉就是它是一块大石头。gsm900模块对我的指令一闻不闻,我通过电脑连接模块,然后用硬串口发送AT指令根本无济于事及没有执行,也没有发聩,我把控制器写成空程序也是同效果。
我想到一种办法,将控制器内部编写一个程序,然后将控制器用外接电源供电,用软串口接收数据,硬串口发送指令。程序的大体思想就是用一个无线串口在电脑上发送AT指令,然后再用一块无线串口连接到节点控制器上,靠软串口接收指令。在程序内部,用一个字符串来接收存储指令。因为不是很了解是软串口和硬串口发送的指令到底是哪一个有效,所以我用软串口和硬串口两个串口同时输出字符串指令,但是都没有一个成功。
后来我想到了把指令通过程序写到控制器里,通过串口发送一些字符进去,用字符去控制指令的发送(或者直接用程序自动调动指令)。做了个最简单的打电话,传入一个字符命令开始打电话,再传入一个去挂断,结果成功了,我感觉问题解决了。但是今天后实验让我又苦恼了,电话的实验能够成功,但是我发短信因为要等到模块返回一个">"符号才能输入要发送的内容,所以没办法输入内容,所以GPRS功能也实现不了了。
现在最大的问题就是:发送指令到模块,模块一点反馈信息也没有,不知道到底生效没有。第一次使用sim900的时候直接用硬串口在电脑端输入AT指令就可以打电话了,当时也有反馈信息,但是测试过后一会就扩展板好像就出问题了。现在硬串口软串口AT指令都输不进去,就算行了指令也没有任何反馈信息,也不知道到底是哪里出了问题。现在指令通过串口发不进去,程序也没反馈,有点麻烦了,不过靠程序应该还是能行吧。