标题:
单片机数字电子钟(年月日星期时分秒、温湿度、整点报时、闹钟、播放音乐、记忆 LM041L
[打印本页]
作者:
xxxxxxiu
时间:
2022-11-7 18:24
标题:
单片机数字电子钟(年月日星期时分秒、温湿度、整点报时、闹钟、播放音乐、记忆 LM041L
基于AT89C51单片机、DHT11传感器、LCD、蜂鸣器设计的数字电子钟,通过按键初始化当前时刻和闹钟,并显示年月日星期时分秒、温湿度显示、整点报时、闹钟、播放音乐(小星星)、记忆时刻,内容包括:Proteus工程和Keil
LM041L大屏幕显示
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.gif
(175.62 KB, 下载次数: 33)
下载附件
2022-11-9 18:22 上传
单片机源程序如下:
#include<reg51.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define port P0
sbit rst=P3^0; // 复位
sbit sclk=P3^1; // 时钟
sbit io=P3^2; // 输入输出口
sbit e=P2^2; // 使能
sbit rw=P2^1; // 读写
sbit rs=P2^0; // 数据/命令
sbit busy=P0^7; // 检测忙
sbit BUZZ=P2^3; // 蜂鸣器
sbit DHT11=P1^0;// DHT11
sbit START=P1^1;
sbit NEXT=P1^3;
sbit JIA=P1^5;
sbit JIAN=P1^7;
uchar setup[10]={20,1,1,1,0,0,0,0,0,0};
uint M_sec,M_min,M_hour;
uint t;
uchar t_H,t_L;
uchar H_1,H_2,T_1,T_2;
code unsigned int toneH[7]={ //音调对应的定时器计数值的高8位 中音1,2,3,4,5,6,7
0XF9,0XF9,0XFA,0XFA,0XFB,0XFB,0XFC
};
code unsigned int toneL[7]={ //音调对应的定时器计数值的低8位
0X21,0XE1,0X8C,0XD8,0X68,0XE9,0X5B
};
code unsigned int soundtone[42]={ //小星星乐谱-音调
1,1,5,5,6,6,5,4,4,3,3,2,2,1,
5,5,4,4,3,3,2,5,5,4,4,3,3,2,
1,1,5,5,6,6,5,4,4,3,3,2,2,1
};
code unsigned int soundlong[42]={ //小星星乐谱-节拍
1,1,1,1,1,1,2,1,1,1,1,1,1,2,
1,1,1,1,1,1,2,1,1,1,1,1,1,2,
1,1,1,1,1,1,2,1,1,1,1,1,1,2
};
/*************************************************
函数名:send()
说明:发送一个字节uchar数据
入口参数:txd(发送的数据)
返回值:无
**************************************************/
void send(uchar txd)
{
uchar i;
for(i=0;i<8;i++)
{
sclk=0;
io=txd&0x01; // 取第一位
txd>>=1; // 左移一位
sclk=1; // 上升沿有效
}
}
/*************************************************
函数名:write()
说明:写地址、数据
入口参数:addr(DS1302地址);dat(写入的数据)
返回值:无
**************************************************/
void write(uchar addr,uchar dat)
{
rst=0;sclk=0;rst=1;
send(addr); // 发送地址
send(dat); // 发送数据
rst=1;
}
/*************************************************
函数名:receive()
说明:接收1个字节uchar数据
入口参数:无
返回值:dat
**************************************************/
uchar receive()
{
uchar i;
uchar dat=0;
for(i=0;i<8;i++)// 循环8次
{
sclk=1;
dat>>=1;
sclk=0; // 下降沿读取
io=1; // 读引脚前置1
if(io==1)dat|=0x80;
} // 此时dat为16进制比如0x10
dat=(dat/16)*10+dat%16;
// 转化为10进制,现在是10;
return(dat); // 返回值
}
/*************************************************
函数名:read()
说明:读时钟
入口参数:addr(地址)
返回值:dat(接受到的一字节uchar数据)
**************************************************/
uchar read(uchar addr)
{
uchar dat=0;
rst=0;sclk=0;rst=1;
send(addr); // 发送地址
dat=receive(); // 接收
rst=0;
return(dat);
}
/*************************************************
函数名:delay()
说明:延时函数
入口参数:n
返回值:无
**************************************************/
void delay(uint n)
{
uint i;
for(;n>0;n--)
for(i=200;i>0;i--);
}
/*************************************************
函数名:check()
说明:判断LCD是否忙
入口参数:无
返回值:无
**************************************************/
void check()
{
rs=0;
rw=1; // 读 e=1;
port=0x00;
e=1;
while(busy);
e=0;
}
/*************************************************
函数名:sendcommand()
说明:LCD写指令
入口参数:command(一个字节uchar的指令)
返回值:无
**************************************************/
void sendcommand(uchar command)
{
check();
rs=0; // 指令
rw=0; // 写 e=0;
port=command;
e=1;
_nop_();_nop_();
e=0; // 写入指令
}
/*************************************************
函数名:writedata()
说明:LCD写数据
入口参数:dat(一个字节uchar数据)
返回值:无
**************************************************/
void writedata(uchar dat)
{
check();
rs=1; // 数据
rw=0;
port=dat;
e=1;
_nop_();_nop_();
e=0;
}
/*************************************************
函数名:pos()
说明:设置LCD光标位置
入口参数:p(一个字节的无符号整型)
返回值:无
**************************************************/
void pos(uint p)
{
sendcommand(p|0x80);// 第一行第一个 0x80;
}
/*************************************************
函数名:init()
说明:初始化LCD
入口参数:无
返回值:无
**************************************************/
void init()
{
sendcommand(0x38); // 8 位数据,双列, 5*7 字形
delay(1);
sendcommand(0x0c); // 开 0x08 关
delay(1);
sendcommand(0x06);// 地址增加一
delay(1);
sendcommand(0x01);// 清屏
delay(1);
}
/*************************************************
函数名:welcome_setup()
说明:设置时的LCD初始界面
入口参数:无
返回值:无
**************************************************/
void welcome_setup()
{
int i=0;
uchar Date[]="Date:";
uchar Time[]="Time:";
uchar Week[]="Week:";
uchar Alarm[]="Alarm:";
init();delay(10);
pos(0x00);delay(1);
while(Date[i]!='\0') {writedata(Date[i++]);delay(1); }
i=0;delay(10);
pos(0x10);delay(1);
while(Week[i]!='\0') {writedata(Week[i++]);delay(1); }
i=0;delay(10);
pos(0x40);delay(1);
while(Time[i]!='\0') {writedata(Time[i++]);delay(1); }
i=0;delay(10);
pos(0x50);delay(1);
while(Alarm[i]!='\0') {writedata(Alarm[i++]);delay(1);}
}
/*************************************************
函数名:welcome()
说明:LCD初始界面
入口参数:无
返回值:无
**************************************************/
void welcome()
{
int i=0;
uchar Date[]="Date:";
uchar Time[]="Time:";
uchar Week[]="Week:";
uchar H[]="H:";
uchar T[]="T:";
init();delay(10);
pos(0x00);delay(1);
while(Date[i]!='\0') {writedata(Date[i++]);delay(1); }
i=0;delay(10);
pos(0x10);delay(1);
while(Week[i]!='\0') {writedata(Week[i++]);delay(1); }
i=0;delay(10);
pos(0x40);delay(1);
while(Time[i]!='\0') {writedata(Time[i++]);delay(1); }
i=0;delay(10);
pos(0x50);delay(1);
while(H[i]!='\0') {writedata(H[i++]);delay(1);}
i=0;delay(10);
pos(0x57);delay(1);
while(T[i]!='\0') {writedata(T[i++]);delay(1);}
}
/*************************************************
函数名:showLCD()
说明:读取时间和日期并在LCD上显示
入口参数:无
返回值:无
**************************************************/
void showLCD()
{
uchar num[]="0123456789";
uchar sign=':';
uchar note='-';
delay(5);pos(0x05);
delay(1);writedata(num[setup[0]/10]);
delay(1);writedata(num[setup[0]%10]);
delay(1);writedata(note);
delay(1);writedata(num[setup[1]/10]);
delay(1);writedata(num[setup[1]%10]);
delay(1);writedata(note);
delay(1);writedata(num[setup[2]/10]);
delay(1);writedata(num[setup[2]%10]);
delay(5);pos(0x15);
delay(1);writedata(num[setup[3]%10]);
delay(5);pos(0x45);
delay(1);writedata(num[setup[4]/10]);
delay(1);writedata(num[setup[4]%10]);
delay(1);writedata(sign);
delay(1);writedata(num[setup[5]/10]);
delay(1);writedata(num[setup[5]%10]);
delay(1);writedata(sign);
delay(1);writedata(num[setup[6]/10]);
delay(1);writedata(num[setup[6]%10]);
delay(5);pos(0x56);
delay(1);writedata(num[setup[7]/10]);
delay(1);writedata(num[setup[7]%10]);
delay(1);writedata(sign);
delay(1);writedata(num[setup[8]/10]);
delay(1);writedata(num[setup[8]%10]);
delay(1);writedata(sign);
delay(1);writedata(num[setup[9]/10]);
delay(1);writedata(num[setup[9]%10]);
}
/*************************************************
函数名:writeLCD()
说明:读取时间和日期并在LCD上显示
入口参数:无
返回值:无
**************************************************/
void writeLCD()
{
uchar num[]="0123456789";
uchar sign=':';
uchar note='-';
delay(5);pos(0x05);
delay(1);writedata(num[read(0x8d)/10]);
delay(1);writedata(num[read(0x8d)%10]);
delay(1);writedata(note);
delay(1);writedata(num[read(0x89)/10]);
delay(1);writedata(num[read(0x89)%10]);
delay(1);writedata(note);
delay(1);writedata(num[read(0x87)/10]);
delay(1);writedata(num[read(0x87)%10]);
delay(5);pos(0x15);
delay(1);writedata(num[read(0x8B)%10]);
delay(1);writedata(' ');
delay(1);writedata(num[M_hour/10]);
delay(1);writedata(num[M_hour%10]);
delay(1);writedata(sign);
delay(1);writedata(num[M_min/10]);
delay(1);writedata(num[M_min%10]);
delay(1);writedata(sign);
delay(1);writedata(num[M_sec/10]);
delay(1);writedata(num[M_sec%10]);
delay(5);pos(0x45);
delay(1);writedata(num[read(0x85)/10]);
delay(1);writedata(num[read(0x85)%10]);
delay(1);writedata(sign);
delay(1);writedata(num[read(0x83)/10]);
delay(1);writedata(num[read(0x83)%10]);
delay(1);writedata(sign);
delay(1);writedata(num[read(0x81)/10]);
delay(1);writedata(num[read(0x81)%10]);
delay(5);pos(0x52);
delay(1);writedata(num[H_1]);
delay(1);writedata(num[H_2]);
delay(1);writedata('R');
delay(1);writedata('H');
delay(5);pos(0x59);
delay(1);writedata(num[T_1]);
delay(1);writedata(num[T_2]);
delay(1);writedata(0XDF);
delay(1);writedata(0X43);
}
/*************************************************
函数名:Delay_us()/Delay_ms()
说明:DHT11延时程序
入口参数:无
返回值:无
**************************************************/
void Delay_us(unsigned char n)//n us延时函数 精度 ±4us
{
n=n/2;
while(--n);
}
void Delay_ms(unsigned int n)//n毫秒延时
{
unsigned char j;
while(n--)
{
for(j=0;j<125;j++);
}
}
/*************************************************
函数名:COM()
说明:接收DHT11数据
入口参数:无
返回值:comdata数据
**************************************************/
uchar COM(void)
{
uchar i,temp,comdata;
for(i=0;i<8;i++)
{
while(!DHT11); //表示读取的高电位延时大于20多us 则读取的是1 否则读取的是0
Delay_us(35); //通过FLAG,可判断DHT11显示数据的脉长
temp=0;
if(DHT11)temp=1;
while(DHT11);
comdata<<=1;
comdata|=temp;
}
return comdata;
}
/*************************************************
函数名:getDHT11()
说明:主机发送起始信号,获取温、湿度值并校验
入口参数:无
返回值:无
**************************************************/
void getDHT11(void)
{
uchar T_data_H,T_data_L,RH_data_H,RH_data_L,checkdata;
//主机拉低18ms
GO1:DHT11=0;
Delay_ms(18);
DHT11=1;
//总线由上拉电阻拉高 主机延时20us
Delay_us(20);
//主机设为输入 判断从机响应信号
//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(!DHT11)
{
while(!DHT11); //wait DHT goto high
while(DHT11);
//数据接收状态
RH_data_H=COM();
RH_data_L=COM();
T_data_H=COM();
T_data_L=COM();
checkdata=COM();
DHT11=1;
//数据校验
if((T_data_H+T_data_L+RH_data_H+RH_data_L)!=checkdata) //if check wrong,read again
goto GO1;
}
H_1=RH_data_H/10;
H_2=RH_data_H%10;
T_1=T_data_H/10;
T_2=T_data_H%10;
}
/*************************************************
函数名:Count_Time()
说明:计时
入口参数:无
返回值:无
**************************************************/
void init_Ex1() {
EA = 1; //开启总中断
EX1 = 1; //开启0号外部中断
IT1 = 0; //设置外部中断触发方式
//0 - 低电平触发
//1 - 负跳变触发
}
void ex1_intr() interrupt 2 {
M_sec=read(0x81); //读秒寄存器
M_min=read(0x83); //读分寄存器
M_hour=read(0x85);//读时寄存器
}
/*************************************************
函数名:init_T0()
说明:初始化定时器0
入口参数:无
返回值:无
**************************************************/
void init_T0(void)
{
TMOD|= 0x01; //使用方式1,16位定时器
TH0=0x00; //给TH0和TL0赋初值,计数器由0开始计数,到65535溢出
TL0=0x00;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=0; //关闭定时器
}
/*************************************************
函数名:T0_ISR()
说明:定时器0中断服务程序
入口参数:无
返回值:无
**************************************************/
void T0_ISR(void) interrupt 1
{
TH0=t_H; //给TH0和TL0重新赋值
TL0=t_L;
BUZZ=~BUZZ; //BUZZ的值取反,改变蜂鸣器的状态。
}
/*************************************************
函数名:alarm()
说明:闹铃
入口参数:h(小时),m(分钟),s(秒)
返回值:无
**************************************************/
void alarm(int h,int m,int s)
{
int sec,min,hour;
sec=read(0x81); //读秒寄存器
min=read(0x83); //读分寄存器
hour=read(0x85);//读时寄存器
if((sec==0)&(min==0))
{
t_H=0XFC;
t_L=0X5B;
TR0=1; //打开定时器,蜂鸣器发声
Delay_ms(50);
BUZZ=0; //蜂鸣器不发声,停顿片刻
TR0=0;
}
if((hour==h)&(min==m)&(sec==s))
for(t=0;t<42;t++)
{
getDHT11();
writeLCD();
t_H=toneH[soundtone[t]];//提取音调对应的定时器初始值
t_L=toneL[soundtone[t]];//提取音调对应的定时器初始值
TH0=t_H; //给TH0和TL0赋值
TL0=t_L;
TR0=1; //打开定时器,蜂鸣器发声
Delay_ms(soundlong[t]*200); //延时soundlong[t]指定的时间长度
BUZZ=0; //蜂鸣器不发声,停顿片刻
TR0=0;
Delay_ms(1);
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
Keil代码与Proteus仿真下载:
数字电子钟.7z
(62.8 KB, 下载次数: 88)
2022-11-9 18:25 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
666777888484
时间:
2023-4-21 11:12
需要用Proteus8.13版本来打开
作者:
666777888484
时间:
2023-4-21 11:12
那个Proteus是那个版本的呢
作者:
51dpjc
时间:
2023-4-26 08:24
能看得到完整的代码吗
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1