薛定谔的猫

一款GSM模块实现接电话收短信功能~

0
阅读(4537)

简单的一款GSM收发模块,MCU通过SPI串口给TAC35烧写数据,由其发射传递给移动基站,实现信息的传递。

MCU通过RES232与上位机时间控制信息的传递。以便得到控制信息进一步与GSM发射模块通信。

电源管理电路,其实还可以更加优化去耦,滤波,储能等功能,限于成本考虑,暂且放弃。

主程序如下,供大家参考!

#include <intrins.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "keybord.h"

 
 
 

//**********函数定义**********//
void   main(void);   //主函数
void   Ini_UART(void);   //串口初始化
void   Delay(void);   //延时
void   Delay1(uint z);
void   CMGF(void);   //设置发送数据为TXET格式
void   CMGS(void);   //设置目的手机号码
void   SEND(void);   //发送字符串
void   ATD(void);   //打电话
void  ATH(void);   //挂断电话
void  Gsm_test  ()  ;
void  ATA(void);
void  CLEAR_BUF();
void  change_num();
void   CLIP(void);   //  功能:开启来电号码提示功能  如果不开启,则不能识别来电号码
void  send_one(uchar a) ;
void    CMGR() ;  //读取对应的短信
uchar  Meg_num();
uchar  Meg_num1();
void getMeg_content() ;
void   CNMI(void);
//void ComInStr(unsigned char *Str) ;
 
int  mode;
uchar idata zong[22];
uchar xdata buf[200];
uchar xdata Meg_buf[160];
uchar xdata  phone_num[42];
uchar xdata  duanxin_num [18];
uchar xdata  duanxin_con[160];
int  flag;
int  bufnum=0;
uchar temp1;
uchar num,num1;     //短信号  
 uchar str1[]={"AT"};
 uchar str2[]={"ATD"};
 uchar str3[]= {"ATH"};
 uchar str5[]={"AT+CMGS="};

