基于51单片机的lcd1602万年历设计_温度+闹钟心得

基于51单片机的lcd1602万年历设计_温度+闹钟心得

下载地址
https://download.youkuaiyun.com/download/weixin_44017446/10908985
当看到这个学习项目的时候,我是一脸的蒙,没办法我还是一个小白,一个刚接触单片机没多久的小菜鸟。
看到这东西我第一想到的就是这该怎么做,有毒吧,好难啊,一点思路都没有,lcd1602好吧这个玩过,ds1302好吧这个也写过,ds18b20咦这个有点难,看那手册就觉得好难,时序图看不懂,到后面看懂了,好吧我延时一直弄不好,所以显示的温度都是负数(-0.06),看着就懵逼,没这么冷吧,换个芯片,噢,插反了,烧了,唉在插一个咯,后来经历过一系列的调试,终于弄好。好了需要的模块已经准备好,开始把他们组合起来,…好吧,它们两跟我作对,在一起就行不通了,什么哦,算了,去网上找找经验,哦原来使能冲突了,emmmm,好啦,它可以了,两个像兄弟一样和平共处,一起显示出来了。
主界面准备好了,切换界面直接用独立按键就好了,这个容易。
我是用4个按键来做的

#ifndef __KEY_H
#define __KEY_H
 
#include "sys.h"
#include "delay.h"
 
 
#define KEYPORT P1  //   四个按键接在了P1口的四个引脚#define NO_KEY   0xf0#define K1    0X01#define K2    0X02#define K3    0X03#define K4   0X04#define KEYSUB    0X02#define KEYADD    0X01#define KEYSET    0X04#define KEYNEXT   0X03 //K1,2,3,4,和这些是一样的,只是写.c文件时#define LONGCNT  150#define SHORTCNT 12
#define K1 1
#define K2 2
#define K3 3
#define K4 4 
 
 
 uchar key_scan();


#endif
#include"key.h"
sbit KeyPort0=P1^4;
sbit KeyPort1=P1^5;						
sbit KeyPort2=P1^6;
sbit KeyPort3=P1^7;	
 
/************************************************************************
函数名称:key_scan()
函数功能:4个独立按键检测
输入参数:无
返回值:KeyV		通过返回值的不同来确定哪个按键被按下
*************************************************************************/ 
uchar key_scan()
{
	uchar KeyV;
	KEYPORT=0xff;		
	if(KeyPort0==0||KeyPort1==0||KeyPort2==0||KeyPort3==0)		//判断是否有按键按下
	//而是从锁存器读的,一直是0xff
	{
		delay_ms(10);		//防止抖动
		 if(KeyPort0==0)		//判断哪个按键被按下
		{	
			KeyV=K1;
		}
		else if(KeyPort1==0)
		{
			KeyV= K2;
		}
		else if(KeyPort2==0)
		{	
			KeyV=K3;
		}
		else if(KeyPort3==0)
		{
			KeyV=K4;
		}
		}
		else 
		{
			KeyV= 0;
		}		  			//判断哪个按键被按下//
		
//		if(KeyV != 0)		//有按键按下时,进行松手检测(不知道为什么,这里一直有毒,反正就是实现不了)
 //             while(KeyPort0==0||KeyPort1==0||KeyPort2==0||KeyPort3==0);
		//delay_ms(10);		//延时消抖
   
 
    return KeyV;			//返回KeyV来标识哪一个按键被按下
}


嗯,按键也就这样了,反正行得通就好了。
接下来,lcd1602,ds1302,ds18b20,嗯网上找,一大堆,我就不贴了,
把需要改的地方贴一下

uchar DS1302Read(uchar addr)
{
	uchar i,dat,dat1;
	DSCE=0;
	_nop_();
	SCLK=0;
	_nop_();
	DSCE=1;
	_nop_();
	for(i=0;i<8;i++)
	{
		DSIO=addr&0x01;
		addr>>=1;
		SCLK=1;
		_nop_();
		SCLK=0;
		_nop_();
	}
	_nop_();
	for(i=0;i<8;i++)
	{
		dat1=DSIO;		
		dat=(dat>>1)|(dat1<<7);
		SCLK=1;
		_nop_();
		SCLK=0;
		_nop_();
	}
//	DSCE=0;							//把这个注释掉就好了    sbit DSCE=P3^5;
	_nop_();
	SCLK=1;
	DSIO=0;
	_nop_();
	DSIO=1;
	_nop_();
	return dat;
}

