技术热线: 4007-888-234

PIC18F452单片机GC864发短信控制流水灯方案

更新时间: 2019-03-22
阅读量:2383

十年单片机开发方案公司深圳英锐恩分享PIC18F452单片机GC864发短信控制流水灯方案,基于QL200开发板。

//------------------------------------------------------------
// 实验介绍: 利用QL200开发板与GSM模块实现发送信息控制流水灯,
//            GSM模块为GC864,用三根线连接232的收发脚和地。
// MCU: PIC18F452
// 拨码: S7拨到ON,S11,S12的高四位拨到ON,其余为OFF
// 现象: 发送“开机”到GSM模块(一定要插SIM卡),流水灯
//              循环跑,发送“关机”到GSM模块后流水灯熄灭,可反复
//  操作。
// 基于本实验可发挥想象,拓展功能 :-)
// 详细信息参见所用GSM模块的AT指令集
//------------------------------------------------------------           
//宏定义及配置位
#include "pic18.h" //18头文件
 
 __CONFIG(1,OSCSEN&HS); //振荡方式为HS
 __CONFIG(2,BORDIS&PWRTDIS); //4.2V复位
 __CONFIG(4,DEBUGDIS&LVPDIS&STVRDIS); //关调式
 __CONFIG(5,CPALL);
 __CONFIG(6,WPA&WRTEN);// 写保护
 __CONFIG(7,TRPA&TRPALL&SWDTDIS);// 关看门狗
 
#define  LED0 PORTC  //灯组1
#define  LED1 PORTB  //灯组2
//------------------------------------------------------------
//定义变量
static unsigned char rc_buff[100]; //信息接收缓存
static unsigned char rxter;    //信息长度计数

static unsigned char *ptr;
static unsigned char on_counter;   //开机信息核对
static unsigned char of_counter;   //关机信息核对
static unsigned char TAB_counter;  //换行计数器
static unsigned char rC_inter; //延时计数器
static unsigned char sC_inter;
const unsigned  char exe_on[]={0x35,0x46,0x30,0x30,0x36,0x37,0x33,0x41,0x0D,0x0A}; //开机的Unicode
const unsigned  char exe_of[]={0x35,0x31,0x37,0x33,0x36,0x37,0x33,0x41,0x0D,0x0A}; //关机的Unicode

static   volatile  unsigned char flag        @ 0x1a9; //定义标志位
static   volatile  bit  open_flag        @ (unsigned) &flag*8+0;  //流水灯运行标志
static   volatile  bit  new_flag        @ (unsigned) &flag*8+1;  //信息取出正确
static   volatile  bit  get_flag        @ (unsigned) &flag*8+2;  //有新信息标志

//------------------------------------------------------------
//函数申明
void ExeData(void);
void SysInit(void);
void TimeDelay(unsigned int kk);
void RegistInit(void);
void data_send0(void);
void RegistInit(void);
void data_send1(void);
void UartReceive(void);
void JudgeStat(void);
void comsend(unsigned char kk);
//------------------------------------------------------------
//主函数
void main(void)
{
 SysInit();  //初始化
 RegistInit();
 
 for(;;)
 {
  UartReceive();
  if(open_flag) //指令正确后开机
   ExeData();
 }

}
//------------------------------------------------------------
//流水灯子函数,转圈跑
void ExeData(void)
{
 unsigned char k;
 for(k=0x08;k!=0;k>>=1) //点亮PORTC高四位
 { 
  LED0 |= k;
  TimeDelay(5000);
  LED0 = 0;
 }
 
 for(k=0X01;k!=0X10;k<<=1) //点亮PORTB高四位
 {
  LED1 |= k;
  TimeDelay(5000);
  LED1 = 0;
 }

}
//------------------------------------------------------------
//中断服务
void interrupt isr(void)
{
 if(TMR2IF) //定时2中断处理
 {
  TMR2IF = 0;
  if(rC_inter<100)
          rC_inter++;
         if(sC_inter<250)
          sC_inter++;
        }
  
 if(RCIE&&RCIF)      //接收中断处理     
      {
        rC_inter = 0;
        if (OERR == 0)    
  {  
     rc_buff[rxter] = RCREG; 
   rxter++;
  }   
  else
  {
   CREN = 0;
   asm("nop");
   CREN = 1;
  }
      }
}

