为什么51CTO的代码域,总是对不齐,明明在编辑器整理的好了。
为何要实施这个项目?
一般小区楼下,每幢都会有一个门禁系统,
可以使用钥匙打开门禁,
有的可以使用刷卡打开门禁,
有的可以使用密码打开门禁,
但是,长期下来,因为小区人多,锁的钥匙孔会被捅坏,物业修起来也很怠慢
使用密码按键解锁门禁,按键也会失灵
每家都会安装一个【楼宇对讲器】,用来与楼下人对话,或者可以从视频看出,是哪位亲朋,并且可以门禁解锁。
目标:
使用智能家居,嵌入楼宇对讲机,模拟开门按键,完成开门动作。
适用对象:
家里人多,拥有门禁的钥匙不够用的家庭
出入门禁不想带钥匙的人
大冬天,懒得拿冰冷的钥匙开门的人
物业门禁钥匙,密码不好使的人
使用方法:
1,给模块插入一张有来电显示功能的移动/联通SIM卡,上电初始化,一个短的嘀的一声提示,初始化完成。
2,在任何时候任何地点,手机呼叫SIM900A GSM通信模块的号码,门禁解锁。
【小区楼幢-门禁外观】钥匙+键盘+刷卡+摄像头
【小区楼幢-门禁外观】键盘+摄像头+刷卡
【小区楼幢-门禁外观】 钥匙
室内【楼宇对讲机】外观
室内【楼宇对讲机】内部图
室内【楼宇对讲机】结合单片机
【SIM900A模块】结合单片机
【单片机串口通信 波特率计算器】
Ver2.0版本程序
C51 SIM900A 判断来电身份,蜂鸣器响起 远程控制
工程名 :手机呼叫SIM900A,门禁解锁
1 先用USB转TTL模块测试模块好用,发送AT,波特率到9600同步
2 STC12C4052AD单片机晶振 11.0592MHz,12M不可以用
版本号:V1.0
手机呼叫SIM900A的号码,蜂鸣器亮500MS;
具体实现看程序,注释我写的非常详细了
/****************************** 工程名 :手机呼叫SIM900A,门禁解锁 1 先用USB转TTL模块测试模块好用,发送AT,波特率到9600同步 2 51单片机晶振 11.0592MHz,12M不可以用 手机呼叫SIM900A的号码,LED亮500MS; *******************************/ #include "string.h" #include "STC12C2052AD.h" #define cache_max 200 //串口接收缓存长度 xdata unsigned char uart_cache[cache_max]; // xdata 把变量存在flash中,而不存在RAM中 //code 定义的数据要放在ROM里面,写入后就不能再更改 bdata unsigned char Flag; //定时器标志位 bdata 把变量定义为可拆成8位寻址 sbit Timer_start =Flag^0; //延时计数功能开关 sbit RUNING = P3^7; //SIM900A运行指示灯,1秒闪烁一次 sbit unlock = P1^7; //解锁 unsigned char code *ring="CLIP"; //来电标记 unsigned char code *phone1="1336218****"; //管理员1的手机号 unsigned char code *phone2="1395804****"; //管理员2的手机号 unsigned char code *phone3="1776715****"; //管理员3的手机号 unsigned char Times=0; // 定时器中断次数累加 unsigned char First_Int = 0; // 串口数组字符索引 unsigned char delay=0; //中断定时器,实际数据delay*50次 void SendData(unsigned char dat){ // 发一个8位数据到串口SBUF ES=0; SBUF=dat; while(TI!=1); TI=0; ES=1; } void SendString(unsigned char *s){ // 发多个8位数据到串口SBUF while(*s) SendData(*s++); } void SendLR(void) { // 发回车换行 SendString("\r\n"); } void DELAY_MS (unsigned int a){ // 延时 unsigned int i; while ( --a != 0 ) for (i=0;i<=600;i++); } void Uart1Init(void) { //[email protected] PCON &= 0x7F; //波特率不倍速 SCON = 0x50; //8位数据,可变波特率 AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T AUXR &= 0xFE; //串口1选择定时器1为波特率发生器 TMOD &= 0x0F; //清除定时器1模式位 TMOD |= 0x20; //设定定时器1为8位自动重装方式 TL1 = 0xFD; //设定定时初值 TH1 = 0xFD; //设定定时器重装值 ET1 = 0; //禁止定时器1中断 TR1 = 1; //启动定时器1 ES=1; //开串口中断 } void Uart1() interrupt 4{ uart_cache[First_Int] = SBUF; //将接收到的字符串存到缓存中 First_Int++; //缓存指针向后移动 if(First_Int > cache_max) //如果缓存满,将缓存指针指向缓存的首地址 First_Int = 0; //数组索引,归位 RI = 0; //清除RI位 } void Timer0Init(void) { //20毫秒@11.0592MHz AUXR &= 0x7F; //定时器时钟12T模式 TMOD &= 0xF0; TMOD |= 0x01; //设置定时器模式,16位定时器 TL0 = 0x00; //设置定时器初值 TH0 = 0xB8; //设置定时器初值 TF0 = 0; //清TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; //使能定时器0中断 EA=1; //开总中断 } void Timer0_ISR() interrupt 1{ //最高级别中断服务程序 static unsigned char Time_count=0; // 定时器计数器 static全局生命周期 TR0=0; //关定时器 TL0 = 0x00; //重设定时器初值 TH0 = 0xB8; //重设定时器初值 Time_count++; if(Time_count>=50) { Time_count = 0; RUNING =~RUNING; //SIM900A运行指示灯,1秒闪烁一次 } if(Timer_start) Times++; //如果收到允许定时,开始计时 if(Times > (50*delay)){ //如果Times 到达设定时间 Timer_start = 0; Times = 0; // 全部变量Times,通知程序 计时时间已到 } TR0=1; //开定时器 } void CLR_Buf1(void){ unsigned int k; for(k=0;k<cache_max;k++) //将缓存内容清零 uart_cache[k] = 0x00; First_Int = 0; //接收字符串的起始存储位置 } void Send_Command(unsigned char *b,unsigned char *a,unsigned char wait_time){ unsigned char i; unsigned char *c; c = b; //保存字符串地址到c CLR_Buf1(); i = 0; while(i == 0) { if(strstr(uart_cache,a)==NULL) { //查找需要应答的字符 if(Timer_start == 0){ b = c; //将字符串地址给b for (b; *b!='\0';b++) SendData(*b); SendLR(); Times = 0; delay = wait_time; Timer_start = 1; // 开启定时器, } } else{ i = 1; Timer_start = 0; } } CLR_Buf1(); } void Unlock(void) {//执行函数,会有一个持续1秒低电平的动作,然后电平拉高 unlock = 0; DELAY_MS(200); unlock = 1; } void Wait_CREG(void) { //等待模块注册成功 unsigned char i; unsigned char k; i = 0; CLR_Buf1(); while(i == 0) { CLR_Buf1(); SendString("AT+CREG?"); //查询模块网络注册状态 SendLR(); DELAY_MS(1000); for(k=0;k<cache_max;k++) { if(uart_cache[k] == ':') { if((uart_cache[k+4] == '1')||(uart_cache[k+4] == '5')){ //表明网络注册成功 i = 1; break; } } } } } void Check_Ring(void) { //检查是否有新信息,并执行信息内容指令 if(strstr(uart_cache,ring)!=NULL) { //若缓存字符串中含有来电标记 DELAY_MS(100); //等待数据全部接收完成 if((strstr(uart_cache,phone1)!=NULL)||(strstr(uart_cache,phone2)!=NULL)||(strstr(uart_cache,phone3)!=NULL)) Unlock(); //如果管理员来电,就解锁 CLR_Buf1(); // 清空SBUF缓存 } } void main(void){ Timer0Init(); //初始化定时器0 Uart1Init(); //初始化串口9600 Send_Command("AT","OK",3); //波特率同步 Send_Command("ATE0","OK",3); //取消回显 Send_Command("AT+CLIP=1","OK",3); //开启来电显示 Wait_CREG(); //查询等待模块注册成功 while(1){ Check_Ring(); } }
编译结果:0错误,0警告
Ver3.0版本程序
/****************************** 工程名 :手机呼叫SIM900A,门禁解锁 1 先用USB转TTL模块测试模块好用,发送AT,波特率到9600同步 2 STC12C2052AD单片机,晶振 11.0592MHz,12M不可以用 软件功能: 1,联网成功,一个短的嘀的一声提示 2,手机呼叫SIM900A的号码,一个长的嘀的一声提示,并完成门禁解锁动作 *******************************/ #include "string.h" #include "STC12C2052AD.h" #define cache_max 100 //串口接收缓存长度 // xdata 把变量存在flash中,而不存在RAM中 //code 定义的数据要放在ROM里面,写入后就不能再更改 // Timer_start =Flag^0 定时器标志位 bdata 把变量定义为可拆成8位寻址 xdata unsigned char uart_cache[cache_max]; bdata unsigned char Flag; sbit beep = P1^3; //蜂鸣器 sbit control = P1^4; //解锁控制 sbit power = P1^7; //运行指示灯 unsigned char code *ring="CLIP"; //SIM900A的来电标记 unsigned char code *phone1="1395719・・・・"; //授权手机号1 unsigned char code *phone2="1395804・・・・"; //授权手机号2 unsigned char code *phone3="1358812・・・・"; //授权手机号3 sbit Timer_start =Flag^0; //计时器,功能开关 unsigned char Times=0; // 定时计数器 unsigned char First_Int = 0; // 串口数组字符索引 unsigned char delay=0; //中断定时器,实际延时delay*50次 void SendData(unsigned char dat){ // 发一个英文8位数据到串口SBUF ES=0; SBUF=dat; while(TI!=1); TI=0; ES=1; } void SendString(unsigned char *s){ // 发英文字符到串口SBUF while(*s) SendData(*s++); } void SendLR(void) { // 发回车换行 SendString("\r\n"); } void DELAY_MS (unsigned int a){ // 延时 unsigned int i; while ( --a != 0 ) for (i=0;i<=600;i++); } void Beep_Ring(unsigned int a) {//发出嘀的一声,或者解锁 if(a==1){ beep = control=0; DELAY_MS(500); beep = control=1; } if(a==2){ beep=0; DELAY_MS(100); beep=1; } } void Uart1Init(void) { //[email protected] PCON &= 0x7F; //波特率不倍速 SCON = 0x50; //8位数据,可变波特率 AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T AUXR &= 0xFE; //串口1选择定时器1为波特率发生器 TMOD &= 0x0F; //清除定时器1模式位 TMOD |= 0x20; //设定定时器1为8位自动重装方式 TL1 = 0xFD; //设定定时初值 TH1 = 0xFD; //设定定时器重装值 ET1 = 0; //禁止定时器1中断 TR1 = 1; //启动定时器1 ES=1; //开串口中断 } void Timer0Init(void) { //20毫秒@11.0592MHz AUXR &= 0x7F; //定时器时钟12T模式 TMOD &= 0xF0; TMOD |= 0x01; //设置定时器模式,16位定时器 TL0 = 0x00; //设置定时器初值 TH0 = 0xB8; //设置定时器初值 TF0 = 0; //清TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; //使能定时器0中断 EA=1; //开总中断 } void CLR_Buf1(void){ unsigned int k; for(k=0;k<cache_max;k++) //将缓存内容清零 uart_cache[k] = 0x00; First_Int = 0; //接收字符串的起始存储位置 } void Send_Command(unsigned char *command,unsigned char *ack,unsigned char wait_time){ unsigned char *pointer; pointer = command; //保存字符串command的首地址到c CLR_Buf1(); //清除串口缓存 while(1) { if(!strstr(uart_cache,ack)) { //查找需要应答的字符 if(Timer_start == 0){ command = pointer; //将字符串地址给b for (command; *command!='\0';command++) SendData(*command); SendLR(); Times = 0; delay = wait_time; Timer_start = 1; // 开启定时器 } } else{ Timer_start = 0; //关闭定时器 break; } } CLR_Buf1(); //清除串口缓存 } void Wait_CREG(void) { //等待模块注册成功 unsigned char i,k; i = 0; // CLR_Buf1(); 想想本处串口缓存该不该注释 while(i == 0) { CLR_Buf1(); SendString("AT+CREG?"); //查询模块网络注册状态 SendLR(); DELAY_MS(1000); for(k=0;k<cache_max;k++) { if(uart_cache[k] == ':') { if((uart_cache[k+4] == '1')||(uart_cache[k+4] == '5')){//表明网络注册成功 i = 1; CLR_Buf1(); } } } } } void Check_Ring(void) { if(strstr(uart_cache,ring)!=NULL) { //检测是否有来电标记 DELAY_MS(100); //等待数据全部接收完成 if((strstr(uart_cache,phone1))|| //注释要写得清晰明了 (strstr(uart_cache,phone2))|| (strstr(uart_cache,phone3))) Beep_Ring(1); //符合权限,就解锁 CLR_Buf1(); // 清空SBUF缓存 } } void SIM900aInit(void){ Send_Command("AT","OK",3); //波特率同步 Send_Command("AT+CLIP=1","OK",3); //开启来电显示 Wait_CREG(); //查询等待模块注册成功 Beep_Ring(2); //联网成功提示音 } //主函数 void main(void){ Timer0Init(); //初始化定时器0 Uart1Init(); //初始化串口9600 SIM900aInit(); //初始化SIM900A模块 while(1){ Check_Ring(); } } //4级串口中断函数 void Uart1() interrupt 4{ uart_cache[First_Int] = SBUF; //将接收到的字符串存到缓存中 First_Int++; //缓存指针向后移动 if(First_Int > cache_max) //如果缓存满,将缓存指针指向缓存的首地址 First_Int = 0; //数组索引,归位 RI = 0; //清除RI位 } //1级最高级别,定时器中断函数 void Timer0_ISR() interrupt 1{ //最高级别中断服务程序 static unsigned char Time_count=0; // 定时器计数器 static全局生命周期 TR0=0; //关定时器 TL0 = 0x00; //重设定时器初值 TH0 = 0xB8; //重设定时器初值 Time_count++; if(Time_count>=50) { Time_count = 0; power=~power; //SIM900A运行指示灯,1秒闪烁一次 } if(Timer_start) Times++; //如果收到允许定时,开始计时 if(Times > (50*delay)){ //如果Times 到达设定时间 Timer_start = 0; // 完成定时,关闭定时功能 Times = 0; // 完成定时,清空定时计数器 } TR0=1; //开定时器 }
Ver4.0版本,加入自动挂机,关闭睡眠
/****************************** 工程名 :手机呼叫SIM900A,门禁解锁 1 先用USB转TTL模块测试模块好用,发送AT,波特率到9600同步 2 STC12C2052AD单片机,晶振 11.0592MHz,12M不可以用 软件功能: 1,2015.12.10 联网成功,一个短的嘀的一声提示 2,2015.12.17 手机呼叫SIM900A的号码,一个长嘀的一声提示,并完成门禁解锁动作 3,2015.12.22 响铃后,自动挂断回应对方 *******************************/ #include "string.h" #include "STC12C2052AD.h" #define cache_max 100 //串口接收缓存长度 // xdata 把变量存在flash中,而不存在RAM中 //code 定义的数据要放在ROM里面,写入后就不能再更改 // Timer_start =Flag^0 定时器标志位 bdata 把变量定义为可拆成8位寻址 xdata unsigned char uart_cache[cache_max]; bdata unsigned char Flag; sbit beep = P1^3; //蜂鸣器 sbit control = P1^4; //解锁控制 sbit power = P1^7; //运行指示灯 unsigned char code *ring="CLIP"; //SIM900A的来电标记 unsigned char code *phone1="1395719・・・・"; //授权手机号1 unsigned char code *phone2="1395804・・・・"; //授权手机号2 unsigned char code *phone3="1358812・・・・"; //授权手机号3 sbit Timer_start =Flag^0; //计时器,功能开关 unsigned char Times=0; // 定时计数器 unsigned char First_Int = 0; // 串口数组字符“指针” unsigned char delay=0; //中断定时器,实际延时delay*50次 void SendData(unsigned char dat){ // 发一个英文8位数据到串口SBUF ES=0; SBUF=dat; while(TI!=1); TI=0; ES=1; } void SendString(unsigned char *s){ // 发英文字符到串口SBUF while(*s) SendData(*s++); } void SendLR(void) { // 发回车换行 SendString("\r\n"); } void DELAY_MS (unsigned int a){ // 延时 unsigned int i; while ( --a != 0 ) for (i=0;i<=600;i++); } void Uart1Init(void) { //定时器1,[email protected] PCON &= 0x7F; //波特率不倍速 SCON = 0x50; //8位数据,可变波特率 AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T AUXR &= 0xFE; //串口1选择定时器1为波特率发生器 TMOD &= 0x0F; //清除定时器1模式位 TMOD |= 0x20; //设定定时器1为8位自动重装方式 TL1 = 0xFD; //设定定时初值 TH1 = 0xFD; //设定定时器重装值 ET1 = 0; //禁止定时器1中断 TR1 = 1; //启动定时器1 ES=1; //开串口中断 } void Timer0Init(void) { //20毫秒@11.0592MHz AUXR &= 0x7F; //定时器0时钟12T模式 TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式,16位定时器,非自动重载模式 TL0 = 0x00; //设置定时器初值 TH0 = 0xB8; //设置定时器初值 TF0 = 0; //清TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; //使能定时器0中断 EA=1; //开总中断 } void CLR_Buf1(void){ unsigned int k; for(k=0;k<cache_max;k++) //将缓存内容清零 uart_cache[k] = 0x00; First_Int = 0; //接收字符串的起始存储位置 } void Send_Command(unsigned char *command,unsigned char *ack,unsigned char wait_time){ unsigned char *pointer; pointer = command; //保存字符串command的首地址到c CLR_Buf1(); //清除串口缓存 while(1) { if(!strstr(uart_cache,ack)) { //查找需要应答的字符 if(Timer_start == 0){ command = pointer; //将字符串地址给b for (command; *command!='\0';command++) SendData(*command); SendLR(); Times = 0; delay = wait_time; Timer_start = 1; // 开启定时器 } } else{ Timer_start = 0; //关闭定时器 break; } } CLR_Buf1(); //清除串口缓存 } void Wait_CREG(void) { //等待模块注册成功 unsigned char i,k; i = 0; CLR_Buf1(); //想想本处串口缓存该不该注释 while(i == 0) { CLR_Buf1(); SendString("AT+CREG?"); //查询模块网络注册状态 SendLR(); DELAY_MS(1000); for(k=0;k<cache_max;k++) { if(uart_cache[k] == ':') { if((uart_cache[k+4] == '1')||(uart_cache[k+4] == '5')){//表明网络注册成功 i = 1; CLR_Buf1(); } } } } } void Beep_Ring(unsigned int a) { //发出嘀的一声,或者解锁 if(a==1){ beep = control=0; DELAY_MS(500); beep = control=1; Send_Command("ATH","OK",2); } if(a==2){ beep=0; DELAY_MS(100); beep=1; } } void Check_Ring(void) { if(strstr(uart_cache,ring)){ //检测是否有来电标记 DELAY_MS(100); //等待数据全部接收完成 if((strstr(uart_cache,phone1))||(strstr(uart_cache,phone2))||(strstr(uart_cache,phone3))) Beep_Ring(1); //符合权限,就解锁 CLR_Buf1(); // 清空SBUF缓存 } } void SIM900aInit(void){ Send_Command("AT","OK",3); //波特率同步 Send_Command("AT+CLIP=1","OK",3); //开启来电显示 Send_Command("AT+CSCLK=0","OK",3); //关闭SIM900A睡眠 Wait_CREG(); //查询等待模块注册成功 Beep_Ring(2); //联网成功提示音 } //主函数 void main(void){ Timer0Init(); //初始化定时器0 Uart1Init(); //初始化串口9600 SIM900aInit(); //初始化SIM900A模块 while(1){ Check_Ring(); } } //4级串口中断函数 void Uart1() interrupt 4{ uart_cache[First_Int] = SBUF; //将接收到的单个字符存到缓存中 First_Int++; //缓存指针向后移动 if(First_Int > cache_max) //如果缓存满,将缓存指针指向缓存的首地址 First_Int = 0; //数组索引,归位 RI = 0; //清除RI位 } //1级最高级别,定时器中断函数 void Timer0_ISR() interrupt 1{ //最高级别中断服务程序 static unsigned char Time_count=0; // 定时器计数器 static全局生命周期 TR0=0; //关定时器 TL0 = 0x00; //重设定时器初值 TH0 = 0xB8; //重设定时器初值 Time_count++; //每隔20毫秒进入中断,Time_count无条件自加运算 if(Time_count>=50) { Time_count = 0; power=~power; //SIM900A运行指示灯,1秒闪烁一次 } if(Timer_start) Times++; //如果收到允许定时,开始计时 if(Times > (50*delay)){ //如果Times 到达设定时间,50*delay就是秒数 Timer_start = 0; // 定时结束,定时功能标记Timer_start一定为0 Times = 0; // 完成定时,清空计数器 } TR0=1; //开定时器 }
编译结果:
Rebuild target 'Target 1' compiling DS18B20.C... linking... Program Size: data=46.0 xdata=100 code=1116 creating hex file from "DS18B20"... "DS18B20" - 0 Error(s), 0 Warning(s).