1-基于AT89C52单片机的多功能电子万年历闹钟设计(复杂、串口、空气质量、温湿度、LCD12864、矩阵按键、闹钟)
功能详细描述:
1.电子万年历能实时显示年、月、日、星期、时、分、秒
2.能通过蜂鸣器实现报警功能,当设定的报警时钟和当时时钟数值相等时,蜂鸣器发出报警声,报警时长5s
3.温度、湿度检测
4.控制质量检测,通过ADC0832实现功能
5.串口输出温度、湿度、控制质量信息,模拟远程传输或语音播报的功能。
6.使用矩阵键盘实现人机交互功能。
7.使用DS1302实现时钟功能。
8.闹钟的控制开关。
9.追求复杂功能,全部IO口均使用完。
资料包含:
1、原理图工程文件及对应PDF文档,使用Altium Designer可以打开
2、源代码可以使用带有C51编译链的keil4或keil5打开运行
3、仿真工程,使用proteus运行
4、赠送的流程图与元器件清单
void disp_num(uchar a)//显示2个数字
{
find(a>>4);q=p;
find(a&0x0f);
}
uchar key_scan()//按键检测
{
uchar i,j;
i=0;
j=0;
P1=0x0f;
if(P1!=0x0f) //检测有无按下
{
switch(P1)//检测行
{
case 0x0e:i=1;break;
case 0x0d:i=5;break;
case 0x0b:i=9;break;
case 0x07:i=13;
}
P1=0xf0;
switch(P1)//检测列
{
case 0xe0:j=0;break;
case 0xd0:j=1;break;
case 0xb0:j=2;break;
case 0x70:j=3;
}
while(P1!=0xf0);//等待按键松开
}
return i+j;
}
//主函数
void main()
{
uchar i,j,k;
Ds1302ReadTime();//初始化DS1302
TIME[0]=0;
Ds1302Init();
UART_init();
lcd_init(); // 初始化
lcd_clear(0); // 清屏
lcd_set_line(0); // 设置起始行为0
TMOD|=0X01;
TH0=0X3C;
TL0=0XB0;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
while (1)
{
// printf_String();
//printf("hello \r\n");
k=key_scan();//按键检测
if(k==1)//年加
{
i=(TIME[6]>>4)*10+(TIME[6]&0X0F);
if(i<99)
i++;
TIME[6]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==2)//年减
{
i=(TIME[6]>>4)*10+(TIME[6]&0X0F);
if(i>0)
i--;
TIME[6]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==3)//月加
{
i=(TIME[4]>>4)*10+(TIME[4]&0X0F);
if(i<12)
i++;
TIME[4]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==4)//月减
{
i=(TIME[4]>>4)*10+(TIME[4]&0X0F);
if(i>1)
i--;
TIME[4]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==5)//日加
{
i=(TIME[3]>>4)*10+(TIME[3]&0X0F);
if(i<30)
i++;
TIME[3]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==6)//日减
{
i=(TIME[3]>>4)*10+(TIME[3]&0X0F);
if(i>1)
i--;
TIME[3]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==11)//星期加
{
i=(TIME[5]>>4)*10+(TIME[5]&0X0F);
if(i<7)
i++;
TIME[5]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==12)//星期减
{
i=(TIME[5]>>4)*10+(TIME[5]&0X0F);
if(i>1)
i--;
TIME[5]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==7)//时加
{
i=(TIME[2]>>4)*10+(TIME[2]&0X0F);
if(i<23)
i++;
TIME[2]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==8)//时减
{
i=(TIME[2]>>4)*10+(TIME[2]&0X0F);
if(i>0)
i--;
TIME[2]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==9)//分加
{
i=(TIME[1]>>4)*10+(TIME[1]&0X0F);
if(i<59)
i++;
TIME[1]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==10)//分减
{
i=(TIME[1]>>4)*10+(TIME[1]&0X0F);
if(i>0)
i--;
TIME[1]=(i/10<<4)+i%10;
Ds1302Init();
}
if(k==13)//闹钟时加
{
if(nao_shi<23)
nao_shi++;
}
if(k==14)//闹钟时减
{
if(nao_shi>0)
nao_shi--;
}
if(k==15)//闹钟分加
{
if(nao_fen<59)
nao_fen++;
}
if(k==16)//闹钟分减
{
if(nao_fen>0)
nao_fen--;
}
//闹钟判断
if(flag==0)
{
i=(TIME[2]>>4)*10+(TIME[2]&0X0F);
j=(TIME[1]>>4)*10+(TIME[1]&0X0F);
if((i==nao_shi)&&(j==nao_fen))
{
if(TIME[0]==0)
beep=0;
if(TIME[0]==0x59)
beep=1;
}
}
if(!k1)//闹钟开关
{
beep=1;
flag=!flag;
while(!k1);
}
if(!k2)//闹钟停止
beep=1;
}
}
//定时器0中断
void Timer0() interrupt 1
{
uint i=0;
if(sec<20) //显示控制
sec++;
else
{
sec=0;
Ds1302ReadTime();
dht11_recive();//测量温湿度
i=ADC(1);//测量空气质量
i=i*99/127;
air=99-i;
printf("空气质量:%c%c μg/m3\r\n",air/10+0x30,air%10+0x30);
shidu=dht11_dat[0];
wendu=dht11_dat[2];
printf("湿度:%c%c %%\r\n",shidu/10+0x30,shidu%10+0x30);
printf("温度:%c%c ℃\r\n",dht11_dat[2]/10+0x30,dht11_dat[2]%10+0x30);
// wendu=Ds18b20ReadTemp();
//显示日期
lcd_clear(0); // 清屏
lcd_set_line(0); // 设置起始行为0
display_num(1, 0,1 * 16, num2 , num0); //20
disp_num(TIME[6]);
display_num(1, 0,2 * 16, q , p);//年
display(1,0,3*16,mao);
disp_num(TIME[4]);
display_num(2, 0,4 * 16, q , p);//月
display(2,0,5*16,mao);
disp_num(TIME[3]);
display_num(2, 0,6 * 16, q , p);//日
disp_num(TIME[2]);
display_num(1, 2,2 * 16, q , p);//时
display(1,2,3*16,mao);
disp_num(TIME[1]);
display_num(2, 2,4 * 16, q , p);//分
display(2,2,5*16,mao);
disp_num(TIME[0]);
display_num(2, 2,6 * 16, q , p);//秒
display(1,4,0*16,str3);//星期
display(1,4,1*16,str4);
switch(TIME[5])
{
case 1:display(1,4,2*16,xin7);break;
case 2:display(1,4,2*16,xin1);break;
case 3:display(1,4,2*16,xin2);break;
case 4:display(1,4,2*16,xin3);break;
case 5:display(1,4,2*16,xin4);break;
case 6:display(1,4,2*16,xin5);break;
case 7:display(1,4,2*16,xin6);
}
//温度
find(shidu/10);q=p;
find(shidu%10);
display_num(2, 4,5 * 16, q , p);
find(wendu/10);q=p;
find(wendu%10);
display_num(2, 4,3 * 16, q , p);
//
//
find(air/10);q=p;
find(air%10);
// display_num(2, 4, 2 * 16, q , p);
// display_num(2, 4,7 * 16, q , p);
//display_num(2, 4,5 * 16, q , p);
// display(2,4,6*16,str5);
display(1,6,0*16,str1);//闹钟
display(1,6,1*16,str2);
display(1,6,2*16,mao);
find(nao_shi/10);q=p;
find(nao_shi%10);
display_num(1, 6,3 * 16, q , p);
display(2,6,4*16,mao);
find(nao_fen/10);q=p;
find(nao_fen%10);
display_num(2, 6,5 * 16, q , p);
//闹钟开关
if(flag==0)
{
display_num(2,6,7*16,char1,char2);
}
else
{
display_num(2,6,6*16,kong,char1);
display_num(2,6,7*16,char3,char3);
}
}
TH0=0X3C;
TL0=0XB0;
}