前段时间做了一个 基于51单片机的万年历加温度控制风扇以及按键播报时间。在这里做一下笔记。
准备硬件
1:51单片机(我这里用的是STC89C52) 2:语音播报模块(我这里用的是SYN6288) 3:DS1302时钟模块 4:DS18B20温度模块 5:LCD1602显示屏 6:L298N电机驱动 7:蜂鸣器 8:电机 9:按键 5个 10:灯
功能介绍
功能: 1:修改时间 2:修改日期(软件自动校正日期) 3:闹钟模式 4:温度控制风扇速度 5:调节灯亮度 6:播报时间
主界面设置 下面是大概的流程图 位置不够没画全。。。
由于代码较多,这里就不全部贴出来了。
修改时间
当我们进入到修改时间的界面,我们屏幕得显示出刚按下的时间,然后我们得让 1: LCD1602显示时间 2:按键的操作 按键 1:让时 / 分 /秒+1 或者按下按键2 让时 / 分 /秒 -1,然后通过按键3 来切换我到底是 调整时 / 分 /秒 3:按键4按下 退出 4:提示是否保存时间(1:保存,4:不保存) 如果保存我们再写入到DS1302这样就完成了修改时间的功能
unsigned char time_add(unsigned char cursor)
{
unsigned char hour_high,hour_low;
unsigned char min_high, min_low;
unsigned char sec_high, sec_low;
switch(cursor)
{
case 0:
hour_high = temp[2] >> 4;
hour_low = temp[2] & 0x0f;
hour_low = hour_low++;
if(hour_low == 4 && hour_high == 2)
{
hour_low = 0;
hour_high = 0;
}
else if(hour_low == 10)
{
hour_low = 0;
if(hour_high == 2)
hour_high = 0;
else
hour_high = hour_high + 1;
}
hour_high = hour_high << 4;
hour_high = hour_high | hour_low;
temp[2] = hour_high;
lcd_display_byte(5,0,(temp[2]>>4) + 0x30);
lcd_display_byte(6,0,(temp[2]&0x0f) + 0x30);
write_com(0x86);
break;
case 1:
min_high = temp[1] >> 4;
min_low = temp[1] & 0x0f;
min_low++;
if(min_low == 10)
{
min_high++;
min_low = 0;
if(min_high == 6 && min_low == 0)
{
min_high = 0;
min_low = 0;
}
}
min_high = min_high << 4;
min_high = min_high | min_low;
temp[1] = min_high;
lcd_display_byte(8,0,(temp[1]>>4) + 0x30);
lcd_display_byte(9,0,(temp[1]&0x0f) + 0x30);
write_com(0x89);
break;
case 2:
sec_high = temp[0] >> 4;
sec_low = temp[0] & 0x0f;
sec_low++;
if(sec_low == 10)
{
sec_low = 0;
sec_high++;
if(sec_high == 6 && sec_low == 0)
{
sec_low = 0;
sec_high = 0;
}
}
sec_high = sec_high << 4;
sec_high = sec_high | sec_low;
temp[0] = sec_high;
lcd_display_byte(11,0,(temp[0]>>4) + 0x30);
lcd_display_byte(12,0,(temp[0]&0x0f) + 0x30);
write_com(0x8c);
break;
default :
break;
}
return cursor;
}
修改日期(并且校正星期)
当我们进入到修改日期的界面,我们屏幕得显示出刚按下的日期,然后我们得让 1: LCD1602显示日期 2:按键的操作 按键 1:让年/月/日+1 或者按下按键2 让年/月/日 -1,然后通过按键3 来切换我到底是 调整年/月/日 3:按键4按下 退出 4:提示是否保存日期(1:保存,4:不保存) 5:星期的自动调整 星期 = (月份对应的数字+日期数字) / 7 余数:则是星期几 0位周日 如果保存我们再写入到DS1302这样就完成了修改日期的功能
void revision_week()
{
unsigned char num;
unsigned char month;
unsigned char day;
unsigned char week;
month = ((temp[4]>>4)*10 + (temp[4]&0x0f));
day = ((temp[3]>>4)*10 + (temp[3]&0x0f));
switch(month)
{
case 5: num = 5; break;
case 6: num = 1; break;
case 8: num = 6; break;
case 1: case 10: num = 4; break;
case 4: case 7: num = 3; break;
case 9: case 12: num = 2; break;
case 2: case 3: case 11: num = 0; break;
}
week = (num+day)%7;
if(week == 0)
temp[5] = 0x07;
else
temp[5] = week;
}
闹钟模式
进入到闹钟模式,设置闹钟的时间 选择周几,选择响铃时长。 时间的设置 跟修改时间的设置一模一样,等设置完时间,我们调到设置星期,按键1是 切换周一到 周日,按键2是确认选择当前这个星期,按键3是取消选择当前这个星期。 按键4:是否保存? 不保存就退出了,如果保存继续跳转到选择闹钟时间的界面。这里就没啥了。然后保存退出。主界面OFF 变成 ON 表示开启了
void lcd_dispaly_chooseClockWeek()
{
unsigned char s = 0;
unsigned char week;
LCD1602_CLS;
lcd_display_str(0,0,"week: 2:ON3:OFF");
lcd_display_str(0,1,"clock:");
week = temp[5];
while(1)
{
lcd_display_byte(5,0,(week & 0x0f) + 0x30);
for(s=0;s<7;s++)
{
if((alarmClockWeek>>s)&0x01 == 1)
lcd_display_byte(s+6,1,(s+1)+0x30);
}
write_com(0x85);
menu = gather_key();
switch(menu)
{
case 1:
week++;
if(week >= 8)
week = 1;
break;
case 2:
switch(week)
{
case 1: alarmClockWeek |= 0x01; lcd_display_byte(6,1,'1'); break;
case 2: alarmClockWeek |= 0x02; lcd_display_byte(7,1,'2'); break;
case 3: alarmClockWeek |= 0x04; lcd_display_byte(8,1,'3'); break;
case 4: alarmClockWeek |= 0x08; lcd_display_byte(9,1,'4'); break;
case 5: alarmClockWeek |= 0x10; lcd_display_byte(10,1,'5'); break;
case 6: alarmClockWeek |= 0x20; lcd_display_byte(11,1,'6'); break;
case 7: alarmClockWeek |= 0x40; lcd_display_byte(12,1,'7'); break;
}
break;
case 3:
switch(week)
{
case 1: alarmClockWeek &= ~0x01; lcd_display_byte(6,1,' '); break;
case 2: alarmClockWeek &= ~0x02; lcd_display_byte(7,1,' '); break;
case 3: alarmClockWeek &= ~0x04; lcd_display_byte(8,1,' '); break;
case 4: alarmClockWeek &= ~0x08; lcd_display_byte(9,1,' '); break;
case 5: alarmClockWeek &= ~0x10; lcd_display_byte(10,1,' '); break;
case 6: alarmClockWeek &= ~0x20; lcd_display_byte(11,1,' '); break;
case 7: alarmClockWeek &= ~0x40; lcd_display_byte(12,1,' '); break;
}
break;
case 4:
s = lcd_display_saveTimeOrDate_YesOrNo(3);
if(s)
{
ALARM_CLOCK_OFF;
alarmClockWeek = 0;
LCD1602_CLS;
return;
}
ALARM_CLOCK_ON;
LCD1602_CLS;
return;
}
}
}
调节灯模式
void modifLightMode()
{
unsigned char s = 0;
s = lcd_display_light_menu();
if(s)
{
write_com(CLEAR_SCREEN);
exitFlag = 1;
return;
}
lcd_display_str(0,0,"Light gear:");
TR0 = 1;
while(menu != 4)
{
lcd_display_byte(11,0,light_gear+0x30);
menu = gather_key();
switch(menu)
{
case 1:
light_gear++;
if(light_gear>=3)
{
light_gear = 3;
TR0 = 0;
LED = 0;
}
else if(light_gear == 0)
{
TR0 = 0;
LED = 1;
}
else
{
TR0 = 1;
LED = 0;
}
break;
case 2:
if(light_gear>=1)
{
light_gear--;
}
else
{
light_gear = 0;
}
if(light_gear == 3)
{
TR0 = 0;
LED = 0;
}
else if(light_gear == 0)
{
TR0 = 0;
LED = 1;
}
else
{
TR0 = 1;
LED = 0;
}
break;
case 4:
exitFlag = 1;
return;
}
}
}
调节风扇模式
void modifFanMode()
{
unsigned char s = 0;
s = lcd_display_fan_menu();
if(s)
{
write_com(CLEAR_SCREEN);
exitFlag = 1;
return;
}
lcd_display_str(0,0,"Fan gear:");
TR1 = 1;
while(menu != 4)
{
lcd_display_byte(9,0,fan_gear+0x30);
menu = gather_key();
switch(menu)
{
case 1:
fan_gear++;
if(fan_gear>=3)
{
FAN = 1;
TR1 = 0;
fan_gear = 3;
}
else if(fan_gear == 0)
{
FAN = 0;
TR1 = 0;
}
else
{
FAN = 1;
TR1 = 1;
}
break;
case 2:
if(fan_gear>=1)
{
fan_gear--;
}
if(fan_gear == 0)
{
FAN = 0;
TR1 = 0;
fan_gear = 0;
}
else if(fan_gear == 3)
{
FAN = 1;
TR1 = 0;
}
else
{
TR1 = 1;
FAN = 1;
}
break;
case 4:
exitFlag = 1;
return;
}
}
}
按键播报时间
这里我是用外部中断做。
void playTime(void)
{
unsigned char syn6288_time[5] = {'\0'};
syn6288_time[0] = (time[2]>>4)+48;
syn6288_time[1] = (time[2]&0x0f)+48;
syn6288_time[2] = ':';
syn6288_time[3] = (time[1]>>4)+48;
syn6288_time[4] = (time[1]&0x0f)+48;
SYN_FrameInfo(0, "[v16][t5]当前时间");
delay(2000);
SYN_FrameInfo(0,syn6288_time);
delay(2000);
}
void key_handler(void) interrupt 0
{
delay(15);
if(kk == 0)
{
EX0 = 0;
playTime();
EX0 = 1;
}
}
温度控制风扇
void fan_speed_control()
{
if(temperature[0] >= 20 && temperature[0] <= 25)
{
fan_gear = 1;
FAN = 1;
TR1 = 1;
}
else if(temperature[0] >= 26 && temperature[0] <= 30)
{
fan_gear = 2;
FAN = 1;
TR1 = 1;
}
else if(temperature[0] > 30)
{
fan_gear = 3;
FAN = 1;
TR1 = 0;
}
else
{
fan_gear = 0;
FAN = 0;
TR1 = 0;
}
}
主程序代码
#include <reg52.h>
#include "lcd1602.h"
#include "ds1302.h"
#include "key.h"
#include "alarmClock.h"
#include "light.h"
#include "ds18b20.h"
#include "fan.h"
#include "uart.h"
#include "syn6288.h"
#include "delay.h"
void main()
{
lcd_init();
ds1302_init();
key_init();
light_init();
ds18b20_init();
fan_init();
uart_init();
while(1)
{
menu = gather_key();
switch(menu)
{
case 0:
if(exitFlag == 0)
{
lcd_display_time();
lcd_display_date();
exitFlag = 2;
}
ds1302_burst_read(DS1302_READ_TIME);
lcd_display_dateAndTimeAndTemp();
if(alarmClock_flag)
{
detectionAlarmClock();
}
break;
case 1:
case 2:
case 3:
lcd_display_menu();
break;
}
}
}
项目演示
如果觉得这篇文章对你有用。欢迎大家点赞、评论哈哈 需要整个工程代码,欢迎大家打赏,评论区留上你的邮箱 or vx or qq。o( ̄︶ ̄)o 或者+我Q 844797079
|