void   main(void)
{
 
  LCD_Init();
   Display_full_screen_color (BLACK);
   disintlcd();
 Ini_UART();  //串口初始化
   Delay();
   Gsm_test();
   Delay1(500);             //注意延时的大小设定,否则通讯出错
// DrawString (0,0,buf,BLACK, WHITE,  NORMAL); 
 ES =0;
 bufnum = 0;
     
  if(buf[5]=='O' && buf[6] =='K') 
{
  DrawString (0,50,"初始化通过",WHITE,BLACK,NORMAL);
    delay1ms(1000);
 DrawString (0,50,"          ",BLACK,BLACK, NORMAL);
}
 else  
{
DrawString (0,50,"初始化错误",WHITE, BLACK,  NORMAL);
}
DrawString (13,70,"按S8进入接电话模式",WHITE, BLACK,  NORMAL);
DrawString (13,85,"按S4进入收短信模式",WHITE, BLACK,  NORMAL);
   while (1)
   { 
  mode = getinput();
  if (0)
{
 
 DrawString (13,220,"短信模式",WHITE, BLACK,NORMAL);
 getinput();
 if(flag ==1)
       {
         ES =0;
         CMGF();
         Delay1(3000);           //注意延时的大小设定,否则通讯出错
         CMGS();
         Delay1(3000);
         SEND();
      Delay1(500);
 
       DrawString (INTNUM,250,"OK          ",BLACK,WHITE,NORMAL); 
   Delay1(500);
   DispOneColor(INTSIGN,240,229,271,BLACK)  ;
   DrawString (13,220,"         ", BLACK, BLACK,NORMAL);

        }  
  else  
  {
    DrawString (INTNUM,250,"ERROR",BLACK,WHITE,NORMAL); 
 Delay1(500);
 DrawString (INTNUM,250,"     ",WHITE,WHITE,NORMAL);
 DispOneColor(INTSIGN,240,229,271,BLACK)  ;
 DrawString (0,220,"          ", BLACK, BLACK,NORMAL);
  }
}
if(mode == 2)
{
 uchar  call_temp = 0;   //空闲标志位,如果大于5,就会提示电话已经挂断
 bit   cut_call = 0;   //电话挂断标志位,
 bit    carry_call = 0;    //接电话标志位
 bit    carry_flag = 0;    //接电话标志位
 bit    come_call = 0;     //有来电标志位 
 uchar  zd_gua = 0;   //自动挂断标志位,如果对方没打通电话,然后挂断电话,此标志位置1
 CLIP();   //  功能:开启来电号码提示功能  如果不开启,则不能识别来电号码
 Delay1(500);    //Delay1(500);
 DrawString (0,250,"                              ",BLACK, BLACK,  NORMAL);
 DrawString (13,220,"接电话模式        ",WHITE, BLACK,NORMAL);
DrawString (0,265,"                              ",RED, GREEN,  NORMAL);
DrawString (13,265,"长按F3退出 按F4接电话      ",RED, GREEN,  NORMAL);
 ES = 1;
 while(1)
 {

 bufnum = 0;
 Delay1(500);    //Delay1(500);

  if(buf[2] == 'R'&&buf[3]=='I'&&buf[4]=='N'&&buf[5]=='G') //如果此时有来电,显示来电提示和来电号码
 {                
  
   change_num();   //把接收到的号码放到指定的数组去
DrawString (0,250,"                        ",RED, YELLOW,  NORMAL);  //这里的空格数为22,请不要随便改动,否则会出现错误
DrawString (13,250,"来电号码",RED, YELLOW,  NORMAL);
DrawString (90, 250,  phone_num ,BLACK,RED,NORMAL);  //显示来电号码
   zd_gua = 0;  //清除自动挂断标志位
      cut_call = 1;  //把允许挂断电话标志位  置1
   CLEAR_BUF();  //清空缓存
   call_temp = 0; //清除空闲标志位,防止系统提示无来电或挂断电话 
      come_call = 1;
//P1口灯闪动,表示此时有来电,用户可根据自己的实际情况再作出修改//
   P1 = 0x00;
      Delay1(500);
   P1 = 0xff;
      Delay1(500);
   P1 = 0x00;
      Delay1(500);
   P1 = 0xff;
   }

  //当平时无来电时,显示无来电或电话已挂断 //
  if((~(buf[2] == 'R'&&buf[3]=='I'&&buf[4]=='N'&&buf[5]=='G'))&(!cut_call)&(!carry_call)) 
   {
   if(call_temp>3)  //标志位大于5,提示的内容刷新一次
      {
//DrawString (90, 250,"",BLACK,BLACK,NORMAL);
DrawString (0,250,"                                ",RED, YELLOW,  NORMAL);
DrawString (13,250,"无来电或电话已挂断",RED, YELLOW,  NORMAL);
    call_temp = 0;
   }
  }
  if(zd_gua>2)  //对方自动挂掉电话 
    {
  zd_gua = 0;
  cut_call = 0;
  come_call = 0;
     }
 
 
  //当接收到挂断电话的命令,提示电话已挂断 //
  if(((buf[2] == 'N'&&buf[3]=='O'))&(carry_call)) 
  {
DrawString (0,250,"                                ",RED, YELLOW,  NORMAL);
DrawString (13,250,"电话已挂断",RED, YELLOW,  NORMAL);
//清除相应的标志位// 
  cut_call = 0;
  carry_call = 0;
  carry_flag = 0;
  come_call =0;
  }
 //模拟信号时钟,正常闪动时表示在处于接电话模式//
      P1=0XFF;
      Delay1(500);
   P1=0XFE;
      Delay1(500);
      P1=0XFF;
   zd_gua ++;//自动挂断标志位自加1
   call_temp++; //标志位自加1
  //如果F3被按下,退出接电话模式//
 if((P3|0xfb)!=0xFF)
  {
mode = 8; break;   
 
  }
 //如果F4被按下,接电话标志位置1//
 if(((P3|0xf7)!=0xFF)&(cut_call))
   {
   carry_flag = 1;
  
   }
 
//如果接电话标志位置1,给TC35模块发送接电话命令// 
  if(carry_flag)
  {
      ATA(); //接电话命令  
      Delay1(60);
   ATA();
   Delay1(60);
   DrawString (0,250,"                                ",RED, YELLOW,  NORMAL);
      DrawString (13,250,"来电已接",RED, YELLOW,  NORMAL);
    carry_call = 1;   //接电话标志置1
    carry_flag = 0;   //此标志位清0,等待下次接电话
   CLEAR_BUF();    //清除缓存,以免出错 
  }

   }
}
//如果mode 为8,即为退出接电话模式
if(mode ==8)
{
DrawString (0,250,"                                  ",RED, BLACK,  NORMAL);
 DrawString (13,220,"接电话模式已退出",WHITE, BLACK,NORMAL);
DrawString (0,265,"                                  ",RED,BLACK,  NORMAL);
mode = 0;
}
if(mode == 3)
{
DrawString (0,250,"                                  ",RED, BLACK,  NORMAL);
 DrawString (13,220,"接收短信模式        ",WHITE, BLACK,NORMAL);
DrawString (0,265,"                                  ",RED,BLACK,  NORMAL);
CNMI();            //开启新短信提示功能
 Delay1(3000);    //Delay1(200);
 CMGF();          //把模块设置为TEXT工作模式,这样方便读短信。
 Delay1(600);    //Delay1(50);
 ES = 1;

while(1)
{
 bufnum = 0;
 Delay1(500);    //Delay1(500);
  if(buf[3] == 'C'&&buf[4]=='M'&&buf[5]=='T'&&buf[6]=='I') //如果此时有短信,显示来电提示和来电号码
 {
 
 DrawString (13,235,"您好!有新的短信。",WHITE, BLACK,NORMAL);
 num = Meg_num();     //把对应的短信号先导出来
 num1 = Meg_num1();   //把对应的短信号先导出来
 CLEAR_BUF();    //清除缓存,以免出错 
 
 CMGR();       //读新短信内容
      Delay1(6000);     //此延时可以改短,看个人习惯而定,但也不要改得太短
 getMeg_content(); 
 
DrawString (0,250,"                                             ",RED, YELLOW,  NORMAL);  //这里的空格数为22,请不要随便改动,否则会出现错误
DrawString (5,250,"发信人号码:",RED, YELLOW,  NORMAL);
DrawString (90, 250,  duanxin_num ,BLACK,RED,NORMAL);  //显示来电号码
DrawString (0,265,"                                             ",RED, GREEN,  NORMAL);  //这里的空格数为22,请不要随便改动,否则会出现错误
DrawString (0,265,"内容",RED, GREEN,  NORMAL);
DrawString (30,265,duanxin_con,RED, GREEN,  NORMAL);  //显示英文短信内容
 
 CLEAR_BUF();    //清除缓存,以免出错 
 }

 //模拟信号时钟,正常闪动时表示在处于接电话模式//
      P1=0XFF;
      Delay1(500);
   P1=0XF7;
      Delay1(500);
      P1=0XFF;
 

  //如果F3被按下,退出收短信模式//
 if((P3|0xfb)!=0xFF)
  {
mode = 5; break;   
 
  }
 
 
}
 
}
//MODE为5,退出收短信模式 //
if(mode ==5)
{
DrawString (0,235,"                                  ",RED, BLACK,  NORMAL);
DrawString (0,250,"                                  ",RED, BLACK,  NORMAL);
 DrawString (13,220,"短信模式已退出",WHITE, BLACK,NORMAL);
DrawString (0,265,"                                  ",RED,BLACK,  NORMAL);
mode = 0;
}

if(0)
{
  if (mode == 0&&flag == 1)
  {
   Ini_UART(); 
   bufnum=0;
   Delay();
   ATD();
 Delay1(500); 
//DrawString (0,20,buf,BLACK, WHITE,  NORMAL); 
  ES =0;
 bufnum=0;
  if(buf[0] == 'A'&&buf[1]=='T'&&buf[14]==';') 
{
  DrawString (INTNUM,250,"通讯中......",BLACK, WHITE,  NORMAL);
 

}
   else  
{
DrawString (INTNUM,250,"ERROR      ", BLACK, WHITE,  NORMAL);
   delay1ms(1000);
 DispOneColor(INTSIGN,240,229,271,BLACK)  ;
 continue;
 
}

  
 Delay();   //打电话
  Delay1(5000);           //注意延时的大小设定,否则通讯出错
   Delay1(10000);
 ATH(); 
 Delay1(3000);    
Delay();
 DispOneColor(INTSIGN,240,229,271,BLACK)  ;
 }
else 
 {
DrawString (INTNUM,250,"ERROR NUM",BLACK,WHITE,NORMAL);
   delay1ms(1000);
 DrawString (INTNUM,250,"     ",WHITE,WHITE,NORMAL);  
  DispOneColor(INTSIGN,240,229,271,BLACK)  ;
  }
 }
}
}

