随着移动通信的发展,手机在人们的生活中变得越来越普及,对人们的生活的影响越来越大。使用移动通信网络的SMS(短消息)/GPRS(通用分组无线业务)工业模块(即手机模块)在工业现场使用的越来越广泛,尤其是在远程监控领域更是得到了广泛的应用,比如北京08奥运场馆的火灾监控系统、泰山旅游景区的火灾监控系统、很多大中城市的公交车/出租车管理系统等等都使用了SMS/GPRS工业模块。随着移动通信网络的服务质量进一步提高,短消息延迟的进一步减小、GPRS资费进一步下调,手机模块必将得到更为广泛的使用。
手机在大学生中特别是在高年级大学生中基本已经普及,用单片机控制手机模块发短信、发送GPRS信息必将会提升他们极大的兴趣。本实验有助于电子信息类专业学生加深对电子电路的理解、对单片机的理解、对TCP/IP协议的理解、对移动通信相关知识的理解以及对使用可视化软件开发工具进行上位机开发的相关知识的理解。手机模块内置了短消息及GPRS的协议,对外接口仅为一UART串口,使用AT指令通过串口与外界交互,所以开发难度适中,有利于实现。能完整的做完本实验将会积累一定的工程经验,对学生找工作将会增加一个很重的砝码。
软件方案
1、串口部分
初始化部分
void UartInit()
{
PCON=0x00;
SCON=0x50;
T2CON=0x30;
RCAP2H=0xff;
RCAP2L=0xb8; //9600
TR2=1;
IP=0x10;//串口中断优先级最高
ES=1;
EA=1;
}
中断接收部分
UartInt() interrupt 4
{
RI=0;
ReceiveBuffer[RecPointer%80]=SBUF;
RecPointer++;
}
2、液晶显示部分
void sendBYTE(uchar dat)/*串行传送一字节数据*/
{
uchar i;
for (i=0;i<8;i++)
{
CLK = 0;
if ((dat & 0x80)!=0)
SID = 1;
else
SID = 0;
CLK = 1;
dat = dat<<1;
}
}
void sendCMD(uchar dat)/*写控制指令*/
{
_CS = 1;
sendBYTE(0xf8);
sendBYTE(dat & 0xf0);
sendBYTE((dat<<4)&0xf0);
_CS = 0;
}
void sendDAT(uchar dat)/*写显示数据;也可以写一个单字节字符*/
{
_CS = 1;
sendBYTE(0xfa);
sendBYTE(dat & 0xf0);
sendBYTE((dat<<4)&0xf0);
_CS = 0;
}
void display(uchar x_add,uchar *dat)
/*写汉字到LCD屏指定位置*/
/*x_add 显示RAM地址*/
/*dat/dat1 显示汉字编码*/
{
sendCMD(x_add);
while(*dat)
{
sendDAT(*(dat++));
}
}
void initlcm(void)/*初始化LCM*/
{
sendCMD(0x30);/*功能设置:一次送8位数据,基本指令集*/
sendCMD(0x04);/*点设定:显示字符/光标从左到右移位,DDRAM地址加一*/
sendCMD(0x0e);/*显示设定:开显示,显示光标,当前显示位反白闪动关*/
sendCMD(0x01);/*清DDRAM*/
sendCMD(0x02);/*DDRAM地址归位*/
}
3、按键扫描部分
uchar scankey()
{
uchar keyvalue ,keyvalue1 ,i;
for(i=0;i<3;i++) //第一次扫描
{
if(i==0) //第一行
P2=0xfe;
if(i==1) //第二行
P2=0xfd;
if(i==2) //第三行
P2=0xfb;
//delay(10);
keyvalue=P2;
keyvalue&=0xf0;
keyvalue>>=4;
switch(keyvalue)
{
case 0x0e:keyvalue=0;break;
case 0x0d:keyvalue=1;break;
case 0x0b:keyvalue=2;break;
case 0x07:keyvalue=3;break;
default: keyvalue=0x55;break;
}
if(keyvalue==0x55) continue; //本行无键按下继续扫描
else
{
keyvalue=keyvalue+i*4;
break; //本行有键按下跳出扫描
}
}
if (keyvalue==0x55 ) return 0xaa;//没有键按下
else //有键按下 第二次扫描
{
//LED=~LED;
delay(35000) ;
for(i=0;i<3;i++)
{
if(i==0) // 第一行
P2=0xfe;
if(i==1) // 第二行
P2=0xfd;
if(i==2) // 第三行
P2=0xfb;
// delay(10);
keyvalue1=P2;
keyvalue1&=0xf0;
keyvalue1>>=4;
switch(keyvalue1)
{
case 0x0e:keyvalue1=0;break;
case 0x0d:keyvalue1=1;break;
case 0x0b:keyvalue1=2;break;
case 0x07:keyvalue1=3;break;
default: keyvalue1=0x55;break;
}
if(keyvalue1==0x55)
continue; //本行无键按下继续扫描
else
{
keyvalue1=keyvalue1+i*4;
break; //本行有键按下跳出扫描
}
}
if(keyvalue==keyvalue1)
{ LED=~LED;
return keyvalue;} //两次扫描结果一致
else
return 0xaa;
}
}
4、呼叫部分
void dial()
{
uchar i;
display(0x80,"请输入对方号码:");
display(0x90,"(以#结束)");
ReadKey(thirdadd);
while(1)
{
SendString("ATD");
ES=0;
for(i=0;i<KeyPointer;i++)
{
SBUF=KeyBuffer[i] ;
while(TI==0) ; TI=0;
}
SBUF=’’;’’ ;
while(TI==0) ; TI=0;
SBUF=0x0d ;
while(TI==0) ; TI=0;
SBUF=0x0a ;
while(TI==0) ; TI=0;
if(CheckAck())
break;
}
display(fourthadd,"嘟………");
KeyPointer=0;
TR0=1;
Timer0IntCount=0;
ES=1;
while(Timer0IntCount<30000) //300s
{
if(strstr(ReceiveBuffer,"BUSY"))
{
display(fourthadd,"对方忙!");
break;
}
if(strstr(ReceiveBuffer,"ANSWER"))
{
display(fourthadd,"无应答!");
break;
}
if(strstr(ReceiveBuffer,"CARRIER"))
{
display(fourthadd,"号码有误!");
break;
}
}
Timer0IntCount=0;
while(Timer0IntCount<300); //3s
ES=0;
TR0=0;
}
5、短信部分
void SMS()
{
uchar DesNumEndAdd,i;
display(0x80,"请输入对方号码:");
display(0x90,"(以#结束)");
ReadKey(thirdadd);
DesNumEndAdd=KeyPointer;//按键数据接收缓冲区中,
if(DesNumEndAdd!=11)
{
display(fourthadd,"输入号码有误!");
TR0=1;
Timer0IntCount=0;
while(Timer0IntCount<300) ; //3s
TR0=0; //关定时器0
KeyPointer=0;
return;
}
sendCMD(0x01);/*清DDRAM*/
delay(200);
display(0x80,"请输入短信内容:");
display(0x90,"(以#结束)");
ReadKey(thirdadd);
while(1)
{
SendATCMD("AT+CMGF=1");
if(CheckAck())
break;
}
while(1)
{
SendATCMD("AT+CSCS=\"GSM\"");
if(CheckAck())
break;
}
while(1)
{
SendATCMD("AT+CSMP=17,168,0,0");
if(CheckAck())
break;
}
SendString("AT+CMGS=\"+86");
ES=0;
for(i=0;i<DesNumEndAdd;i++)
{
SBUF=KeyBuffer[i] ;
while(TI==0) ; TI=0;
}
SBUF=’’"’’;
while(TI==0) ; TI=0;
SBUF=0x0d ;
while(TI==0) ; TI=0;
SBUF=0x0a ;
while(TI==0) ; TI=0;
delay(20000);// 等待‘<’
for(i=DesNumEndAdd;i<KeyPointer;i++)
{
SBUF=KeyBuffer[i] ;
while(TI==0) ; TI=0;
}
delay(2000);//
SBUF=0x1a;
while(TI==0) ; TI=0;
KeyPointer=0;
sendCMD(0x01);/*清DDRAM*/
delay(200);
display(secondadd+2,"发送成功!");
TR0=1;
Timer0IntCount=0;
while(Timer0IntCount<300) ; //3s
TR0=0; //关定时器0
}