热度 1||
最近......应该说是搞了很长时间的东西了。
在搞一个自己很久很久就想做的东西。简要说一下功能吧。
这个东西有3个按键。暂且叫它们为Key1,Key2和Set吧。其中还有两个继电器S1和S2,一个单片机(STC12LE5A60S2),一个SIM900A模块。简单的就这些东西。我也不会写博文,描述的功能很乱,暂且就这么写吧。我也不知道大家看得懂吗。
功能呢。
①如果按键Key1被按下,则继电器S1翻转状态。再次按Key1,则继电器S1的状态再次翻转。相同原理按键Key2同样原理控制继电器S2。这个都是比较容易实现的。
②现在说一下电话控制功能。也就是说当我打电话给模块的时候,单片机会通过串口收到数据
RING |
+CLIP: "18158113280",161,"",,"",0 |
然后单片机会通过读取串口数据来获得来电电话号码为:18158113280。再然后,单片机将这个电话号码和自己之前存在eepom中的主人电话号码相比对。如果电话号码相同,则控制继电器S1状态翻转。然后发送ATH挂掉电话。如果电话号码不一致则不做任何处理。
③然后就是短信控制了。当我向模块发送短信内容:继电器S1打开。则继电器S1打开。当我向模块发送短信内容:继电器S1关闭。则继电器S1关闭。同样也可以这样控制继电器S2。只是将短信内容换成继电器S2打开和继电器S2关闭就可以了。
目前就着三个功能。在制作过程中,论坛里的好友辛昕给予了我无私的帮助。在这儿先感谢一下。可是现在我还是有很多疑惑。就是我在网上下载的一些例程百篇一律。几乎都是出自一处。例如下面这段。
while(!Hand("OK"))//与GSM模块握手,判断是否收到GSM模块返回的OK
{
Uart2SendStr("AT\r");//握手,同步波特率。
DelaySec(1);//延时
}
无一例外的都是这种模式。发送完一串AT命令字符。然后等待1秒。然后检测收到的字符串里面有没有OK这两个字。如果有,则说明握手成功,跳出while循环。如果没有,则继续发送AT。直到收到OK为止。这样就很容易出现问题。但是我也不知道该怎么解决这个问题。
其实SIM900A的数据手册上写的很清楚。就是SIM900的回复命令都是以0D 0A开头,中间是内容,然后以0D 0A结尾。例如下面:
0D 0A 4F 4B 0D 0A //这是SIM900回复的内容:OK
但是有的命令就不一样了。举个例子。当有电话打进来的时候。你会在串口截获下面这组字符串:
0D 0A 52 49 4E 47 0D 0A 0D 0A 2B 43 4C 49 50 3A 20 22 31 38 31 35 38 31 31 33 32 38 30 22 2C 31 36 31 2C 22 22 2C 2C 22 22 2C 30 0D 0A |
其中绿色字体是单词RING。蓝色字体是我的手机号码:18158113280.反正大家看到了吗。这里面有四组0D 0A。是吧。很恼人。我就不知道串口数组该怎么处理了。
因为我不知道这组数据什么时候收完,什么时候该清掉。说了这么多我还是没有说到自己困扰的地方。我想问一下我怎么处理串口数组的收发数呢。我把我自己的代码贴出来让大家看一下吧。代码还没完善好。所以有些地方读起来可能比较费劲。
#include "stc12c5a.h"
#include <string.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define UART1_PRIO 2 // 串口1中断优先级2
#define UART2_PRIO 3 // 串口2中断优先级3
#define MAXBUF 200
#define MAXRCV 200
/*定义单片机的IO口*/
sbit LED2=P2^7; //定义LED指示灯I/O口
sbit LED3=P2^6; //定义LED指示灯I/O口 黄色灯
sbit LED4=P2^5; //定义LED指示灯I/O口 蓝色灯
sbit KEY1=P2^2; //定义按键I/O口
sbit KEY2=P2^1; //定义按键I/O口
sbit KEY_Set=P2^0; //定义按键I/O口
sbit SIM_900A_STAR=P2^4;//定义SIM900开机
sbit Buzzer=P1^0;//定义蜂鸣器
//以下是开机后单片机所发送的一些指令。
uchar AT_DATA_1[] = {0x41,0x54,0x2B,0x43,0x4D,0x47,0x52,0x3D,0x31,0x0D,0x0A};//AT+CMGR=1 读1号短信位置。
uchar AT_DATA_2[] = {0x41,0x54,0x0D,0x0A};//AT 握手
uchar AT_DATA_3[] = {0x41,0x54,0x0D,0x0A};//ATH 挂电话
uchar GsmRcv[MAXRCV] = {0};
uchar DebugBuf_U2[MAXBUF] = {0};
uchar DebugBuf_U1[MAXBUF] = {0};
uchar Boss_Tel_NO[14]={0};//主人电话号码
uchar New_Tel_NO[11]={0};//新来电/新短信电话号码
uchar Boss_Feixin_NO[9]={0};//主人飞信号码
uchar New_Feixin_NO[9]={0};//新飞信电话号码
uchar SEND_SBUF[20] = {0};//串口发送字符串数组
uchar GsmRcvCnt = 0;
uchar SEND_NUM=0;//发送数组中字节数
uchar SEND=0;//字符发送个数
uint timer0_cnt = 0; //秒定时器
uint timer0_mcnt = 0;//毫秒定时器
uint sec_cnt = 0;
uint msec_cnt = 0;
uchar SBUF2_tmp = 0;//定义串口2缓存寄存器
uchar check=0;//校验符。F
uchar Address_Message=1;//新来的短信地址号码。
bit CleanGsmRcv_Enable=0;//置保护位。不准清GsmRcv。1:不可以清buf。0:可以清buf。
uchar Number_0D_0A_Message=0;//读短信0D 0A组合个数寄存器。
uint Key1_TimeCnt=0; //按键去抖动延时计数器
bit Key1_Lock=0; //按键触发后自锁的变量标志
uint Key2_TimeCnt=0; //按键去抖动延时计数器
bit Key2_Lock=0; //按键触发后自锁的变量标志
uint Key_Set_TimeCnt=0; //按键去抖动延时计数器
bit Key_Set_Lock=0; //按键触发后自锁的变量标志
uint Buzzer_Open_time=0;
uint Buzzer_Closed_time=0;
uchar Buzzer_Number=0;//蜂鸣器发声变量
uchar Buzzer_flag=0;//蜂鸣器鸣叫类型标志位
uchar SBUF_flag =0;//串口回复类型标志位。
bit Buzzer_condition=0;//蜂鸣器是在鸣叫还是静音
bit Buzzer_Doing=0;//判断蜂鸣器是否正在工作,如果没工作,就给参数赋值。
bit rev_start = 0; //标志位为1,开始接收
bit GsmRcv_dispose_flag = 0; //告诉主函数可以解析数据了。0:不能解析。1:可以解析。
bit GSM_RECEIVE_flag=0;//当单片机收到OK时,就将这个位置1.
void initialise();//系统初始化
void Timer0Init();//定时器初始化
char Uart1Init(char smod,char brtx12,uchar reload);//串口1初始化
char Uart2Init(char s2smod,char brtx12,uchar reload);//串口2初始化
void DelaySec(uint sec);//秒延时函数
void DelaymSec(uint msec);//豪秒延时函数
void CleanGsmRcv();//清除buf内容
void Buzzer_SCAN();//蜂鸣器
void KEY_SCAN();//按键扫描
void SBUF_flag_SCAN();//串口字符串处理函数
void main()//主函数函数在这里面运行
{
initialise();//系统初始化 GsmRcv_dispose_flag = 0;//串口数据处理标志。当处理完毕,就会将其置零。
DelaymSec(100);
DelaySec(1);
Boss_Tel_NO[1]=0x31;//主人电话号码
Boss_Tel_NO[2]=0x38;
Boss_Tel_NO[3]=0x31;
Boss_Tel_NO[4]=0x35;
Boss_Tel_NO[5]=0x38;
Boss_Tel_NO[6]=0x31;
Boss_Tel_NO[7]=0x31;
Boss_Tel_NO[8]=0x33;
Boss_Tel_NO[9]=0x32;
Boss_Tel_NO[10]=0x38;
Boss_Tel_NO[11]=0x30;
Boss_Feixin_NO[1]=0x32;//主人飞信号码
Boss_Feixin_NO[2]=0x37;
Boss_Feixin_NO[3]=0x33;
Boss_Feixin_NO[4]=0x37;
Boss_Feixin_NO[5]=0x38;
Boss_Feixin_NO[6]=0x32;
Boss_Feixin_NO[7]=0x34;
Boss_Feixin_NO[8]=0x31;
Boss_Feixin_NO[9]=0x39;
while(GSM_RECEIVE_flag==0)
{
strcpy(SEND_SBUF,AT_DATA_2);//将字符串AT赋给字符串SEND_SBUF
SEND_NUM = strlen(SEND_SBUF);//所发AT命令字节个数。
S2BUF = SEND_SBUF[0];
DelaySec(1);//延时1秒
}
GSM_RECEIVE_flag=0;
while(GSM_RECEIVE_flag==0)
{
strcpy(SEND_SBUF,AT_DATA_2);//将字符串AT赋给字符串SEND_SBUF
SEND_NUM = strlen(SEND_SBUF);//所发AT命令字节个数。
S2BUF = SEND_SBUF[0];
DelaySec(1);//延时1秒
}
GSM_RECEIVE_flag=0;
while(GSM_RECEIVE_flag==0)
{
strcpy(SEND_SBUF,AT_DATA_2);//将字符串AT赋给字符串SEND_SBUF
SEND_NUM = strlen(SEND_SBUF);//所发AT命令字节个数。
S2BUF = SEND_SBUF[0];
DelaySec(1);//延时1秒
}
GSM_RECEIVE_flag=0;
while(1)
{
if(!SBUF_flag==0)
{
GsmRcv_dispose_flag=0;//锁住,不再进入SBUF_flag_SCAN
switch(SBUF_flag)//判断SBUF_flag来判断应该如何再次通信
{
case 0://
SBUF_flag=0;
break;
case 1://
SBUF_flag=0;//将串口回复类型标志位置零。
SEND_SBUF[0]=0x41;//AT+CMGD=Address 删除所读短信
SEND_SBUF[1]=0x54;
SEND_SBUF[2]=0x2B;
SEND_SBUF[3]=0x43;
SEND_SBUF[4]=0x4D;
SEND_SBUF[5]=0x47;
SEND_SBUF[6]=0x44;
SEND_SBUF[7]=0x3D;
SEND_SBUF[8]=Address_Message;
SEND_SBUF[9]=0x0D;
SEND_SBUF[10]=0x0A;
SEND_NUM=10;
S2BUF = SEND_SBUF[0];//启动发送字符串命令
break;
case 2:// 读新来的短信 0x41,0x54,0x2B,0x43,0x4D,0x47,0x52,0x3D,0x31,0x0D,0x0A
SBUF_flag=0;//将串口回复类型标志位置零。
SEND_SBUF[0]=0x41; //AT+CMGR=1
SEND_SBUF[1]=0x54;
SEND_SBUF[2]=0x2B;
SEND_SBUF[3]=0x43;
SEND_SBUF[4]=0x4D;
SEND_SBUF[5]=0x47;
SEND_SBUF[6]=0x52;
SEND_SBUF[7]=0x3D;
SEND_SBUF[8]=Address_Message;
// SEND_SBUF[8]=0x31;
SEND_SBUF[9]=0x0D;
SEND_SBUF[10]=0x0A;
SEND_NUM=10;
S2BUF = SEND_SBUF[0];//启动发送字符串命令
// strcpy(SEND_SBUF,AT_DATA_1);//将字符串AT赋给字符串SEND_SBUF
// SEND_NUM = strlen(SEND_SBUF);//所发AT命令字节个数。
// S2BUF = SEND_SBUF[0];
break;
case 3://
SBUF_flag=0;//将串口回复类型标志位置零。
SEND_SBUF[0]=0x41; //AT+CMGR=1
SEND_SBUF[1]=0x54;
SEND_SBUF[2]=0x2B;
SEND_SBUF[3]=0x43;
SEND_SBUF[4]=0x4D;
SEND_SBUF[5]=0x47;
SEND_SBUF[6]=0x52;
SEND_SBUF[7]=0x3D;
SEND_SBUF[8]=0x31;
// SEND_SBUF[8]=0x31;
SEND_SBUF[9]=0x0D;
SEND_SBUF[10]=0x0A;
SEND_NUM=10;
S2BUF = SEND_SBUF[0];//启动发送字符串命令
// strcpy(SEND_SBUF,AT_DATA_1);//将字符串AT赋给字符串SEND_SBUF
// SEND_NUM = strlen(SEND_SBUF);//所发AT命令字节个数。
// S2BUF = SEND_SBUF[0];
break;
SBUF_flag=0;
break;
default:
SBUF_flag=0;
break;
}
}
}
}
void initialise()//系统初始化
{
// P2M0=0xF0;//设置P2口输入输出
// P2M1=0x07;//
// P1M0=0x01;//设置蜂鸣器为输出
// P1M1=0x00;//
Timer0Init();//定时器0初始化
Uart1Init(0,1,253);//初始化串口1,设置波特率115200
Uart2Init(0,1,253);//初始化串口2,设置波特率115200
IPH=0x10;
IP=0x02;
IP2H=0x01;
IP2=0x01;
LED2=1; //打开LED
LED3=1;//关闭LED
LED4=1;//关闭LED
KEY1=1; //关闭LED
KEY2=1;
KEY_Set=1;
Buzzer=1;
SIM_900A_STAR=1;
}
void Timer0Init()//初始化定时器0
{
TMOD=0x01; //设置定时器0为工作方式1。16位定时器/计数器,TL0,TH0全用。
TH0=0xFC ; //放入初值,11.0592M,1ms。计算方法:65535-(1ms/1.085μs)=64614=FC66H。
TL0=0x66; //上式中。1ms代表定时器周期。1.085μs=12/11.0592。其中11.0592代表的是晶振频率。
// 设置定时器0中断优先级(优先级1)
// IPH &= (~PT0H); //定时器0中断优先级控制高位 注意:IPH不可以位寻址
// PT0 = 1; //定时器0中断优先级控制低位 PT0H=0 PT0=1 定时器0中断为优先级1中断
EA=1; //开总中断
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
}
char Uart1Init(char smod,char brtx12,uchar reload)//串口1初始化函数 0,1,253
{
SCON = 0X50;//8位可变波特率,无奇偶位(SM0=0,SM1=1)方式1,使能串口接收模块(REN=1)
BRT = reload;//设置独立波特率发生器波特率
if(smod == 1)//备注:串口设置位独立波特率提供波特率,和串口2使用同一个波特率,也可以使用定时器1来提供波特率
{
PCON |= SMOD; //SMOD = 1;//波特率倍速位
}
else if(smod == 0)
{
PCON &= (~SMOD); //SMOD = 0;//取消波特率倍速位
}
else
{
return -1;//输出参数: -1 smod位错误,没有写入0/1
}
if(brtx12 == 1)
{
AUXR |= BRTx12;//BRTx12 = 1;1T模式
}
else if(brtx12 == 0)
{
AUXR &= (~BRTx12);//BRTx12 = 0;12T模式
}
else
{
return -2;//输出参数: -2 brtx12位错误,没有写入0/1
}
AUXR |= S1BRS;//串口设置为使用独立波特率发生器 S1BRS默认值为0。但是在系统头文件中是0x01。
AUXR |= BRTR;//开启波特率发生器 BRTR 默认值为0。但是在系统头文件中是0x10。
//设置串口1中断优先级
// if (UART1_PRIO & 0x02) //设置串口2的优先级为2 PSH=1 PS=0
// {
// IPH |= PSH; //置1;
// }
// else
// {
// IPH &= ~PSH; //置0;
// }
// if (UART1_PRIO & 0x01)
// {
// PS = 1; //置1;
// }
// else
// {
// PS = 0; //置0
// }
ES = 1; //开串口中断
EA = 1; //开总中断
return 0;
}
char Uart2Init(char s2smod,char brtx12,uchar reload)//串口2初始化函数函数
{
S2CON = 0X50;//8位可变波特率,无奇偶位
BRT = reload;//设置独立波特率发生器波特率 reload寄存器数值 0-255
//函数功能:初始化用于连接gprs的串口2 ,串口2只能设置为独立波特率提供波特率,并打开串口2中断和全局中断
if(s2smod == 1)
{
AUXR |= S2SMOD; //S2SMOD = 1;//波特率倍速位
}
else if(s2smod == 0)
{
AUXR &= (~S2SMOD); //S2SMOD = 0;//取消波特率倍速位
}
else
{
return -1;//输出参数: -1 s2smod位错误,没有写入0/1
}
if(brtx12 == 1)
{
AUXR |= BRTx12;//BRTx12 = 1;1T模式
}
else if(brtx12 == 0)
{
AUXR &= (~BRTx12);//BRTx12 = 0;12T模式
}
else
{
return -2;//输出参数: -2 brtx12位错误,没有写入0/1
}
AUXR |= S1BRS;//串口设置为使用独立波特率发生器 S1BRS默认值为0。但是在系统头文件中是0x01。
AUXR |= BRTR;//开启波特率发生器
// if (UART2_PRIO & 0x02)// 设置串口2的中断级别最高。为优先级3. 只要与的结果不为0,就表示为1.
// {
// IP2H |= PS2H; //置1;
// }
// else
// {
// IP2H &= ~PS2H; //置0;
// }
// if (UART2_PRIO & 0x01)
// {
// IP2 |= PS2; //置1
// }
// else
// {
// IP2 &= ~PS2; //置0;
// }
IE2 |= ES2;// ES2 = 1; //允许串口2中断
EA = 1; //开总中断
return 0;
}
void Uart1InterruptReceive() interrupt 4//串口1发送接收中断函数
{//备注:接收函数内部不可以放入其他的中断或者发送函数,否则影响接收数据
// ET0=0; //开定时器0中断
ES=0;//关串行口中断
if(TI) //如果是发送中断,则不做任何处理
{
if(SEND>=SEND_NUM)//数据串发送完毕
{
SEND=0;
SEND_NUM=0;
}
else
{
SEND++;
SBUF = SEND_SBUF[SEND]; //发送一个字节
}
TI = 0; //清除发送中断标志位
}
if(RI)
{
RI=0;//接收中断信号清零,表示将继续接收 SEND_NUM
}
ES=1;//开串行口中断
// ET0=1; //开定时器0中断
}
void Uart2InterruptReceive() interrupt 8//串口2发送接收中断函数
{
// ET0=0; //关闭定时器0中断
IE2 &= (~ES2);//关闭串口2中断//ES2 = 0;ES2的复位值是0.
if(S2CON & S2RI) //if(S2RI == 1),如果有中断产生。即S2RI为1.
{
S2CON &= (~S2RI);//将S2RI置0。
SBUF2_tmp = S2BUF;//将串口2缓存中的数据放到tmp中。&& (GsmRcvCnt==0) && (GsmRcv_dispose_flag == 0)
//开始接收到了完整的AT指令回复,完整的AT指令是以0x0a 0x0d开头的。故作此判断,在接收的过程中是否收到0x0a 0x0d
//如果数据包头出现的数据不是0D 0A,则说明这组数据错误,扔掉。
if ((SBUF2_tmp == 0x0D) &&(rev_start == 0) ) //如果收到字符0d而且串口寄存数组里还没有收到下一个0D数据。
{ //表明有数据进来了。则可以接收这串数据。置标志位。
rev_start = 1; //标志位为1,开始接收
GsmRcvCnt = 0; //将串口接收数组指针指到0位置
Number_0D_0A_Message=0;//将计数次数清零
}
if (rev_start == 1) //标志位为1,开始接收
{
GsmRcv[GsmRcvCnt] = SBUF2_tmp; //字符存到数组中 //接收缓存
// GsmRcvAt[GsmRcvCnt] = SBUF2_tmp; //字符存到数组中 //接收缓存
GsmRcvCnt++;
if ( (GsmRcvCnt>=3)&&(GsmRcv[GsmRcvCnt-2]==0x0D) && (GsmRcv[GsmRcvCnt-1] == 0x0A) ) //如果上一个字节是0d,而且串口寄存数组字节个数大于3。
{ //则说明不是第一个0d 0a。是一串数接收完了。
if((GsmRcv[2]==0x2B) && (GsmRcv[3]==0x43) && (GsmRcv[4]==0x4D) && (GsmRcv[5]==0x47) && (GsmRcv[6]==0x52))
{ //如果是+CMGR,说明正在读短信。需要将下面的数据全部接收后再清除GsmRcv。置保护位。
Number_0D_0A_Message++;
if(Number_0D_0A_Message==4) //说明收到了完整的短信息。
{
GsmRcv_dispose_flag = 1; //告诉主函数可以解析数据了
CleanGsmRcv_Enable=0;//置保护位。收完一串数据了。可以清GsmRcv。
Number_0D_0A_Message=0;//将计数次数清零
}
else
{
CleanGsmRcv_Enable=1;//置保护位。不准清GsmRcv。
GsmRcv_dispose_flag = 0; //告诉主函数不可以解析数据
}
}
else if((GsmRcv[2]==0x52) && (GsmRcv[3]==0x49) && (GsmRcv[4]==0x4E) && (GsmRcv[5]==0x47))
{ //如果是RING,说明是来电电话。需要将下面的数据全部接收后再清除GsmRcv。置保护位。
Number_0D_0A_Message++;
if(Number_0D_0A_Message==3) //说明收到了完整的来电电话号码信息。
{
GsmRcv_dispose_flag = 1; //告诉主函数可以解析数据了
CleanGsmRcv_Enable=0;//置保护位。收完一串数据了。可以清GsmRcv。
Number_0D_0A_Message=0;//将计数次数清零
}
else
{
CleanGsmRcv_Enable=1;//置保护位。不准清GsmRcv。
GsmRcv_dispose_flag = 0; //告诉主函数不可以解析数据
}
}
else
{
Number_0D_0A_Message=0;//将计数次数清零
CleanGsmRcv_Enable=0;//置保护位。收完一串数据了。可以清GsmRcv。
GsmRcv_dispose_flag = 1; //告诉主函数可以解析数据了
}
}
}//收到了完整的AT指令,完整的AT指令是以0x0a 0x0d结尾的。故作此判断,在接收的过程中是否收到0x0a 0x0d
}
if(S2CON & S2TI) //if(S2TI == 1),如果有中断产生。即S2TI为1.
{
S2CON &= ~S2TI; //将S2TI置0。清除发送中断标志位。
if(SEND>=SEND_NUM)//数据串发送完毕
{
SEND=0;
SEND_NUM=0;
}
else
{
SEND++;
S2BUF = SEND_SBUF[SEND]; //发送一个字节
}
}
// ET0=1; //打开定时器0中断
IE2 |= ES2;//ES2 = 1;
}
void timer0() interrupt 1//定时器0中断,每1ms执行一次中断,中断内部重新赋值
{
TH0=0xFC;//对定时器重装初值,1毫秒。
TL0=0x66;
timer0_cnt++;
if(timer0_cnt == 1000)//是否到了1秒钟
{
timer0_cnt = 0;
sec_cnt++;
LED2=~LED2;
}
timer0_mcnt++;
if(timer0_mcnt == 1)//是否到了10毫秒钟
{
timer0_mcnt = 0;
msec_cnt++;
}
KEY_SCAN();//按键扫描
Buzzer_SCAN();//蜂鸣器扫描
SBUF_flag_SCAN();//串口字符串处理函数
}
void DelaySec(uint sec)//定时函数,单位是秒。
{
sec_cnt = 0;
while(sec_cnt < sec);
}
void DelaymSec(uint msec)//定时函数,单位是毫秒。
{
msec_cnt = 0;
while(msec_cnt < msec);
}
void CleanGsmRcv()//清除GPRS接收缓冲数据初始化函数
{
uchar i = 0;
for(i=0; i<=MAXRCV; i++)
{
GsmRcv[i] = 0;
}
GsmRcvCnt = 0;//将GsmRcv[]数据清除,并且使缓冲指针移到第一位。
}
void KEY_SCAN()//按键扫描
{
/****************************************************************************/
if(KEY1==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
{
Key1_Lock=0; //按键自锁标志清零
Key1_TimeCnt=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。
}
else if(Key1_Lock==0&&KEY1==0)//有按键按下,且是第一次被按下
{
Key1_TimeCnt++; //延时计数器
if(Key1_TimeCnt>=20)
{
Buzzer_flag=1;
Key1_TimeCnt=0;//清计数器
Key1_Lock=1; //自锁按键置位,避免一直触发。当置1后,程序就再也不会在这个循环里跑了。
LED3=~LED3;
}
}
/****************************************************************************/
if(KEY2==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
{
Key2_Lock=0; //按键自锁标志清零
Key2_TimeCnt=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。
}
else if(Key2_Lock==0&&KEY2==0)//有按键按下,且是第一次被按下
{
Key2_TimeCnt++; //延时计数器
if(Key2_TimeCnt>=20)
{
SBUF_flag=3;
Buzzer_flag=2;
Key2_TimeCnt=0;//清计数器
Key2_Lock=1; //自锁按键置位,避免一直触发。当置1后,程序就再也不会在这个循环里跑了。
LED4=~LED4;
}
}
/****************************************************************************/
if(KEY_Set==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
{
Key_Set_Lock=0; //按键自锁标志清零
Key_Set_TimeCnt=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。
SIM_900A_STAR=1;
}
else if(Key_Set_Lock==0&&KEY_Set==0)//有按键按下,且是第一次被按下
{
Key_Set_TimeCnt++; //延时计数器
if(Key_Set_TimeCnt>=20)
{
Buzzer_flag=3;
Key_Set_TimeCnt=0;//清计数器
Key_Set_Lock=1; //自锁按键置位,避免一直触发。当置1后,程序就再也不会在这个循环里跑了。
SIM_900A_STAR=0;//SIM900开机
}
}
/****************************************************************************/
}
void Buzzer_SCAN()//蜂鸣器
{
switch(Buzzer_flag)//判断Buzzer_flag来判断应该如何鸣叫
{
case 0://蜂鸣器静音
Buzzer=1;//静音
Buzzer_condition=0;//蜂鸣器是在响还是没响
Buzzer_Doing=0;//蜂鸣器不在工作状态
Buzzer_flag=0;//选择叫声标志位清零
Buzzer_Number=0;//响次数清零
Buzzer_Open_time=0;//响时间清零
Buzzer_Closed_time=0;//不响时间清0
break;
case 1://蜂鸣器响5声
if(Buzzer_Doing==0)//判断蜂鸣器是否正在工作,如果没工作,就给参数赋值。
{
Buzzer_Number=4;//响4声
Buzzer_Open_time=30;//响50毫秒
Buzzer_Closed_time=30;//不响50毫秒
Buzzer_Doing=1;//重新赋值,不再进入此循环。
}
else
{
if( (Buzzer_Number>0)&&(Buzzer_Doing==1) )//没有达到响声次数
{
if(Buzzer_condition)//如果正在响,就进入响延时状态1
{
Buzzer_Open_time--;
if(Buzzer_Open_time>0)
{
Buzzer=0;//鸣叫
}
else
{
Buzzer_condition=!Buzzer_condition;//翻转状态为静音
Buzzer_Open_time=30;//计数器重新赋值
Buzzer_Number--;//叫声次数减1
// SBUF = Buzzer_Number;
}
}
else//如果没在响,就进入不响延时状态0
{
Buzzer_Closed_time--;
if(Buzzer_Closed_time>0)
{
Buzzer=1;//静音
}
else
{
Buzzer_condition=!Buzzer_condition;//翻转状态为鸣叫
Buzzer_Closed_time=30;//计数器重新赋值
}
}
}
else //鸣叫完毕,除去标志位。
{
Buzzer=1;//静音
Buzzer_condition=0;//蜂鸣器是在响还是没响
Buzzer_Doing=0;//蜂鸣器不在工作状态
Buzzer_flag=0;//选择叫声标志位清零
Buzzer_Number=0;//响次数清零
Buzzer_Open_time=0;//响时间清零
Buzzer_Closed_time=0;//不响时间清零
}
}
break;
case 2://蜂鸣器响2声
if(Buzzer_Doing==0)//判断蜂鸣器是否正在工作,如果没工作,就给参数赋值。
{
Buzzer_Number=4;//响4声
Buzzer_Open_time=20;//响50毫秒
Buzzer_Closed_time=20;//不响50毫秒
Buzzer_Doing=1;//重新赋值,不再进入此循环。
}
else
{
if( (Buzzer_Number>0)&&(Buzzer_Doing==1) )//没有达到响声次数
{
if(Buzzer_condition)//如果正在响,就进入响延时状态1
{
Buzzer_Open_time--;
if(Buzzer_Open_time>0)
{
Buzzer=0;//鸣叫
}
else
{
Buzzer_condition=!Buzzer_condition;//翻转状态为静音
Buzzer_Open_time=20;//计数器重新赋值
Buzzer_Number--;//叫声次数减1
// SBUF = Buzzer_Number;
}
}
else//如果没在响,就进入不响延时状态0
{
Buzzer_Closed_time--;
if(Buzzer_Closed_time>0)
{
Buzzer=1;//静音
}
else
{
Buzzer_condition=!Buzzer_condition;//翻转状态为鸣叫
Buzzer_Closed_time=20;//计数器重新赋值
}
}
}
else //鸣叫完毕,除去标志位。
{
Buzzer=1;//静音
Buzzer_condition=0;//蜂鸣器是在响还是没响
Buzzer_Doing=0;//蜂鸣器不在工作状态
Buzzer_flag=0;//选择叫声标志位清零
Buzzer_Number=0;//响次数清零
Buzzer_Open_time=0;//响时间清零
Buzzer_Closed_time=0;//不响时间清零
}
}
break;
case 3://蜂鸣器响2声
if(Buzzer_Doing==0)//判断蜂鸣器是否正在工作,如果没工作,就给参数赋值。
{
Buzzer_Number=4;//响4声
Buzzer_Open_time=10;//响50毫秒
Buzzer_Closed_time=30;//不响50毫秒
Buzzer_Doing=1;//重新赋值,不再进入此循环。
}
else
{
if(Buzzer_Number>0)//没有达到响声次数
{
if(Buzzer_condition)//如果正在响,就进入响延时状态1
{
Buzzer_Open_time--;
if(Buzzer_Open_time>0)
{
Buzzer=0;//鸣叫
}
else
{
Buzzer_condition=!Buzzer_condition;//翻转状态为静音
Buzzer_Open_time=10;//计数器重新赋值
Buzzer_Number--;//叫声次数减1
}
}
else//如果没在响,就进入不响延时状态0
{
Buzzer_Closed_time--;
if(Buzzer_Closed_time>0)
{
Buzzer=1;//静音
}
else
{
Buzzer_condition=!Buzzer_condition;//翻转状态为鸣叫
Buzzer_Closed_time=30;//计数器重新赋值
}
}
}
else//鸣叫完毕,除去标志位。
{
Buzzer=1;//静音
Buzzer_condition=0;//蜂鸣器是在响还是没响
Buzzer_Doing=0;//蜂鸣器不在工作状态
Buzzer_flag=0;//选择叫声标志位清零
Buzzer_Number=0;//响次数清零
Buzzer_Open_time=0;//响时间清零
Buzzer_Closed_time=0;//不响时间清零
}
}
break;
default:
Buzzer=1;//静音
Buzzer_flag=0;
break;
}
}
void SBUF_flag_SCAN()//串口字符串处理函数。用于触发各种消息。
{
if(GsmRcv_dispose_flag)//判断是否可以解析串口字符串中的数据
{
if( (GsmRcv[2]==0x4F) && (GsmRcv[3]==0x4B) )//检测到:OK
{
// SBUF_flag=3;
GSM_RECEIVE_flag=1;//收到OK就将这个位置1.
Buzzer_flag=2;
}
else if( (GsmRcv[2]==0x2B) && (GsmRcv[3]==0x43) && (GsmRcv[4]==0x4D) && (GsmRcv[5]==0x54) && (GsmRcv[6]==0x49))//检测到:+CMTI
{ //检测到有短信
Address_Message=GsmRcv[14]; //读取短信地址。
SBUF_flag=2;
// Buzzer_flag=2;
}
// else if( (GsmRcv[2]==0x52) && (GsmRcv[3]==0x49) && (GsmRcv[4]==0x4E) && (GsmRcv[5]==0x47) )//检测到:RING
// { //检测到有电话
// SBUF_flag=3;
// Buzzer_flag=3;
// }
else if( (GsmRcv[2]==0x45) && (GsmRcv[3]==0x52) && (GsmRcv[4]==0x52) && (GsmRcv[5]==0x4F)&& (GsmRcv[6]==0x52) )//检测到:ERROR
{
SBUF_flag=4;
}
else if( (GsmRcv[2]==0x2B) && (GsmRcv[3]==0x43) && (GsmRcv[4]==0x4D) && (GsmRcv[5]==0x47) && (GsmRcv[6]==0x52) )
{//读短信,判断。特定位置收到+CMGR
if( (GsmRcv[42]==0x36) && (GsmRcv[43]==0x38) )//如果是68开头的号码。则为短信。
{//判断短信
New_Tel_NO[1]=GsmRcv[45];//新来电电话号码
New_Tel_NO[2]=GsmRcv[44];
New_Tel_NO[3]=GsmRcv[47];
New_Tel_NO[4]=GsmRcv[46];
New_Tel_NO[5]=GsmRcv[49];
New_Tel_NO[6]=GsmRcv[48];
New_Tel_NO[7]=GsmRcv[51];
New_Tel_NO[8]=GsmRcv[50];
New_Tel_NO[9]=GsmRcv[53];
New_Tel_NO[10]=GsmRcv[52];
New_Tel_NO[11]=GsmRcv[55];
if(!strcmp(New_Tel_NO,Boss_Tel_NO))//电话号码与主人电话号码符号。进入下面括号内继续判断。
{ //此句代表New_Tel_NOBoss_Tel_NO只要和Boss_Tel_NO一样,则进入到下面大括号里去执行命令。
LED4=!LED4;
}
}
if( (GsmRcv[42]==0x32) && (GsmRcv[43]==0x31) )//如果是21开头的号码。则为飞信。
{//判断飞信
New_Feixin_NO[1]=GsmRcv[46];//新来电电话号码
New_Feixin_NO[2]=GsmRcv[49];
New_Feixin_NO[3]=GsmRcv[48];
New_Feixin_NO[4]=GsmRcv[51];
New_Feixin_NO[5]=GsmRcv[50];
New_Feixin_NO[6]=GsmRcv[53];
New_Feixin_NO[7]=GsmRcv[52];
New_Feixin_NO[8]=GsmRcv[55];
New_Feixin_NO[9]=GsmRcv[54];
if(!strcmp(New_Feixin_NO,Boss_Feixin_NO))// 飞信号码与主人飞信号码符号。进入下面括号内继续判断。
{ //此句代表New_Feixin_NO只要和Boss_Feixin_NO一样,则进入到下面大括号里去执行命令。
LED3=!LED3;
}
}
else//否则为广告。
{
}
SBUF_flag=1;
}
else if( (GsmRcv[11]==0x43) && (GsmRcv[12]==0x4C) && (GsmRcv[13]==0x49) )//检测到CLIP。说明有电话打进来。
{//读电话号码,判断。Boss_Tel_NO1
New_Tel_NO[1]=GsmRcv[18];//新来电电话号码
New_Tel_NO[2]=GsmRcv[19];
New_Tel_NO[3]=GsmRcv[20];
New_Tel_NO[4]=GsmRcv[21];
New_Tel_NO[5]=GsmRcv[22];
New_Tel_NO[6]=GsmRcv[23];
New_Tel_NO[7]=GsmRcv[24];
New_Tel_NO[8]=GsmRcv[25];
New_Tel_NO[9]=GsmRcv[26];
New_Tel_NO[10]=GsmRcv[27];
New_Tel_NO[11]=GsmRcv[28];
if(!strcmp(New_Tel_NO,Boss_Tel_NO))//当数组New_Tel_NOBoss_Tel_NO与Boss_Tel_NO数组相等,则返回0.此句代表New_Tel_NOBoss_Tel_NO只要和Boss_Tel_NO一样,则进入到下面大括号里去执行命令。
{
Buzzer_flag=2;
LED3=!LED3;
LED4=!LED4;
}
}
else
{
}
if(CleanGsmRcv_Enable==0)//如果可以清,就清除。
{
CleanGsmRcv(); //清除串口数组的数据
}
GsmRcv_dispose_flag=0;
rev_start = 0; //可以接收下一组数据了
}
}