基于 51 单片机 GPRS 打电话等功能的实现!
血顶猎鹰
大家好,小弟花了大半个月时间折腾出使用 51 单片机和 TC35 进行打电话,发短信,收到短信后回一个短信给发信人(谁
发的就回给谁,不是指特定的一个人!)网上好多程序都是不能用的,这个程序经本人实际调试过,可以使用!!!
先介绍下功能:
1. 按下第一个按钮打电话给程序中指定的手机
2. 按下第二个键发温度值给程序中指定的手机
3. 按下第三个键发测试短信给程序中指定的手机
4. 随便来个手机发一个 bang 给和单片机连在一起的手机卡,手机卡回 ph=0.7 给你的手机,发别的字符就不会(这个相当
于密码),当然这个 bang 和 ph=0.7 这个是你自己设的。
下面看看电路图:
右边那个长长的就是 TC35 的接口了,第 15 脚接单片机,其他的按着连就行了。
处于方便,1602 就这样接了,还有按钮怎么接程序看看就知道了,红笔是我修改的,你懂的!
这些脚和单片机一下,再接下晶振就好了,接下来进入正题。
程序如下,程序横向有点长,为了让大家可以看程序方便点就把字体缩小了。里面解释很详细了,程序我是修改别人的,
之前不能用,现在可以了。
为了便于大家理解,我把几个重要的地方说下
打电话过程
mingling(3,AT12);for(x=0;x<11;x++)senddata(neirong[x]); senddata(0x3b);senddata(0x0D);while(sw1==0); senddata(0x0D); //
发 0x0d 停止打电话,首先发一些命令准备打,然后输入电话号码,在内容里面,然后结束符号,等待按键松开就不打了。
发短信的过程
ES=0;mingling(8,AT7); for(i=0;i<11;i++)senddata(neirong[i]);senddata(0x0d);delaymm(100);
senddata(shi+0x30);senddata(ge+0x30); //发送数据内容
senddata(0x20);senddata(0x1a);senddata(0x0d);ES=1;
串口中断关不关都没事的,一般不会冲突。过程和打电话的差不多,只是命令有点不同,你懂的!
接受短信过程
先检测下有没短信来 receive_ready();来了的话那个 TC35 通过串口给单片机发东西,我看了下东西是这个:
&&+CMTI: "SM",10 10 表示我当前的短信数,说明我之前有 9 条,加上现在的共 10 条
我们取标志位 TI,所以有 SystemBuf[5]==0x54)&&SystemBuf[6]==0x49 就表示短信来了,0x54,0x49 就是 TI 的意思,你
懂的!
来短信了我们准备发出短信,
if(receiveready==1)
{
read_message();
receiveready=0;
sendready=1;
}
Delay_ms(300);
message_read();
这里是准备的过程
其中
void message_read(void) /*准备是否回复短信给目标号码*/
{
if((sendready==1)&&(SystemBuf[5]==0x47)&&(SystemBuf[6]==0x52))
send=1;
}
就是绕来绕去,你们也可以不绕,这里简单。
另外我看了下这个时候数组里面存的东西,用我下面注释了的程序就好了(如果你们也想看看)
/* write_cmd(0x01);
write_cmd(0x80);
for(i=64;i<80;i++)
{
write_dat(SystemBuf[i]);
delaymm(1);
}
write_cmd(0xc0);
for(i=80;i<91;i++)
{
write_dat(SystemBuf[i]);
delaymm(1);
}
while(1);//读出来看下,结果是
//&&+CMGR: "REC UN 0~15
//READ","+86151581 16~31
//07680",,"11/06/1 32~47
//1,14:01:09+32"&& 48~63
//1234567891234567 64~79
//8912345678 80~89 */
看这个小东西把你的手机号码,发的时间日期,内容都记下来存到数组里了,接下来的事情就好办了
void readcommend(void) /*读取短信内容,判断相应指令是否正确*/
{
uchar i;
for(i=0;i<4;i++) //将短信内容中的指令部分截取出来放到
{ //CommandBuf 数组中
CommandBuf[i]=SystemBuf[64+i];
}
if((CommandBuf[0]=='b')&&(CommandBuf[1]=='a')&&(CommandBuf[2]=='n')&&(CommandBuf[3]=='g')) //判断指令是否为开发光管指令
{
write_cmd(0x01); //测试接收
write_cmd(0x80);
write_dat('b');
write_dat('a');
write_dat('n');
write_dat('g');
sendmessage();
} //如果发送的指令既不是 bang 就定义为错误操作,不干别的
}
这里读短信内容看看我们的暗号是不是对的,我这里就设置成 bang 了,如果密码是对的,我们就发短信!上面我们不是看
了这个小东西存的东西都放在哪了,看到没,在 64 开始就是你的内容了
接下来我们来看看它是怎么发出去的
void sendmessage(void) /*发送回复短信指令*/
{
uchar i;
for(i=0;i<8;i++)
{
AT_SendNumber[i]=AT_CMGS[i];
}
for(i=8;i<19;i++)
{
AT_SendNumber[i]=SystemBuf[18+i]; //位置 26~36 将对方号码提取用来回复给对方
}
sendstring(AT_SendNumber);senddata(0x0d);delaymm(100);
senddata('P');senddata('H');senddata('=');senddata('7');senddata('.');senddata('0');//内容
senddata(0x20);senddata(0x1a);senddata(0x0d);Delay_ms(30);
}
看到没,和之前我们发短信的方法是一样的,只不过这里用的是它数组里存的电话号码,所在位置 26~36,很方便看出来
的哈,用我上面的显示程序就行了。接下来就是删除短信了,发一个指令还有储存的位置,这里人性化处理,不把你以前
存在卡里的短信删掉,删掉的是你放进卡之后发过去的指令,这个是这样实现的。
read_message(void)程序执行的时候把位置读走了,但是后来没消掉看到没? 在 delete_message(void)中我们用一个循环把你
的位置放到数组里,然后再删,程序如下
for(i=8;i<11;i++)
{
AT_delete[i]=numberbuf[i-8];
}
好了,基本也就是这些了,打到这里累死我了!!!
下面是整个程序!大家拿回去用吧。
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define RxIn 90 //定义接收的数组长度为 90
uchar code AT[]="AT"; //握手信号
uchar code ATE[]="ATE"; //关回显
uchar code AT_CNMI[]="AT+CNMI=2,1";//设置这组参数来了新信息直接显示到串口,不作存储
uchar code AT_CSCA[]="AT+CSCA=\"+8613800571500\"";//设置服务中心号码 AT+CSCA=\"+8613010360500\"
uchar code AT_CMGF[]="AT+CMGF=1";//设置短信的格式为 text 格式
uchar code AT_CMGR[]="AT+CMGR=";//读取短信指令
uchar code AT_CMGS[]="AT+CMGS=";//发送短信指令
uchar code AT_CMGD[]="AT+CMGD=";//发送短信指令
uchar AT_delete[12];
uchar AT_Read[12]; //用来存储发送读取短信指令
uchar AT_SendNumber[22]; //用来存储发送短信号码指令
uchar numberbuf[3]; //用来保存短信条数
uchar idata SystemBuf[RxIn]; //储存出口接收数据
uchar CommandBuf[4]; //用来储存指令
uchar Rx=0;
bit receiveready=0; //接收短信标志位
bit sendready=0; //发送短信准备标志位
bit send=0; //发送短信标志位
sbit IGT=P2^7;//启动 GSM 的启动线连 IGT
sbit sw1=P3^3; //打电话
sbit sw2=P3^4; //发测试短信
sbit sw3=P3^5; //发温度
sbit beep=P3^2; //蜂鸣器
void Delay_ms(uint i);
void Start_GSM(void);
void UART_init (void);
void sendchar(uchar ch);
void sendstring(uchar *p);
void GSM_INIT(void);
void receive_ready(void);
void message_read(void);
void read_message(void);
void sendmessage(void);
uchar code AT7[]={0x41,0x54,0x2B,0x43,0x4D,0x47,0x53,0x3D};//AT+CMGS= AT+CMGS=“+8613xxxxxxxxx”回车>输入短消息。Crtl+Z 结束
并发送。
uchar code AT12[]={0x41,0x54,0x44,0x3E};//ATD> ATD*****; (拨号,"*"为需要拨的号码,如呼叫 13973292929,则为 ATD13973292929;
uchar code neirong[11]="15158107675"; //13185018567
sbit DQ=P3^7; //DS18B20 数据传输线接单片机的相应的引脚
unsigned char tempL=0; //临时变量低位
unsigned char tempH=0; //临时变量高位
float temperature; //温度值
unsigned char k,ge,shi,bai;
uchar code atshanchu[]={ "AT+CMGD=9"};
sbit lcdrs=P1^0;
sbit lcdrw=P1^1;
sbit lcden=P1^2;
void delaymm(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void delay(unsigned int k)
{
unsigned int n;
n=0;
while(n < k)
{n++;}
return;
}
void write_cmd(uchar cmd)
{
lcden=0;
lcdrs=0;
lcdrw=0;