//------------------------------------------------------------
//系统初始化
void SysInit(void)
{
 flag = 0; //清标志位
 on_counter = 0;
 of_counter = 0;
 rxter = 0;
 sC_inter = 0;
 rC_inter = 0;
 TAB_counter = 0;
 
 TRISA = 0Xf0;
 TRISB = 0Xf0;

 TRISC = 0Xf0;
 
 PORTA = 0X00;
 PORTB = 0X00;
 PORTC = 0X00;
}
//------------------------------------------------------------
//特殊功能寄存器初始化
void RegistInit(void)
{
 SPBRG = 0XC;    //设置波特率为19200BPS
   TXSTA = 0X24;   //使能串口发送,选择高速波特率
   RCSTA = 0X90;   //使能串口工作,连续接收
   RCIE = 0X1;     //使能接收中断
   GIE = 0X1;      //开放全局中断
   PEIE = 0X1;     //使能外部中断

   TMR2IE = 1; //TMR2中断允许
   TMR2IF = 0;      
        PR2 = 249;  //定时计数为250US进中断
 T2CON = 0x04;  //开启定时器2,分频比为0
 RBIE = 0;       //禁止B口中断
}
   

//------------------------------------------------------------ 
// 延时子程序 
void TimeDelay(unsigned int kk) //软件延时
{
 unsigned int k;
 for(k=kk;k>0;k--)
 {
  asm("nop");
  asm("nop");
  asm("nop");
  asm("nop");
 }
}

//------------------------------------------------------------
// 提取信息子程序
void data_send0(void)
{

static unsigned char ask[]={'A','T','+','C','M','G','L',0x0d}; //AT+CMGL 回车
 unsigned char i;

 for(i=0;i<8;i++) //循环发送8个字节
 {
  TXREG = ask[i];
  NOP();
  NOP();
  TXIE = 0;
  while(!TXIF);
 }
}
//------------------------------------------------------------
// 删除信息1子程序
void data_send1(void)
{
 static unsigned char ask[]={'A','T','+','C','M','G','D','=','1',0x0d}; //AT+CMGL 回车
 unsigned char i;

 for(i=0;i<10;i++) //循环发送10个字节
 {
  TXREG = ask[i];
  NOP();
  NOP();
  TXIE = 0;
  while(!TXIF);

 }
}
//------------------------------------------------------------
//调试串口发送子程序
void  comsend(unsigned char kk)
{
 TXREG = kk;
 TXEN = 1;
 TXIE = 0;
 while(!TXIF); 
}
//------------------------------------------------------------
// 接收信息
void  UartReceive(void)
{
 if(rxter>15&&rC_inter>80)// 接收长度大于15且间隔大于20MS认为接收完成
 {
  JudgeStat();   //对信息进行操作                                            

   rxter = 0;
            rC_inter = 0;       
        }
        if(get_flag)
        { 
         if(sC_inter >= 100)
         {
          data_send0();   //25MS后发送AT+CMGL指令提取信息
          get_flag = 0;
         }
        } 
}
//------------------------------------------------------------
// 处理信息
void JudgeStat(void) 
{
 unsigned char i = 0;
 
 ptr = rc_buff;
 while(*ptr != 0x2B)  //扫描信息串里有无'+'
 {
  ptr++;
 }
 if(*(ptr+4) == 0x49)   //+CMTI:提示有新的信息
 { 
  get_flag = 1;
  sC_inter = 0;
 }
 else if(*(ptr+4) == 0x4C) //+CMGL:有信息列出
  new_flag = 1;
  
 if(new_flag)

 {
  new_flag = 0;
  ptr = rc_buff; //重新指向缓存区
  while(TAB_counter < 2)
  {
   while(*ptr != 0x0A) //扫描两次换行
   {
    ptr++;
   }
   ptr++;
   TAB_counter++;
  }
  for(i=0;i<8;i++,ptr++) //提取汉字信息
  {
   if(*ptr == exe_on[i])
    on_counter++;    
   if(*ptr == exe_of[i])
    of_counter++;

 }
  //comsend(on_counter);
  //comsend(of_counter);
  if(on_counter == 0x08) //开机8个字节全正确
   open_flag = 1; //开机标志位置位
  if(of_counter == 0x08) //关机8个字节全正确
   open_flag = 0; //关机标志位置清零
  on_counter = 0; //计数器清零
  of_counter = 0;
  TAB_counter = 0;
  for(i=0;i<100;i++)
   rc_buff[i] = 0; //清空接收缓存
  data_send1(); //删除此条信息
 }

//------------------------------------------------------------
// END
//------------------------------------------------------------