ok!
然后就是一大堆按键处理了
一个一个界面写吧,先把进入和出来的先写好,然后在写里面的功能。
烦哦,一大堆的东西,花了我4天的时间。
/****** 主界面显示 ******/
/2018年01月01日 P 星期五/
/12:01:01 温度:20C 闹钟开关/

/****** 主界面按键功能 ******/
/******key1: 进入设置 ******/
/******key2: 加 ******/
/******key3: 减 ******/
/******key4: 打开闹钟 ******/

/****** 功能选择 ******/
/******1:timeSet ******/
/******2: alarmSet /
/
按键功能 ******/
/******key1: 进入设置 ******/
/******key2: 加 ******/
/******key3: 减 ******/
/******key4: 退出设置 ******/

/****** 时间设置 ******/
/key1: 选择设置位置/
/******key2: 加 ******/
/******key3: 减 ******/
/******key4: 退出设置 ******/

/****** 闹钟设置 /
/
+:增加,-:删除 ******/
/******key1: 确定选择 ******/
/******key2: 选择设置位置加1 ******/
/******key3: 选择设置位置减1 ******/
/******key4: 退出设置 ******/

/****** 闹钟x ******/
/******key1: 选择设置 (时间,开关,重复/不重复,选择音乐)******/
/******key2: 加1 ******/
/******key3: 减一 ******/
/******key4: 退出设置 ******/

/****** 重复/不重复 ******/
/******key2: 重复 ******/
/******key3: 不重复 ******/

/****** 重复 ******/
/key1:选择设置位置/
/******key2: 开启重复 ******/
/******key3: 关闭重复 ******/
/******key4: 退出设置 ******/

/****** 不重复 ******/
/key1:选择设置位置/
/******key2: 开启 ******/
/******key3: 关闭 ******/
/******key4: 退出设置 ******/

嗯,这是所有的按键处理的思路,
主函数吧,把闹钟需要的参数返回给它处理就好了。

#include "sys.h"
#include "delay.h"
#include "lcd1602.h"
#include "temp.h"
#include "ds1302.h"
#include "keyProcess.h"
#include "otherProcess.h"
#include "musicCode.h"
#define RldTmr(fr) 65536 - (11059200 / 12) / (fr << 1)
#define FuDian(n) (n << 1) / 3    //附点n分音符的换算
sbit beep = P2^0;

uchar Temp_TH0,Temp_TL0;
uchar Temp_TH1,Temp_TL1; 
uchar tmrFlg=0,enable = 1;
extern uint mflag;	  //音符计算
extern bit nflag;
extern bit aflag;	  //闹钟开关
extern uchar a;
extern uchar b;

void PlayMusic(uchar *Sound,uchar *lengthlen,uint speed);    //固定标准为4分音符的速度:例如speed = 108 表示一分钟扫过108个4分音符
void sound_Init();
uint length(uchar *Sound);			 //判断音符个数
uint mflag;							 //音符循环个数
bit nflag=0;						 //1分钟关闭闹钟暂停标志
bit aflag=1;	//总开关
uchar stop[7];	//暂停标志位