void   Ini_UART(void)
{
        SCON=0x50;   //UART方式1:8位UART;   REN=1:允许接收
        PCON=0x00;   //SMOD=0:波特率不加倍
        TMOD=0x20;   //T1方式2,用于UART波特率
        TH1=0xFD;
        TL1=0xFD;   //UART波特率设置:9600
       
  TI = 0;
  RI = 0;
  EA = 1;
  TR1=1;
}

 
 
void com_interrupt(void) interrupt 4 using 3
{
 
   if(RI)                                 //处理接收中断
   {
                                      //清除中断标志位
      buf[ bufnum]=SBUF;             //接收串口数据
        RI=0;
  bufnum++;
   
      }
   
}
 
 
 void  Gsm_test  ()
 {
   uint i;
  uchar   code test[]= {0x41,0x54,0X0D}   ;
 ES = 0;
   for (i=0;i<3;i++)
   {
     SBUF = test[i];
     while (TI == 0)  ;
   TI = 0;
  
   }
  
   ES = 1;
 }

void   Delay(void)
{      
        uint   i,j;
        for(i=0;i<10;i++)
        {
            for(j=0;j<1000;j++);
        }
}
void   Delay1(uint z)
{
    uint x,y;
 for(x=z;x>0;x--)
    for(y=110;y>0;y--);
}
 
