- 家有恶猫,任性跋扈;
- 贪吃贪睡,屎尿巨臭;
- 爪力强劲,刨砂疯狂;
- 猫砂四溅,尘土飞扬;
- 娘子过敏,喷嚏不止;
- 吾心痛焉,技以治之;
本设计用到的元器件:
1.STC12C5068AD为主控;
2.DS1302为时钟IC;
3.TD1030卫星定位授时模块授时;
4.TM1637模块用于显示时间;
5.E18-D80NK型光电开关为触发开关;
6.辅以土壤湿度监测模块监测砂盆附近花盆里的土壤湿度;
7.对外输出包括两路低电平有效的继电器模块(控制风扇、水泵的开关)、蜂鸣器、指示灯等。
实现的主要功能:
1.在恶猫进入砂盆后出发光电开关输出维持低电平,打开风扇开始通风除尘;
2.当恶猫大小便完毕离开砂盆,光电开关输出恢复高电平,使用单片机PCA模块的触发捕获功能捕获上升沿跳变,风扇延时开启2min后关闭;
3.每隔1h自动打开风扇2min通风除味;
4.每天早上07:10打开水泵30s向花盆喷水(润湿植物表层);
5.当土壤湿度模块检测到土壤湿度过低,启动水泵浇水;
6.每天早上7:00及晚上19:00自动打开卫星定位授时模块校准时间。
电路原理图如下:
简单原理图
部分单片机程序:
- #include "STC12C56XX.H"
- #include "intrins.h"
- #include "TM1637.h"
- #include "DS1302.h"
- /*定义各个端口*/
- sbit GPS_EN=P2^4; //定义GPS模块使能端口
- sbit LED=P2^5; //定义GPS_LED开关端口
- sbit FAN=P2^6; //定义风机信号端口(继电器驱动)
- sbit PUMP=P2^7; //定义水泵信号端口(继电器驱动)
- sbit SPK=P3^7; //定义蜂鸣器信号端口
- sbit SD=P1^0; //定义土壤湿度信号端口(数字信号)
- sbit GPS_RST=P1^4; //GPS手动对时按键
- sbit SW=P3^5; //定义触发端口,低电平有效,一并捕获上升沿触发
- sbit EPCAI=IE^6; //PCA模块和LVD监测中断允许位(在头文件中为EPCA_LVD)
- /*定义各个变量、数组及标志位*/
- unsigned char hour,min,sec,hourr,minr,secr,hour1,hour2,min1,min2;//小时,分钟,秒钟,小时收到,分钟收到,秒钟收到,小时十位,小时个位,分钟十位,分钟个位
- bit rev_start,rev_stop; //串口接收开始标志位,接收停止标志位
- bit flagT,flag_PCA; //计时标志位,PCA触发标志位
- unsigned int t50ms; //定时变量
- unsigned char buf[80]; //接收到GPS数据存储到该数组
- void delayms(unsigned int xms)//ms延时函数
- {
- unsigned int i,j;
- for(i=0; i<xms; i++)
- for(j=0; j<500; j++);
- }
-
- void USART_Init() //串口及定时器0,1初始化
- {
- TMOD=0x21; //定时器1工作在方式2,8位自动重装,定时器0工作在模式1
- SCON = 0x50; //使用串行工作方式1,10位异步收发8位数据,波特率可变(由T1的溢出率控制)
- TH1 = TL1=0xFD; //9600波特率的初值
- // TH1 = TL1=0xFA; //4800波特率的初值
- ES = 1; //开串口中断
- TR1 = 1; //允许T1计数
- TH0 = 0x3C; //装定时器0初值,TH0=(65535-50000)/256,TL0=(65535-50000)%256
- TL0 = 0xB0; //50ms中断一次
- ET0 = 1; //开T0中断
- TR0 = 1; //允许T0计数
- EA=1; //开总中断
- }
- void PCA_Init() //PCA初始化,关于计数部分的配置可注释掉,这里只用到了捕获模式
- {
- CCON=0; //初始化PCA控制寄存器,PCA定时器停止运行,清零CF标志位,清零所有模式中断标志位
- CL=0; //重置PCA计数器
- CH=0;
- CMOD=0x00; //设置PCA计数器时钟源为Fosc/12,禁止PCA计数器溢出中断
- // CCAPM1=0x31; //PCA模块1工作在16位捕获模式,跳变触发
- CCAPM1=0x21; //PCA模块1工作在16位捕获模式,上升沿触发
- CR=1; //PCA计数器启动
- EPCAI=1; //开PCA中断
- EA=1; //开总中断
- }
- /* NMEA0183协议中最简定位信息GNRMC数据格式 */
- /* $GNRMC,203741.00,A,3636.39993,N,12011.80057,E,0.023,,270718,,,A,V*19 */
- /* 定位成功的GNRMC数据格式,串口调试模拟发送时务必要有换行标志"\n"符提示接收停止 */
- /* $GNRMC,,V,,,,,,,,,,N,V*37 */
- /* 无信号时的GNRMC数据,即无效定位/授时数据,此时Write_time函数将从','和'V'中取值,所以需要判断定位/授时数据的有效性 */
- void Write_time()//将GPS授时数据取值转换并写入DS1302
- {
- if((rev_stop==1)&&(buf[0]=='R')&&(buf[2]=='C')&&(buf[4]!=','))//如果接收到GPRMC,从'R'开始接受计数,当buf[4]!=','时,授时数据有效,否则无效
- {
- ES=0; //关闭串口中断
- hourr= (buf [4]-0x30)* 16+ buf[5] -0x30; //取hour数值HEX
- minr= (buf [6]-0x30)* 16+ buf[7]-0x30; //取min数值HEX
- secr= (buf[8]-0x30)* 16+ buf[9]-0x30; //取sec数值HEX
- hourr= hourr / 16 * 10 + hourr % 16; //HEX-DEC
- hourr= (hourr+8) % 24; //UTC Time换算成北京时间,+8h
- hourr=hourr/10*16+hourr%10; //DEC-HEX
- set_time(secr,minr,hourr); //授时数据写入DS1302
- ES=1; //开启串口中断
- rev_stop=0; //接收停止标志位清零
- }
-
- }
- void Read_time() //从DS1302中读取时间数据
- {
- hour= ds1302_read(0x85); //小时
- min = ds1302_read(0x83); //分钟
- sec = ds1302_read(0x81); //秒钟
- }
- void jisuan(void) //根据接收到的授时数据取值
- {
- hour1=hour/16; //取hour十位
- hour2=hour%16; //取hour个位
- min1=min/16; //取min十位
- min2=min%16; //取min个位
- if (sec%2==0) //判断sec奇偶
- {
- hour2=hour2+10; //":"闪烁,间隔1s,亮1s,灭1s
- }
- }
- void da() //长鸣一声,代表整点报时及动作开启
- {
- SPK=1;
- delayms(2000);
- SPK=0;
- }
- void daa() //短鸣一声,用于GPS授时时的声音提示
- {
- SPK=0;
- delayms(1000);
- SPK=1;
- delayms(1000);
- SPK=0;
- }
- void didi() //短鸣两声,代表动作结束
- {
- SPK=1;
- delayms(500);
- SPK=0;
- delayms(300);
- SPK=1;
- delayms(500);
- SPK=0;
- }
- void shan() //GPS模块上的LED闪烁
- {
- LED=0;
- delayms(1000);
- LED=1;
- delayms(1000);
- LED=0;
- }
- void Out(void) //定时输出
- {
- if((min==0x30)&&(sec==0x00)) {da();} //每隔1h(xxh30m00s时),蜂鸣器长鸣一声
- else if(((min>=0x30)&&(min<0x32))||(SW==0)) {FAN=0;} //风机启动2min(xxh30m00s-xxh32m00s),如果光电开关被触发且维持低电平,维持风机启动
- else if((min==0x32)&&(sec==0x00)) {FAN=1;didi();} //2min后(xxh32m00s时),关闭风机,蜂鸣器短鸣两声
- else if((min==0x00)&&(sec==0x00)) {da();} //每个整点(xxh00m00s时),蜂鸣器长鸣一声,整点报时
- else if((hour==0x07)&&(min==0x10)&&(sec==0x00)) {da();} //每天早上07h10m00s,蜂鸣器长鸣一声
- else if((hour==0x07)&&(min==0x10)&&(sec<0x30)&&(sec>=0x00)) {PUMP=0;} //水泵启动30s(07h10m00s-07h10m30s)
- else if((hour==0x07)&&(min==0x10)&&(sec==0x30)) {PUMP=1;didi();} //30s后(07h10m30s时),关闭水泵,蜂鸣器短鸣两声
- else if(SD==1) {PUMP=0;} //如果土壤湿度低于设定值,开启水泵浇水
- // else if(SW==0) {FAN=0;} //如果光电开关被触发且维持低电平,维持风机启动
- else {FAN=PUMP=1;SPK=0;}
- }
- void chufa() //PCA触发定时执行
- {
- if(flag_PCA==1) //被触发
- {
- FAN=0; //开启风机
- if(flagT==1) //定时满2min
- {
- FAN=1; //关闭风机
- flagT=0; //清零定时标志位
- flag_PCA=0;//清零触发标志位
- }
- }
- }
- void main()
- {
- P2M0=0x00;
- P2M1=0xf0; //P24-P27强推挽输出
- P3M0=0x20;
- P3M1=0x80; //P37强推挽输出,P35高阻输入
- FAN=PUMP=SW=1; //关闭风机、水泵,触发端口置高
- SPK=0; //关闭蜂鸣器
- GPS_EN=0; //关闭GPS模块
- LED=1; //开启GPS模块上的LED
- GPS_RST=1; //GPS手动对时按键端口置高
- PCA_Init(); //PCA初始化
- USART_Init(); //串口及定时器0初始化
- while(1)
- {
- if(((hour==0x07)&&(min==0x00))||((hour==0x19)&&(min==0x00))||(GPS_RST==0)) //每天(07:00、19:00)定时打开GPS校准时间再关掉,对时持续1min,也可手动触发校准
- {GPS_EN=1;shan();daa();ES=1;} //使能GPS模块,LED闪烁,蜂鸣器鸣响,开启串口中断
- else
- {GPS_EN=0;LED=0;ES=0;} //关闭GPS模块,LED关闭,关闭串口中断
- Write_time(); //向DS1302中写入时间
- Read_time(); //读取DS1302中的时间数据
- Out(); //输出
- chufa(); //PCA触发执行延时
- jisuan(); //接收时间数据并取值
- xsled(hour1,hour2,min1,min2); //显示时间
- }
- }
- void Uart_Receive(void) interrupt 4 //串口中断,接收GNRMC授时数据
- {
- unsigned char ch,num; //定义接收字符、数组计数变量
- ES = 0; //关闭串口
- if (RI) //如果接收完成则进入
- {
- ch=SBUF; //从串口缓冲寄存器中取值
- if(ch=='R') //如果收到字符'R',便开始接收
- {
- rev_start=1; //接收开始标志位置1
- rev_stop =0; //接收停止标志置0
- }
- if(rev_start==1) //标志位为1,开始接收
- {
- buf[num++]=ch; //字符存到数组中
- if (ch=='\n') //如果接收到换行
- {
- buf[num]='\n';
- rev_start=0; //接收开始标志位置0
- rev_stop=1; //接收停止标志位置1
- num=0; //计数置0
- }
- }
- }
- RI = 0; //RI清0,重新接收
- ES = 1; //串口1中断允许
- }
- void TIM0(void) interrupt 1 //定时器0中断函数
- {
- TH0 = 0x3C; //重装初值
- TL0 = 0xB0;
- if(flag_PCA==1) //如果触发
- {
- t50ms++; //开始计时
- if(t50ms>=2400) //计时满2min时,实际测试约2min10sec
- {
- t50ms=0; //清零计时变量
- flagT=1; //计时标志位置1
- }
- }
- }
- void PCA_isr() interrupt 6 //PCA捕获模式中断函数
- {
- CCF1=0; //清零中断标志位
- flag_PCA=1; //触发执行标志位
- }
复制代码
全部资料51hei下载地址:
GPS授时.zip
(54.18 KB, 下载次数: 19)
|