uchar a;	   //闹钟x
uchar b;	   //重复检测
void main()
{
	uchar mode;	   
	stop[0]=1;	   //暂停标志位
	stop[1]=1;
	stop[2]=1;
	stop[3]=1;
	stop[4]=1;
	stop[5]=1;
	stop[6]=1;
	Clock=0;	   //初始闹钟个数
	
	LCD1602_Init();	   //1602初始化
	DS1302_Init();	   //1302初始化
	sound_Init();	   //定时器初始化
	
	while(1)
	{	
		/**********按键处理***********/	
		if(key_scan()==K1||key_scan()==K2||key_scan()==K3||key_scan()==K4)
		{				
			switch (key_scan())
			{	
				case K1: mode=MODE0;break;		//MODE0进入菜单
				case K2: mode=MODE1;break;		//MODE0设置日期
				case K3: mode=MODE2;break;		//MODE0设置闹钟
				case K4: mode=MODE3;aflag=!aflag;break;		//MODE3退出
			}
			key_process(mode);				   //按键处理函数
		}
		/**********主屏幕显示**********/		
		LCD1602_DisplayTemp(DS18B20_ReadTemp());	 //温度
		DS1302_ReadTime();							 //读时间
		LCD1602_DisplayData();						 //显示时间
		if(AM_PM==0&&hour12_24==1)					 //显示上午
		{
			LCD1602_WriteCom(0x80+13);
			LCD1602_WriteData('A');
		}
		if(AM_PM==1&&hour12_24==1)					 //显示下午
		{
			LCD1602_WriteCom(0x80+13);
			LCD1602_WriteData('P');
		}											 //24小时制
		if(hour12_24==0)
		{
			LCD1602_WriteCom(0x80+13);
			LCD1602_WriteData(' ');
		}
		LCD1602_WriteCom(0xc0+15);					 //显示闹钟开关
		if(aflag)
			LCD1602_WriteData('N');
		else 
			LCD1602_WriteData('F');
		/**********闹钟设置**********/
		if(aflag==1)
		{
		for(a=0;a<=Clock;a++)			 //检测闹钟
		{
			if(alarm[a][2]==1)		 //判断闹钟是否开启
			{
				if(alarm[a][3]==1)	  //判断是否重复 alarm[a][3]==1为重复
				{
					for(b=0;b<7;b++)		//判断周是否重复
					{
					 if(TIME[5]==b+1&&repeat[a][b]==1)	  //	repeat[a][0]		  重复天数星期一到星期日
					 {
						 if((alarm[a][0]==TIME[1]&&alarm[a][1]==TIME[2]))	   //alarm[0][0]=分钟 alarm[0][1]=小时	
						{
							nflag=1;
							switch(alarm[a][4])
							{
								case 0:	   PlayMusic(musicNote5,noteDuration5,108);	  break;
								case 1:	   PlayMusic(musicNote1,noteDuration1,108);	  break;
								case 2:	   PlayMusic(musicNote2,noteDuration2,108);	  break;
								case 3:	   PlayMusic(musicNote3,noteDuration3,108);	  break;
								case 4:	   PlayMusic(musicNote4,noteDuration4,108);	  break;
							
							}
					
						}
						else
							stop[a]=1;
					}
					}
				} 
				else
				{
					for(b=0;b<7;b++)
					{
					 if(TIME[5]==b+1&&repeat[a][b]==1)	  //	repeat[a][0]		  重复天数星期一到星期日
					 {
						 if((alarm[a][0]==TIME[1]&&alarm[a][1]==TIME[2]))	   //alarm[0][0]=分钟 alarm[0][1]=小时	
						{
							switch(alarm[a][4])
							{
								case 0:	   PlayMusic(musicNote5,noteDuration5,108);	  break;
								case 1:	   PlayMusic(musicNote1,noteDuration1,108);	  break;
								case 2:	   PlayMusic(musicNote2,noteDuration2,108);	  break;
								case 3:	   PlayMusic(musicNote3,noteDuration3,108);	  break;
								case 4:	   PlayMusic(musicNote4,noteDuration4,108);	  break;
							
							}
					
						}
						else
							stop[a]=1;
					}
					}
				}
		}
		}
		}
		else
		{
			 beep=1;TR0=0;
		}
//		LCD1602_WriteCom(0xc0+15);
//		if(stop[a]==1)
//		{
//			LCD1602_WriteData('1');	
//		}
//		else
//			LCD1602_WriteData('0');
		delay_ms(10);
	}

}

延时函数,嗯还算可以吧,不准确

#ifndef __DELAY_H
#define __DELAY_H
#include "sys.h"
#define uchar unsigned char
#define uint unsigned int 
void delay_ms(uint i);
void delay_us(uchar x);
#endif

#include "delay.h"
void delay_ms(uint i)
{
	uchar n;
 	while(i--)
	for(n=0;n<80;n++)
	;
}
void delay_us(uchar x)	//x*5 us
{
    uchar a,b;
    for(b=x;b>0;b--)
        for(a=1;a>0;a--);
}

那个按键处理函数太多了,不好贴,
可以去GitHub看看吧,我都放那了
MCU_alarm搜一下

下载地址
https://download.youkuaiyun.com/download/weixin_44017446/10908985

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值