写在前面
🍁个人主页:HNUJSY
✨推荐专栏:《史上最全经典面试题总结》欢迎订阅学习~
📌Xmind文件获取:GitHub 持续更新中,别忘了 star 喔~
GitHub链接:智慧闹钟工程
一、设计目标
- 通过无源蜂鸣器实现闹钟响铃功能;
- 通过光照传感器实现闹钟开启功能;
- 通过振动传感器实现闹钟关闭功能;
- 通过温度传感器实现温度测量功能;
- 通过按键KEY1实现蜂鸣器变调功能;
- 通过按键KEY2实现闹钟开关的功能;
- 通过数码管显示温度、闹钟开关和对应的音调;
二、设计想法
由于社会的发展和科技的进步,人们对生活品质要求越来越高,而计算机时代的来临和物联网技术的发展也会给我们的生活带来巨大的变化,所以我希望通过物联网传感技术实现对闹钟的创意设计,从而改进人们的生活品质。
首先相对于传闹钟设置闹铃的方式,我想把这款创意闹钟设计成通过光照传感器来实现对闹钟的开启,更有效实现闹钟的自动化、智能化,不过为了防止误触带来闹钟的开启,需要对开启条件进行考量。其次我希望改变传统闹钟按键关闭的方式,实现通过运动或手部摆动帮助用户清醒,所以需要通过振动传感器关闭闹钟的功能。然后我希望闹钟可以实现温度显示的功能,帮助用户识别当前温度,辨别冷暖,适当的增减衣物。最后通过按键实现闹钟的总开关和闹铃音调的改变。
所以在本次实验中,我通过三个按键,光照传感器、温度传感器、振动传感器以及数码管对上述想法进行实现。
三、硬件原理
……
四、软件原理
- 数码管显示模块
1.1 数组段选用于存储相应的数码管显示的段选信号,函数weixuan(char i)用于选择对应的位置
char segtable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void weixuan(char i)
{
SEL2=i/4;
SEL1=i%4/2;
SEL0=i%2;
}
1.2 数码管显示函数
void SEG_Display()
{
//用于设置温度的位数
if(temp<0)
{
P0=0;
weixuan(0); //若温度为负,则首位显示‘-‘
P0=0x40;
Delay(10);
}
else
{
P0=0;
weixuan(5);
P0=segtable[temp_bai];
Delay(10);
}
P0=0;
weixuan(6);
P0=segtable[temp_shi];
Delay(10);
P0=0;
weixuan(7);
P0=segtable[temp_ge];
Delay(10);
P0=0;
weixuan(1); //显示闹钟开关
P0=segtable[ringopen];
Delay(10);
P0=0;
weixuan(3); //显示闹铃音调
P0=segtable[num];
Delay(10);
}
- 温度光照传感器的AD转换模块
2.1 使用定时器1的中断函数为温度ADC计时
IE=0xa8; //EA=1打开总中断,EADC=1允许A/D转化中断,ET1=1允许T1中断
TMOD=0x01; //使用定时器1,16位不可重装载模式,TH1、TL1全用
TH1=(65535-1000)/256;//高8位赋初值,定时40000周期
TL1=(65535-1000)%256;//低8位赋初值
TR1=1; //启动定时器1
2.2 初始化温度光照AD转换
void InitADC_temp()
{
P1ASF=0xff; //将P1口作为模拟功能A/D使用
ADC_RES=0; //寄存器ADC_RES和ADC_RESL保存A/D转化结果
ADC_RESL=0; //初始赋值0
ADC_CONTR=0x8b; //ADC_POWER=1打开A/D转换器电源;ADC_START=1启动模拟转换器ADC;CHS=011选择P1^3作为A/D输入使用
CLK_DIV=0x20; //ADRJ=1:ADC_RES[1:0]存放高2位ADC结果,ADC_RESL[7:0]存放低8位ADC结果
}
void InitADC_light()
{
P1ASF=0xff;
ADC_RES=0;
ADC_RESL=0;
ADC_CONTR=0x8c; //CHS=100选择P1^4作为A/D输入使用
CLK_DIV=0x20;
}
2.3 AD中断,当flag为0时查找对应AD的温度值,处理温度部分数据,当flag为1时查找对应AD的光照值,处理光照部分数据,转换完成后,ADC_FLAG清零,ADC_START赋1,打开中断。
time++;
IE=0x00; //关闭中断
if(time>2000) //取多次值求平均值减小误差
{
if(flag==1) //此时flag=1执行温度部分
{
date_temp=(sumt+t/2)/t; //四舍五入
temp=tempdata[date_temp-1]; //查找对应的AD的温度值
sumt=0;
t=0;
time=0;
date_processtemp();
}
if(flag==-1) //此时flag=-1执行光部分
{
light=(suml+l/2)/l; //四舍五入
suml=0;
l=0;
time=0;
}
}
if(flag==1)
{
//对应温度的数据处理
t++;
date_temp=(ADC_RES*256+ADC_RESL)/4;//由10位AD值转换为8位AD值
sumt+=date_temp; //求t次AD值的和
}
if(flag==-1)
{
//处理光部分的数据
l++;
suml+=ADC_RES*256+ADC_RESL;//求l次AD值的和
}
- 蜂鸣器判断模块
3.1 定时器中断处理,进行判断,满足光照条件开启蜂鸣器,满足振动条件关闭蜂鸣器
if(ringopen==1){ //判断按键开关
if(light<40){ //判断之前是否黑夜
if(dark<2000){
dark++;} //利用dark进行计数
state=0; //状态为黑夜
}else{
if(white<2000){ //判断现在是否白天
white++;} //利用white进行计数
state=1; //状态为白天
}
if(white==2000&&dark==2000&&state==1){//判断从黑夜进入白天且当前为白天
dark=0; //dark white清零且打开开关
white=0;
ring=1;
}
}
if(sbtVib == 0)
{
Delay(100); //延时消除抖动
if(sbtVib == 0)
{
ring=0; //通过振动关闭闹钟
}
}
4.蜂鸣器发声模块
4.1 定时器中断处理,进行判断,满足条件则蜂鸣器取反
if(ring==1&&ringopen==1){//光照开关且按键开关为开时蜂鸣器启动
sbtbeep = ~sbtbeep;
}else{
sbtbeep = 0;
}
五、软件流程
六、设计结果
- 打开闹钟总开关,遮挡光照传感器十秒钟,取走遮挡物,闹钟开始响,实现光照控制闹钟开启;
- 按按键2修改音调,蜂鸣器音调改变,实现按键2控制音调;
- 温度实时显示在数码管,实现温度的实时显示;
- 振动STC板多次,闹铃声停止,实现振动控制闹钟关闭;
- 按按键1,关闭闹钟总开关,遮挡光照传感器十秒钟,取走遮挡物,闹钟没有反应,实现按键控制闹钟的总开关。
七、操作说明
- 按键说明:
- 按键1为总开关按键,控制闹钟的开启和关闭,按键1只能在闹钟未开启的状态下进行设置(为了防止通过按键控制闹钟的关闭);
- 按键2为音调调节按键,按压按键可以控制闹铃的音调。
- 显示说明:
- 第一个数字为闹钟开关按键,0代表开的状态,1代表关的状态;
- 第二个数字代表闹铃的音调,有0-9十个状态,通过按键2不断递增,数字越大,音调越低;
- 第三个数字代表温度,当温度为零下时,数码管会显示负数;
- 操作说明:
通过按键1开启闹钟总开关,从黑夜进入白天,光照传感器接受信息开启闹钟,闹钟开始响铃,通过振动关闭闹钟,数码管第三个数字实时显示当前温度,提醒您适时增减衣物,通过按键2可以改变闹铃的音调。
八、 设计日志
-
刚开始出现手动干扰时或黑夜进入白天时闹铃都会开启
解决方案:设计white和dark两个计数变量,state状态变量,通过亮度低时dark递增计数state设为0,亮度高时white递增计数state设为1,只有满足dark和white达到一定数量即都需满足黑夜和白天都有一定的时间且当前状态为1即现在状态为白天时,才开启闹钟开关。 -
闹钟关闭后对闹钟进行黑夜入白天测试没反应,再次开启开关时,闹钟直接开始响
解决方案:设置总的ringopen变量,并设置为最初的条件判断,根据按键2的状态进行改变,当为关闭的状态时,dark和white不发生计数,闹钟不能进入开启状态。 -
多次测试过程中,发现一次按键会发生多次响应
解决方案:为按键加入防抖程序。 -
闹铃过程中发现可以通过按键关闭闹钟
解决方案:在按键响应程序中加入条件判断,必须在闹铃没有响的情况下才能置ringopen为1。