方案设计:本设计项目主要由stc89c52单片机控制模块、oled显示模块、数码管、DHT11温湿度传感器模块、蜂鸣器等来实现的电子时钟与温湿度监测设计。
功能描述:
1、使用定时器实现电子时钟计时
2、温湿度监测
3、按键控制时分秒加减设置时间
4、设置闹钟或温湿度到达一定值后蜂鸣器发出声音提醒
模块介绍:
stc89c52单片机:STC89C52 是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。使用高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,也适于常规编程器,拥有灵巧的8位CPU和在线系统可编程Flash。原理图如下:
oled显示模块:OLED显示,无需背光灯,屏幕又轻又薄,可视角度大,并且能够节约电能,操作简单,可以显示字符,可以用于标明光照单位等其他信息。选择OLED可以显示一些其他内容并且能够快速刷新数据。其自身可以发光,功耗低。我们使用的一般是分辨率为 128×64 ,屏幕尺寸为 0.96 寸,目前我使用的这个SPI协议(7线)的OLED屏幕,其较小的尺寸和比较高的分辨率,让它有着很好的显示效果和便携性,使用3-5V的电源进行供电。可以使用取模软件进行取模显示自己需要的字或数字,然后通过程序控制进行显示。
数码管:使用4位8段数码管显示分、秒的显示,通过采用9012三极管高低电平信号来进行控制数码管的亮灭、通断状态。数码管显示原理与LED灯显示原理一样,数码管也可以通过发光二极管工作,我们通过二进制进行计算数码管,转换成十六进制写进程序,显示出我们想要的效果。
蜂鸣器:通过程序控制P32口的高低电平,来实现三极管的开关作用,之所以通过三极管的发射极引导电流进入集电极,而不是用P32直接加到蜂鸣器上,是因为单片机的功率很小,虽然可以输出很高的电压,但是是无法驱动这种功率器件的。当P32口输出低电平时,此时三极管导通,所以蜂鸣器发出声音,用于我们闹钟的设置,当输出高电平时,蜂鸣器无响应。
主要程序:
#include<reg52.h>
#include "DHT11.H"
#include"intrins.h"
#include "OLED.H"
//数码管定义口
sbit SMG1=P2^4;
sbit SMG2=P2^5;
sbit SMG3=P2^6;
sbit SMG4=P2^7;
//蜂鸣器定义口
sbit Beep=P3^2;
//开关定义口
sbit key=P1^0;
sbit key1=P1^1;
sbit key2=P1^2;
sbit key3=P1^3;
sbit key4=P1^4;
unsigned char fen =59;
unsigned char miao = 30;//定义时分秒
unsigned char shi=23;
unsigned char R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
void Init_Timer0(void);
unsigned char code SMG_duanma[]=
{0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
void delayms(unsigned int xms)
{
unsigned int i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void Delay1000ms()
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void display()
{
SMG1=0;//第一个数码管显示
P0=SMG_duanma[fen/10];
delayms(5);//延时5ms
SMG1=1;
P0&=0xff;//消影
SMG2=0;//第二个数码管显示
P0=SMG_duanma[fen%10];
delayms(5);
SMG2=1;
P0&=0xff;
SMG3=0;//第三个数码管显示
P0=SMG_duanma[miao/10];
delayms(5);
SMG3=1;
P0&=0xff;
SMG4=0;//第四个数码管显示
P0=SMG_duanma[miao%10];
delayms(5);
SMG4=1;
P0&=0xff;
}
void main()
{
Init_Timer0();
OLED_Init();
OLED_Clear();
while(1)
{
unsigned int n=50;
while(n--)
{
display();
}
DHT11_Start();
if(DATA==0)
{
while(!DATA);
while(DATA);
R_H=DHT11_rec_byte();
R_L=DHT11_rec_byte();
T_H=DHT11_rec_byte();
T_L=DHT11_rec_byte();
revise=DHT11_rec_byte();
}
if((R_H+R_L+T_H+T_L)==revise)
{
RH=R_H;
RL=R_L;
TH=T_H;
TL=T_L;
//湿度
OLED_ShowCHinese(0,0,10);
OLED_ShowCHinese(20,0,11);
OLED_ShowChar(36,0,':');
OLED_ShowNum(54,0,RH,2,16);
OLED_ShowString(74,0,"%RH");
//温度
OLED_ShowCHinese(0,2,8);
OLED_ShowCHinese(20,2,9);
OLED_ShowChar(36,2,':');
OLED_ShowNum(54,2,TH,2,16);
OLED_ShowChar(70,2,'.');
OLED_ShowNum(74,2,TL,2,16);
OLED_ShowCHinese(90,2,7);
//时钟
OLED_ShowCHinese(40,4,12);
OLED_ShowCHinese(56,4,13);
OLED_ShowChar(74,4,':');
OLED_ShowNum(0,6,shi/10,2,16);
OLED_ShowNum(16,6,shi%10,2,16);
OLED_ShowChar(33,6,':');
OLED_ShowNum(36,6,fen/10,2,16);
OLED_ShowNum(52,6,fen%10,2,16);
OLED_ShowChar(69,6,':');
OLED_ShowNum(72,6,miao/10,2,16);
OLED_ShowNum(88,6,miao%10,2,16);
}
/*
if(key==0) //按键按下并松开分钟加1
{
delayms(5);
while(!key);
fen++;
if(fen==60) //加到60后置为清零
{
fen=0;
shi++;
}
}
if(key1==0)
{
delayms(5);
while(!key1);
fen--;
if(fen==0)
{
shi--;
}
}
if(key4==0) //按键复位\全部清零
{
delayms(5);
shi=fen=miao=0;
while(!key4);
delayms(5);
}
*/
}
}
void Init_Timer0(void)
{
TMOD |= 0x01;
//TH0=0x00; //给定初值
//TL0=0x00;
TH0=(65536-2000)/256;//重新赋值 2ms
TL0=(65536-2000)%256;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1;
}
void Timer0_isr(void) interrupt 1
{
static unsigned int num;
TH0=(65536-2000)/256;//重新赋值 2ms
TL0=(65536-2000)%256;
num++;
if(num==500) //大致1s
{
num=0;
miao++;
if(miao==60) //秒到60,分钟加1
{
miao=0;
fen++;
if(fen==60) //分钟到60,小时加1
{
fen=0;
shi++;
if(shi==24) //小时到24,回零
shi=0;
}
}
}
}
PCB 3D图:
源码、PCB、原理图、关注后私聊!