一、题目: (1)基于单片机的电子时钟设计 用LCD(1602)液晶作为显示,可以分别设置小时、分钟、秒,复位为后0,实现日期的设置,年、月、日;闹钟功能,显示星期等。 器件:LCD、按键、蜂鸣器 代码及其详解
时间: 2023-07-10 13:09:58 浏览: 97
很高兴回答你的问题。
针对你的问题,我可以为你提供一些基本思路和参考代码,但是由于篇幅限制,无法提供详细的代码和注释解释。以下是设计思路:
1. 硬件设计
该电子时钟主要由单片机、LCD、按键、蜂鸣器等器件组成。单片机采用常用的AT89C51,LCD选择1602液晶,蜂鸣器用于闹钟提醒。
2. 软件设计
该电子时钟主要需要实现以下功能:
(1)显示时间和日期
(2)设置时间和日期
(3)设置闹钟
(4)闹钟提醒
具体实现可以采用中断方式,定时器中断用于更新时间和日期的显示,外部中断用于按键检测和闹钟提醒。
以下是参考代码:
```c
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit LCD_RS = P1^0;
sbit LCD_RW = P1^1;
sbit LCD_EN = P1^2;
sbit BUZZ = P1^3;
uchar code week[] = {"Sun Mon Tue Wed Thu Fri Sat"};
uchar code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar year, month, day, hour, min, sec, week_day, alarm_hour, alarm_min, alarm_flag;
void delay(uint xms) //延时函数
{
uint i, j;
for (i = xms; i > 0; i--)
for (j = 112; j > 0; j--);
}
void write_com(uchar com) //写命令函数
{
LCD_RS = 0;
P0 = com;
LCD_EN = 1;
delay(5);
LCD_EN = 0;
}
void write_data(uchar dat) //写数据函数
{
LCD_RS = 1;
P0 = dat;
LCD_EN = 1;
delay(5);
LCD_EN = 0;
}
void init_lcd() //初始化LCD函数
{
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
void display_time() //显示时间函数
{
uchar hour10, hour1, min10, min1, sec10, sec1;
hour10 = hour / 10;
hour1 = hour % 10;
min10 = min / 10;
min1 = min % 10;
sec10 = sec / 10;
sec1 = sec % 10;
write_com(0x80);
write_data(table[hour10]);
write_data(table[hour1]);
write_data(0x3a); //":"
write_data(table[min10]);
write_data(table[min1]);
write_data(0x3a); //":"
write_data(table[sec10]);
write_data(table[sec1]);
}
void display_date() //显示日期函数
{
uchar year10, year1, month10, month1, day10, day1;
year10 = year / 10;
year1 = year % 10;
month10 = month / 10;
month1 = month % 10;
day10 = day / 10;
day1 = day % 10;
write_com(0xc0);
write_data(table[month10]);
write_data(table[month1]);
write_data(0x2f); //"/"
write_data(table[day10]);
write_data(table[day1]);
write_data(0x2f); //"/"
write_data(table[year10]);
write_data(table[year1]);
write_data(' ');
write_data(week[week_day*4]);
write_data(week[week_day*4+1]);
write_data(week[week_day*4+2]);
write_data(week[week_day*4+3]);
}
void key_scan() //按键扫描函数
{
uchar key_value;
key_value = P2 & 0x0f;
if (key_value != 0x0f) //有按键按下
{
delay(5); //去抖
key_value = P2 & 0x0f;
if (key_value != 0x0f) //确认按键按下
{
switch (key_value)
{
case 0x0e: //设置小时
while ((P2 & 0x0f) != 0x0f) //等待按键释放
{
delay(5);
key_value = P2 & 0x0f;
if (key_value == 0x0d) //增加小时
{
hour++;
if (hour == 24)
hour = 0;
display_time();
}
else if (key_value == 0x0b) //减少小时
{
if (hour == 0)
hour = 23;
else
hour--;
display_time();
}
}
break;
case 0x0d: //设置分钟
while ((P2 & 0x0f) != 0x0f) //等待按键释放
{
delay(5);
key_value = P2 & 0x0f;
if (key_value == 0x0d) //增加分钟
{
min++;
if (min == 60)
min = 0;
display_time();
}
else if (key_value == 0x0b) //减少分钟
{
if (min == 0)
min = 59;
else
min--;
display_time();
}
}
break;
case 0x0b: //设置日期
while ((P2 & 0x0f) != 0x0f) //等待按键释放
{
delay(5);
key_value = P2 & 0x0f;
if (key_value == 0x0d) //增加日期
{
day++;
if ((month == 2 && year % 4 == 0 && day == 30) || ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) || (day == 32))
{
day = 1;
month++;
if (month == 13)
{
month = 1;
year++;
}
}
display_date();
}
else if (key_value == 0x0b) //减少日期
{
if (day == 1)
{
if (month == 1)
{
day = 31;
month = 12;
year--;
}
else if (month == 3 && year % 4 == 0)
{
day = 29;
month--;
}
else if (month == 3 && year % 4 != 0)
{
day = 28;
month--;
}
else if (month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
{
day = 30;
month--;
}
else
{
day = 31;
month--;
}
}
else
day--;
display_date();
}
}
break;
case 0x07: //设置闹钟
while ((P2 & 0x0f) != 0x0f) //等待按键释放
{
delay(5);
key_value = P2 & 0x0f;
if (key_value == 0x0d) //增加小时
{
alarm_hour++;
if (alarm_hour == 24)
alarm_hour = 0;
write_com(0x8f);
write_data(table[alarm_hour/10]);
write_data(table[alarm_hour%10]);
}
else if (key_value == 0x0b) //减少小时
{
if (alarm_hour == 0)
alarm_hour = 23;
else
alarm_hour--;
write_com(0x8f);
write_data(table[alarm_hour/10]);
write_data(table[alarm_hour%10]);
}
else if (key_value == 0x0e) //增加分钟
{
alarm_min++;
if (alarm_min == 60)
alarm_min = 0;
write_com(0x92);
write_data(table[alarm_min/10]);
write_data(table[alarm_min%10]);
}
else if (key_value == 0x0d) //减少分钟
{
if (alarm_min == 0)
alarm_min = 59;
else
alarm_min--;
write_com(0x92);
write_data(table[alarm_min/10]);
write_data(table[alarm_min%10]);
}
}
break;
}
}
}
}
void alarm() //闹钟函数
{
if (alarm_flag == 1)
{
BUZZ = ~BUZZ;
delay(10);
BUZZ = ~BUZZ;
delay(10);
}
}
void timer0() interrupt 1 //定时器0中断函数
{
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
sec++;
if (sec == 60)
{
sec = 0;
min++;
if (min == 60)
{
min = 0;
hour++;
if (hour == 24)
{
hour = 0;
week_day++;
if (week_day == 7)
week_day = 0;
}
}
}
display_time();
if (sec == 0)
display_date();
key_scan();
if (hour == alarm_hour && min == alarm_min && sec == 0)
alarm_flag = 1;
alarm();
}
void main()
{
TMOD = 0x01; //定时器0模式1
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
EA = 1; //总中断开关
ET0 = 1; //定时器0中断开关
TR0 = 1; //定时器0开关
init_lcd();
year = 20;
month = 1;
day = 1;
hour = 0;
min = 0;
sec = 0;
week_day = 2;
alarm_hour = 6;
alarm_min = 30;
alarm_flag = 0;
display_time();
display_date();
while (1);
}
```
以上是一个基于单片机的电子时钟设计,其中包含了 LCD 显示、按键扫描、闹钟功能等。由于篇幅限制,代码中注释并不详细,但是希望这份代码可以给你提供一些参考和帮助。
阅读全文