写一个基于stc89c52单片机,DS1302芯片和LCD1602的定时闹钟代码
时间: 2024-01-22 11:21:39 浏览: 149
以下是一个基于STC89C52单片机、DS1302实时时钟芯片和LCD1602的定时闹钟代码,可以参考:
```c
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCLK = P1^0; // DS1302时钟线
sbit RST = P1^1; // DS1302复位线
sbit IO = P1^2; // DS1302数据线
sbit RS = P2^6; // LCD1602寄存器选择位
sbit RW = P2^5; // LCD1602读写选择位
sbit E = P2^7; // LCD1602使能控制位
uchar code table[] = "0123456789"; // 用于显示数字
uchar code week[] = " 星期日一二三四五六"; // 用于显示星期
uchar sec, min, hour, day, month, week_day, year; // DS1302时间变量
uchar alarm_hour, alarm_min; // 闹钟时间变量
void delay_us(uint us) // 微秒级延时函数
{
while (us--)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
void delay_ms(uint ms) // 毫秒级延时函数
{
while (ms--)
{
delay_us(1000);
}
}
void write_byte(uchar dat) // DS1302写入一个字节数据
{
uchar i;
for (i = 0; i < 8; i++)
{
IO = dat & 0x01;
dat >>= 1;
SCLK = 0;
SCLK = 1;
}
}
uchar read_byte() // DS1302读取一个字节数据
{
uchar i, dat = 0;
for (i = 0; i < 8; i++)
{
dat >>= 1;
if (IO)
{
dat |= 0x80;
}
SCLK = 0;
SCLK = 1;
}
return dat;
}
void write_reg(uchar reg, uchar dat) // DS1302写入一个寄存器数据
{
RST = 0;
delay_us(1);
SCLK = 0;
delay_us(1);
RST = 1;
delay_us(1);
write_byte(reg);
write_byte(dat);
RST = 0;
SCLK = 0;
}
uchar read_reg(uchar reg) // DS1302读取一个寄存器数据
{
uchar dat;
RST = 0;
delay_us(1);
SCLK = 0;
delay_us(1);
RST = 1;
delay_us(1);
write_byte(reg);
dat = read_byte();
RST = 0;
SCLK = 0;
return dat;
}
void write_time() // DS1302写入当前时间
{
write_reg(0x8e, 0); // 关闭写保护
write_reg(0x80, sec); // 写入秒
write_reg(0x82, min); // 写入分
write_reg(0x84, hour); // 写入时
write_reg(0x86, day); // 写入日
write_reg(0x88, month); // 写入月
write_reg(0x8a, week_day); // 写入星期
write_reg(0x8c, year); // 写入年
write_reg(0x8e, 0x80); // 打开写保护
}
void read_time() // DS1302读取当前时间
{
sec = read_reg(0x81); // 读取秒
min = read_reg(0x83); // 读取分
hour = read_reg(0x85); // 读取时
day = read_reg(0x87); // 读取日
month = read_reg(0x89); // 读取月
week_day = read_reg(0x8b); // 读取星期
year = read_reg(0x8d); // 读取年
}
void init_ds1302() // DS1302初始化
{
write_reg(0x8e, 0); // 关闭写保护
write_reg(0x90, 0x10); // 使能时钟
write_reg(0x8c, 0x20); // 写入年份
write_reg(0x88, 0x01); // 写入月份
write_reg(0x86, 0x01); // 写入日期
write_reg(0x8a, 0x01); // 写入星期几
write_reg(0x84, 0x12); // 写入小时
write_reg(0x82, 0x30); // 写入分钟
write_reg(0x80, 0x00); // 写入秒钟
write_reg(0x8e, 0x80); // 打开写保护
}
void init_lcd1602() // LCD1602初始化
{
RW = 0;
delay_ms(20);
write_reg(0x30);
delay_ms(5);
write_reg(0x30);
delay_ms(1);
write_reg(0x30);
delay_ms(1);
write_reg(0x38);
write_reg(0x08);
write_reg(0x01);
write_reg(0x06);
write_reg(0x0c);
}
void write_cmd(uchar cmd) // LCD1602写入命令
{
RS = 0;
E = 0;
P0 = cmd;
delay_us(5);
E = 1;
delay_us(5);
E = 0;
}
void write_data(uchar dat) // LCD1602写入数据
{
RS = 1;
E = 0;
P0 = dat;
delay_us(5);
E = 1;
delay_us(5);
E = 0;
}
void write_str(uchar x, uchar y, uchar *str) // LCD1602显示字符串
{
uchar i;
if (y == 1)
{
x |= 0x40;
}
x |= 0x80;
write_cmd(x);
for (i = 0; str[i] != '\0'; i++)
{
write_data(str[i]);
}
}
void write_num(uchar x, uchar y, uchar num) // LCD1602显示数字
{
uchar high, low;
high = num / 10;
low = num % 10;
write_str(x, y, &table[high]);
write_str(x + 1, y, &table[low]);
}
void update_time() // 更新时间显示
{
write_num(0, 0, hour);
write_data(':');
write_num(3, 0, min);
write_data(':');
write_num(6, 0, sec);
write_str(11, 0, &week[week_day]);
write_num(0, 1, year);
write_data('-');
write_num(3, 1, month);
write_data('-');
write_num(6, 1, day);
}
void check_alarm() // 检查闹钟
{
if (alarm_hour == hour && alarm_min == min)
{
write_str(0, 1, "Alarm!");
delay_ms(1000);
write_str(0, 1, " ");
}
}
void main()
{
init_ds1302();
init_lcd1602();
while (1)
{
read_time();
update_time();
check_alarm();
delay_ms(1000);
sec++;
if (sec == 60)
{
sec = 0;
min++;
if (min == 60)
{
min = 0;
hour++;
if (hour == 24)
{
hour = 0;
}
}
}
}
}
```
这段代码实现了一个简单的定时闹钟功能,可以在LCD1602上显示当前时间,并检查是否到了设定的闹钟时间。需要注意的是,DS1302时钟芯片需要连接到单片机的三个引脚上,而LCD1602则需要连接到单片机的P0口和P2口上,具体连接方式可以参考相关的资料。
阅读全文