void   ATD(void)
{
 uchar   code houzui[]= {0x3B,0X0D};    //   ATD15839114002;回车
   
    uint i;
 ES =0;
     strcpy(zong,str2);
        strcat(zong,shuru);
    for(i=0;i<14;i++)
        {
            SBUF=zong[i];
            while(TI==0);
            TI=0;
           
        }
     for(i=0;i<2;i++)
     {
          SBUF=houzui[i];
            while(TI==0);
            TI=0;
     }
  ES =1;
}
void  ATH(void)
{
    uchar   code guaduan[]= {0x41,0x54,0x48,0X0D};
  uint i;
    for(i=0;i<4;i++)
        {
            SBUF=guaduan[i];
            while(TI==0);
            TI=0;
           
        }
}
void  ATA(void)
{
    uchar   code jietong[]= {0x41,0x54,0x41,0X0D};
  uint i;
    for(i=0;i<4;i++)
        {
            SBUF=jietong[i];
            while(TI==0);
            TI=0;
           
        }
}
 

void   CMGF(void)
{
     uchar   code sel[10]= {0x41,0x54,0x2B,0x43,0x4D,0x47,0x46,0x3D,0x31,0x0D}; //AT+CMGF=1回车
  uint i;
   for(i=0;i<10;i++)
        {
            SBUF=sel[i];
            while(TI==0);
            TI=0;
           
        }
}
void   CLIP(void)   //  功能:开启来电号码提示功能  如果不开启,则不能识别来电号码
{
     uchar   code sel[10]= {0x41,0x54,0x2B,0x43,0x4C,0x49,0x50,0x3D,0x31,0x0D}; //AT+CLIP=1回车
  uint i;
   for(i=0;i<10;i++)
        {
            SBUF=sel[i];
            while(TI==0);
            TI=0;
           
        }
}
void   CNMI(void)   //  功能:开启新短信提示功能
{
     uchar   code sel[16]= {0x41,0x54,0x2B,0x43,0x4E,0x4D,0x49,0x3D,0x32,0x2C,0x31,0x2C,0x30,0x2C,0x30,0x0D}; //AT+CNMI=2,1,0,0回车    
  uint i;
   for(i=0;i<16;i++)
        {
            SBUF=sel[i];
            while(TI==0);
            TI=0;
           
        }
}

void   CMGS(void)
{
   //  uchar   code mode[20]= {0x41,0x54,0x2B,0x43,0x4D,0x47,0x53,0x3D,0x31,0x33,0x38,0x33,0x39,0x31,0x31,0x30,0x34,0x31,0x35,0x0D}; //AT+CMGS=15839114002回车
  uint i;
        strcpy(zong,str5);
        strcat(zong,shuru);
  for(i=0;i<19;i++)
        {
            SBUF=zong[i];
            while(TI==0);
            TI=0;
           
        }
           SBUF=0x0D;
           while(TI==0);
            TI=0;
 
}
uchar  Meg_num()  //提取十位数    
{
uchar i;
i = buf[14];
return    i;
}
uchar  Meg_num1()  //提取个位数
{
uchar i;
i = buf[15];
return    i;
}

void  send_one(uchar a)   //  串口发送一个字节
{
SBUF = a;
while(TI==0);
TI=0;
}
 

void    CMGR()   //读取对应的短信     即AT+CMGR=NUM NUM为要读取短信的位置号,此号相当重要
{  uint i;
//uchar num;
     uchar   code Meg[8]= {0x41,0x54,0x2B,0x43,0x4D,0x47,0x52,0x3D}; //AT+CMGR=Meg_num回车
//   num = Meg_num();
//  Meg[8] = num;
 ES =0;
 for(i=0;i<8;i++)
        {
            SBUF=Meg[i];
            while(TI==0);
            TI=0;
           
        }
  send_one(num); //短信对应的位置数(如果是10以内,此位为个位,如果10以上,此位为十位)
  send_one(num1);//短信对应的位置数(如果10以上,此为个位)    
  send_one(0x0D);  //不要漏掉换行号,不然模块不会响应
  ES = 1;
 
}
void getMeg_content()    //提取短信发信人号码及短信内容的子程序 
{
uint i,b=0,a=0,c=0,temp,temp1;
/*
for(i=0;i<80;i++)
{
b = buf[i];
if(b == 0x22)
{
 a++;
}
if(a == 3)
{
for(y=0;y<14;y++)
{
duanxin_num[y] = buf[i+y];
}
return;
}
*/
for(i = 0;i<100;i++)
{
if(buf[i]==0x22)
{
b++;
if(b==3)
{
 temp =i+1;
 //i =80;
 for(temp;buf[temp]!=0x22;temp++)
 {
 duanxin_num[a] = buf[temp];
 a++;
 }
duanxin_num[a] = 0x00;

}
   if(b==6)
   {
 temp1 = i+3;
 i = 120;
 for(temp1;buf[temp1]!=0x0D;temp1++)
 {
 duanxin_con[c] = buf[temp1];
 c++;
 }
duanxin_con[c] = 0x00;
 

   }
 
 
}
}
 
}
 
 
 
 
 
 
 

void   SEND(void)   //发送字符串
{
    uchar   code neirong[10]={0x48,0x69,0x21,0x6E,0x69,0x68,0x61,0x6F,0x2E,0x1a};  //hi!nihao.
 uint i;
 ES =0;
 for(i=0;i<10;i++)
        {
            SBUF=neirong[i];
            while(TI==0);
            TI=0;
           
        }
  ES = 1;
}
void  CLEAR_BUF()  //清除缓存子程序
{
uint i;
ES = 0;
 for(i=0;i<200;i++)
{
  buf[i] = 0;

}
ES = 1;
}
void  change_num()  //提取来电号码子程序 
{
uint i,a=0,temp;
//uint b;
/*
uchar num[] = {0x70,0x68,0x6f,0x6e,0x65,0x20,0x6e,0x75,0x6d,0x62,0x65,0x72,0x20,0x69,0x73,0x3a};
for(b = 0;b<16;b++)
{
phone_num[a] = num[b];
a++;
}
*/
for(i = 0;i<30;i++)
{
if(buf[i]==0x22)
{
 temp =i+1;i =50;
 for(temp;buf[temp]!=0x22;temp++)
 {
 phone_num[a] = buf[temp];
 a++;
 }
phone_num[a] = 0x00;
}
}
 
}