当前位置:   article > 正文

基于MCS-51单片机的数字时钟设计_基于mcs51单片机的时钟设计

基于mcs51单片机的时钟设计

基于MCS-51单片机的数字时钟设计

源码链接

项目面试问题
C/C++/嵌入式—面试题汇总

一、项目描述

1.基于DS1302时钟模块,可以完成年、月、日、时、分、秒、周的正确显示。
2.可以通过外部按键对当前时间进行校准。
3.能够以12小时和24小时制表示方式显示时间。
4.能够通过外部按键设置闹钟提醒时间。

实际操作:
LCD1602显示时钟,按K3键进入时钟设置,此时秒钟停止走动,按K1键选择设置的秒、分、时、
日、月、星期、年,按K2键进行加1,设置完成后,再次按下K3键继续走时,按下K4进入闹钟
界面设置(在闹钟界面不能按下K3),K1进行选择时、分,K2进行加一,再按下K4返回时钟界面,
当时间走到设置时间时,蜂鸣器会响起大概五秒钟,之后继续走时。按下矩阵按键P15进行12/24小时制切换。

二、项目功能展示

1.日期显示
在这里插入图片描述
2.闹钟时间设置
在这里插入图片描述
3.二十四小时制显示
在这里插入图片描述
在这里插入图片描述
4.十二小时制显示
在这里插入图片描述在这里插入图片描述

三、代码展示

在这里插入图片描述

1、main.c

/*******************************************************************************
参考LCD1602液晶显示实验接线图
参考DS1302时钟实验接线图
K1-->P31
K2-->P30
K3-->P32
K4-->P33(该按键未做功能,可扩展)

实验操作:
LCD1602显示时钟,按K3键进入时钟设置,此时秒钟停止走动,按K1键选择设置的秒、分、时、
日、月、星期、年,按K2键进行加1,设置完成后,再次按下K3键继续走时,按下K4进入闹钟
界面设置(在闹钟界面不能按下K3),K1进行选择时、分,K2进行加一,再按下K4返回时钟界面,
当时间走到设置时间时,蜂鸣器会响起大概五秒钟,之后继续走时。
按下矩阵按键P15进行12/24小时制切换。 

此时开机时钟默认为12:00:55,闹钟时间为12:01(分)
*******************************************************************************/

#include <reg51.h>
#include "lcd.h"
#include "ds1302.h"

#define GPIO_KEY P1

sbit K1=P3^1;
sbit K2=P3^0;
sbit K3=P3^2;
sbit K4=P3^3;	 //管脚接线
sbit beep=P1^5;

sbit line=P1^4;
sbit list1=P1^3;
sbit list2=P1^2;

sbit led1=P2^0;
sbit led2=P2^1;
sbit led3=P2^2;
sbit led4=P2^3;
sbit led5=P2^4;

void Int0Configuration();
void LcdDisplay();
void DisplayTime();
void DisplayClock();
void write_sfm(uchar add,uchar date);
unsigned char toCompare();
unsigned char SetState,SetPlace,SetClock;
bit ClockPlace;
bit ClockFlag;
void Delay10ms(void);   //误差 0us

unsigned char C_shi=12,C_fen=1;
int count = 0;
uint APM = 0;	   //为0时表示24小时制,为1时表示上午,为2时表示下午
int temp = 0;	   //为0时表示24小时制,为1时表示12小时制
uint h=0x23;    //默认初始24小时制
uint key;
uint key_num;//键盘扫描值,键盘键值

/*******************************************************************************
* 函数名         : main
* 函数功能		   : 主函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void delay(uint i)
{
	while(i--);
}

void main()
{	
    
    uint keynum();
	unsigned char result;
	unsigned int i;
	unsigned int time = 1500;
	Int0Configuration();
	LcdInit();
	Ds1302Init();
	while(1)
	{
		key=16;
        key = keynum();
		
        if(key==7)		//检测按键K2是否按下
		{   
		    led5=0;
			delay(20000);
			led5=1;
			Delay10ms();	//消除抖动
			if(key==7)
			{	
			    led5=0;
			    delay(20000);
			    led5=1;
				SetPlace=2;

				 
				if((TIME[SetPlace]>=0x0c) && (temp==0))		
				{
				    /*LcdWriteCom(0x80+0x40+10);
   	                LcdWriteData('P');LcdWriteData('M');   */
					TIME[SetPlace]=TIME[SetPlace]-18;
					APM = 2;
					temp = 1;	
				}
				else if((TIME[SetPlace]<0x0c)  &&  (temp==0))
				{	  
				    /*LcdWriteCom(0x80+0x40+10);
   	                LcdWriteData('A');LcdWriteData('M'); */
				    APM = 1;
					temp = 1;
				}
				else if((TIME[SetPlace]<0x0c)  &&  (APM==2))
				{
				    /*LcdWriteCom(0x80+0x40+10);
   	                LcdWriteData(' ');LcdWriteData(' ');*/
					TIME[SetPlace]=TIME[SetPlace]+18;
				    APM = 0;
					temp = 0;
				}
				else if((TIME[SetPlace]<0x0c)  &&  (APM==0))
				{
				    /*LcdWriteCom(0x80+0x40+10);
   	                LcdWriteData('A');LcdWriteData('M'); */
				    APM = 1;
					temp = 1;
				}
				else if((TIME[SetPlace]<0x0c)  &&  (APM==1))
				{
				    /*LcdWriteCom(0x80+0x40+10);
   	                LcdWriteData(' ');LcdWriteData(' '); */
					APM = 0;
					temp = 0;
				}
			 }

			while((i<50)&&(key==7))	 //检测按键是否松开
			{
				Delay10ms();
				i++;
			}
			i=0;
			
		}  

         if(APM == 0)
		{
		    LcdWriteCom(0x80+0x40+10);
   	        LcdWriteData(' ');LcdWriteData(' '); 
		}
		else if(APM == 1)
		{
		    LcdWriteCom(0x80+0x40+10);
   	        LcdWriteData('A');LcdWriteData('M'); 
		}
		else if(APM == 2)
		{
		    LcdWriteCom(0x80+0x40+10);
   	        LcdWriteData('P');LcdWriteData('M');
		}

		if(ClockFlag)
		{
			while(time>0)
			{
				time--;
				beep=0;
				i=150;
				while(i>0)
				{
					i--;
				}
				beep=1;
				i=150;
				while(i>0)
				{
					i--;
				}
			}
		}
		if(K4==0)
		{
		    led4=0;
			delay(20000);
			led4=1;
			Delay10ms();	//消除抖动
			if(K4==0)
			{
				while(!K4);	//等待按键释放
				SetClock = ~SetClock;
				LcdWriteCom(0x01);  //清屏
			}
		}
		if(SetClock == 0)
		{	
			DisplayTime();
			result=toCompare();	
			if(result)	//闹钟响起
				ClockFlag=1;
				
		}	
		else
			DisplayClock();			
	}	
}

/********************************************************************/
//函数名:delay_1ms(uint x)
//功能:利用定时器0精确定时1ms; 自加 time_t的值为后面时间调整函数服务
//调用函数:
//输入参数:x,1ms计数
//输出参数:
//说明:延时的时间为1ms乘以x
/********************************************************************/
void delay_1ms(uint x)
{
	TMOD=0X01;//开定时器0,工作方式为1
	TR0=1;//启动定时器0;
	while(x--)
	{
		TH0=0Xfc;//定时1ms初值的高8位装入TH0
		TL0=0X18;//定时1ms初值的低8位装入TL0
		while(!TF0);//等待,直到TF0为1
		TF0=0;
	}		
	TR0=0;//停止定时器0;
}


/**********************************************************/
//函数名:keyscan()
//功能:得出4x4键盘的行列扫描值
//调用函数:delay_1ms(uint x)
//输入参数:
//输出参数:
//说明:通过P1口的扫描得出扫描值key,无键按下key为16
/**********************************************************/
uchar keyscan()
{
 	uchar code_h;		//行扫描值
	uchar code_l;		//列扫描值
	P1=0XF0;			 //P1.0-P1.3全为0,(行状态全为低电平)
	if((P1&0xF0)!=0XF0)	//如果P1.4-P1.7不全为1,可能有键按下(为准确识别按键动作)
	{
	    delay_1ms(5);	//廷时去抖动,为准确识别按键动作
	    if((P1&0xF0)!=0XF0)//重读高4位(列状态),若还是不全为1,定有键按下
            {			
	        code_h=0xfe;  //开始行扫描 (0xfe:11111110)
	        while((code_h&0x10)!=0x00)//判断是否扫描四行(X0~X3)完毕,若不是,继续扫描(0x10:00010000)	 
               {
	           P1=code_h;	//第1次P1.0置为0,其余高电平;第2次P1.1置为0,其余高电平	;第3次P1.2置为0,其余高电平;第4次P1.3置为0,其余高电平
	           if((P1&0xF0)!=0XF0) //如果P1.4-P1.7不全为1,该行有键按下(0xF0:11110000)
                   {
		       		code_l=(P1&0xF0|0x0F);//保留P1口高4位,低4位变为1,作为列值
		       		return((~code_h)+(~code_l));//键盘编码=行扫描值+列扫描值 (取反后用,相当于改为按下按键对应的行、列标识为1,其它为0)				 
	           }
	           else                           //左移后补0,但是我们需要将其他位置1,所以+1
		       		code_h=(code_h<<1)|0x01;  //若该行无键按下,行扫描值左移+1,扫描下一行 
	         }
	     }
	 }
	return(16);	 //无键按下,返回16 
 }

/**********************************************************/
//函数名:keynum()
//功能:得出4x4按键的键值
//调用函数:keyscan()
//输入参数:
//输出参数:
//说明:通过key的值确定按键键值
/**********************************************************/
uint keynum()
{
    int i=0,j=0;
    int tab[4][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11},{12,13,14,15}}; 
    //4x4键盘各键值标注
    key=16;
    key = keyscan();//引入key值
    if((key&0x01)!=0) i=0;	//判断出按下按键的行列号 (即找出低电平的行、列)
    if((key&0x02)!=0) i=1;
    if((key&0x04)!=0) i=2;
    if((key&0x08)!=0) i=3;
    if((key&0x10)!=0) j=0;
    if((key&0x20)!=0) j=1;
    if((key&0x40)!=0) j=2;
    if((key&0x80)!=0) j=3;
	key_num=key;
    if(key!=16) 
    {
   		key_num = tab[i][j];//通过比较得出4x4键盘的键值
    } 
	return key_num; 
}



/*******************************************************************************
* 函数名         : toCompare()
* 函数功能		 : 比较闹钟和时钟
* 输入           : 无
* 输出         	 : 0:时间不同		1:时间相同
*******************************************************************************/
unsigned char toCompare()
{
	unsigned char shi,fen;
	shi = (TIME[2]/16)*10 + TIME[2]&0x0f;
	fen = (TIME[1]/16)*10 + TIME[1]&0x0f;
	if((shi==C_shi)&&(fen==C_fen))
		return 1;
	else
		return 0;
}

/*******************************************************************************
* 函数名         : DisplayClock()
* 函数功能		 : 闹钟显示的函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void DisplayClock()
{	
	LcdInit();
	LcdWriteCom(0x80);
	LcdWriteData('C');LcdWriteData('l');LcdWriteData('o');LcdWriteData('c');LcdWriteData('k');LcdWriteData(':');
	
	if(K1==0)
	{
	    led1=0;
		delay(20000);
		led1=1;
	    
		Delay10ms();
		if(K1==0)
		{
		    led1=0;
			delay(20000);
			led1=1;
			while(!K1);	//等待按键释放
		   	ClockPlace = ~ClockPlace;
		}		
	}
	if(K2==0)
	{
	    led2=0;
		delay(2000);
		led2=1;
		Delay10ms();
		if(K2==0)
		{
		    led2=0;
			delay(20000);
			led2=1;
			while(!K2);
			if(ClockPlace == 0)
			{
				C_shi++;
				if(C_shi>23)
					C_shi=0;
				LcdWriteCom(0x80+0x40+6);
				LcdWriteCom(0x0f);
			}
			if(ClockPlace == 1)
			{
				C_fen++;
				if(C_fen>59)
					C_fen=0;
				LcdWriteCom(0x80+0x40+9);
				LcdWriteCom(0x0f);
			}
		}	
	}
	Delay10ms();
	LcdWriteCom(0x80+0x40+7);LcdWriteData(':');
	Delay10ms();
	write_sfm(5,C_shi);
	Delay10ms();
	write_sfm(8,C_fen);
	Delay10ms();
}

void write_sfm(uchar add,uchar date)	//在液晶上写时分秒
{
	uchar shi,ge;
	shi=date/10;
	ge=date%10;
	LcdWriteCom(0x80+0x40+add);		//说明显示位置
	LcdWriteData(shi+0x30);
	LcdWriteData(ge+0x30);
}

/*******************************************************************************
* 函数名         : DisplayTime()
* 函数功能		 : 时钟显示的函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void DisplayTime()
{
	unsigned char i;
	if(SetState==0)
	{
		Ds1302ReadTime();
	}
	else	//key3按下,进入校准界面
	{	
		count=0;

        if(temp==0)
		{
		    h = 0x23 ;		   	//此时为24小时制
		}
		else if(temp==1)
		{
		    h = 0x11;		   //此时为12小时制
		}

		if(K1==0)		//检测按键K1是否按下
		{
		    led1=0;
			delay(20000);
			led1=1;
			Delay10ms();	//消除抖动
			if(K1==0)
			{
		        led1=0;
			    delay(20000);
			    led1=1;	    
				SetPlace++;
				if(SetPlace>=7)
					SetPlace=0;
									
			}

			while((i<50)&&(K1==0))	 //检测按键是否松开
			{
				Delay10ms();
				i++;
			}
			i=0;
		}
		if(K2==0)		//检测按键K2是否按下
		{   
		    led2=0;
			delay(20000);
			led2=1;
			Delay10ms();	//消除抖动
			if(K2==0)
			{	
			    led2=0;
			    delay(20000);
			    led2=1;
				TIME[SetPlace]++;
				if((TIME[SetPlace]&0x0f)>9)					 //换成BCD码。
				{
					TIME[SetPlace]=TIME[SetPlace]+6;
				}
				if((TIME[SetPlace]>=0x60)&&(SetPlace<2))		//分秒只能到59
				{
					TIME[SetPlace]=0;
				}
				if((TIME[SetPlace]>h)&&(SetPlace==2))		//小时只能到23
				{
					TIME[SetPlace]=0;
					if(APM==1)
					{
					    APM=2;
					}
					else if(APM==2)
					{
					    APM=1;
					}
					
				}
				if((TIME[SetPlace]>=0x32)&&(SetPlace==3))		//日只能到31
				{
					TIME[SetPlace]=0;	
				}
				if((TIME[SetPlace]>=0x13)&&(SetPlace==4))		//月只能到12
				{
					TIME[SetPlace]=0;
				}	
				if((TIME[SetPlace]>=0x7)&&(SetPlace==5))		//周只能到7
				{
					TIME[SetPlace]=1;
				}		
//					if(SetPlace==5)		//月只能到12
//					{
//						TIME[SetPlace]=;
//					}	
			}
			
			while((i<50)&&(K2==0))	 //检测按键是否松开
			{
				Delay10ms();
				i++;
			}
			i=0;
			
		}
		key=16;
        key = keynum();
		
		if(key==4)		//检测减键是否按下
			{
			led3=0;
			delay(20000);
			led3=1;
				Delay10ms();	//消除抖动
				if(key==4)
				{
				led3=0;
			    delay(20000);
			    led3=1;
			    if(TIME[SetPlace]==0x00)
				{
				    count=1;
				}
				else if((TIME[SetPlace]&0x0f)==0x00)
				{
				   	   TIME[SetPlace]=TIME[SetPlace]-6;
				}
					TIME[SetPlace]--;
					//if(TIME[SetPlace]<0)					 //换成BCD码。
					//{
					//	TIME[SetPlace]=TIME[SetPlace]+10;
					//}
					if((count==1)&&(SetPlace<2))		//分秒只能到59
					{
						TIME[SetPlace]=0x59;
					}
					if((count==1)&&(SetPlace==2))		//小时只能到h
					{
						TIME[SetPlace]=h;
						if(APM==1)
					    {
					        APM=2;
					    }
					    else if(APM==2)
					    {
					    APM=1;
					    }
					}
					if((TIME[SetPlace]<=0x00)&&(SetPlace==3))		//日只能到31
					{
						TIME[SetPlace]=0x31;	
					}
					if((TIME[SetPlace]<=0x00)&&(SetPlace==4))		//月只能到12
					{
						TIME[SetPlace]=0x12;
					}	
					if((TIME[SetPlace]<=0x00)&&(SetPlace==5))		//周只能到7
					{
						TIME[SetPlace]=0x07;
					}		
//					if(SetPlace==5)		//月只能到12
//					{
//						TIME[SetPlace]=;
//					}	
				}

				
				while((i<50)&&(key==4))	 //检测按键是否松开
				{
					Delay10ms();
					i++;
				}
				i=0;	
			} 
								
	}
	LcdDisplay();	
}


/*******************************************************************************
* 函数名         : LcdDisplay()
* 函数功能		   : 显示函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/

void LcdDisplay()
{
	LcdWriteCom(0x80+0X40);
	LcdWriteData('0'+TIME[2]/16);				//时
	LcdWriteData('0'+(TIME[2]&0x0f));				 
	LcdWriteData('-');
	LcdWriteData('0'+TIME[1]/16);				//分
	LcdWriteData('0'+(TIME[1]&0x0f));	
	LcdWriteData('-');
	LcdWriteData('0'+TIME[0]/16);				//秒
	LcdWriteData('0'+(TIME[0]&0x0f));

	LcdWriteCom(0x80);
	LcdWriteData('2');
	LcdWriteData('0');
	LcdWriteData('0'+TIME[6]/16);			//年
	LcdWriteData('0'+(TIME[6]&0x0f));
	LcdWriteData('-');
	LcdWriteData('0'+TIME[4]/16);			//月
	LcdWriteData('0'+(TIME[4]&0x0f));
	LcdWriteData('-');
	LcdWriteData('0'+TIME[3]/16);			//日
	LcdWriteData('0'+(TIME[3]&0x0f));
	LcdWriteCom(0x8D);
	LcdWriteData('0'+(TIME[5]&0x07));	//星期			 
}
/*******************************************************************************
* 函数名         : Int0Configuration()
* 函数功能		   : 配置外部中断0
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/

void Int0Configuration()
{
	//设置INT0
	IT0=1;//跳变沿出发方式(下降沿)
	EX0=1;//打开INT0的中断允许。
	EA=1;//打开总中断	
}
/*******************************************************************************
* 函数名         : Int0() 
* 函数功能		   : 外部中断0 中断函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/

void Int0() interrupt 0		 
{
	Delay10ms();
	//keynum();
	if(K3==0)
	{
	    led3=0;
		delay(20000);
		led3=1;
		SetState=~SetState;
		SetPlace=0;
		Ds1302Init();	
	}
}
/*******************************************************************************
* 函数名         : Delay10ms
* 函数功能		   : 延时函数,延时10ms
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Delay10ms(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577
  • 578
  • 579
  • 580
  • 581
  • 582
  • 583
  • 584
  • 585
  • 586
  • 587
  • 588
  • 589
  • 590
  • 591
  • 592
  • 593
  • 594
  • 595
  • 596
  • 597
  • 598
  • 599
  • 600
  • 601
  • 602
  • 603
  • 604
  • 605
  • 606
  • 607
  • 608
  • 609
  • 610
  • 611
  • 612
  • 613
  • 614
  • 615
  • 616
  • 617
  • 618
  • 619
  • 620
  • 621
  • 622
  • 623
  • 624
  • 625
  • 626
  • 627
  • 628
  • 629
  • 630
  • 631
  • 632
  • 633
  • 634
  • 635
  • 636
  • 637
  • 638
  • 639
  • 640
  • 641
  • 642
  • 643
  • 644
  • 645
  • 646
  • 647
  • 648
  • 649
  • 650
  • 651
  • 652
  • 653
  • 654
  • 655
  • 656
  • 657
  • 658

2、led.c

#include"lcd.h"

/*******************************************************************************
* 函 数 名         : Lcd1602_Delay1ms
* 函数功能		   : 延时函数,延时1ms
* 输    入         : c
* 输    出         : 无
* 说    明         : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/

void Lcd1602_Delay1ms(uint c)   //误差 0us
{
    uchar a,b;
	for (; c>0; c--)
	{
		 for (b=199;b>0;b--)
		 {
		  	for(a=1;a>0;a--);
		 }      
	}
    	
}

/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能		   : 向LCD写入一个字节的命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
#ifndef 	LCD1602_4PINS	 //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com)	  //写入命令
{
	LCD1602_E = 0;     //使能
	LCD1602_RS = 0;	   //选择发送命令
	LCD1602_RW = 0;	   //选择写入
	
	LCD1602_DATAPINS = com;     //放入命令
	Lcd1602_Delay1ms(1);		//等待数据稳定

	LCD1602_E = 1;	          //写入时序
	Lcd1602_Delay1ms(5);	  //保持时间
	LCD1602_E = 0;
}
#else 
void LcdWriteCom(uchar com)	  //写入命令
{
	LCD1602_E = 0;	 //使能清零
	LCD1602_RS = 0;	 //选择写入命令
	LCD1602_RW = 0;	 //选择写入

	LCD1602_DATAPINS = com;	//由于4位的接线是接到P0口的高四位,所以传送高四位不用改
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;	 //写入时序
	Lcd1602_Delay1ms(5);
	LCD1602_E = 0;

//	Lcd1602_Delay1ms(1);
	LCD1602_DATAPINS = com << 4; //发送低四位
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;	 //写入时序
	Lcd1602_Delay1ms(5);
	LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能		   : 向LCD写入一个字节的数据
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/		   
#ifndef 	LCD1602_4PINS		   
void LcdWriteData(uchar dat)			//写入数据
{
	LCD1602_E = 0;	//使能清零
	LCD1602_RS = 1;	//选择输入数据
	LCD1602_RW = 0;	//选择写入

	LCD1602_DATAPINS = dat; //写入数据
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;   //写入时序
	Lcd1602_Delay1ms(5);   //保持时间
	LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat)			//写入数据
{
	LCD1602_E = 0;	  //使能清零
	LCD1602_RS = 1;	  //选择写入数据
	LCD1602_RW = 0;	  //选择写入

	LCD1602_DATAPINS = dat;	//由于4位的接线是接到P0口的高四位,所以传送高四位不用改
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;	  //写入时序
	Lcd1602_Delay1ms(5);
	LCD1602_E = 0;

	LCD1602_DATAPINS = dat << 4; //写入低四位
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;	  //写入时序
	Lcd1602_Delay1ms(5);
	LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能		 : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/		   
#ifndef		LCD1602_4PINS
void LcdInit()						  //LCD初始化子程序
{
 	LcdWriteCom(0x38);  //开显示
	LcdWriteCom(0x0c);  //开显示不显示光标
	LcdWriteCom(0x06);  //写一个指针加1
	LcdWriteCom(0x01);  //清屏
	LcdWriteCom(0x80);  //设置数据指针起点
}
#else
void LcdInit()						  //LCD初始化子程序
{
	LcdWriteCom(0x32);	 //将8位总线转为4位总线
	LcdWriteCom(0x28);	 //在四位线下的初始化
	LcdWriteCom(0x0c);  //开显示不显示光标
	LcdWriteCom(0x06);  //写一个指针加1
	LcdWriteCom(0x01);  //清屏
	LcdWriteCom(0x80);  //设置数据指针起点
}
#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135

3、ds1302.c

#include"ds1302.h"

//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; 
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0x55, 0, 0x12, 0x23, 0x03, 0x02, 0x21};

/*******************************************************************************
* 函 数 名         : Ds1302Write
* 函数功能		   : 向DS1302命令(地址+数据)
* 输    入         : addr,dat
* 输    出         : 无
*******************************************************************************/

void Ds1302Write(uchar addr, uchar dat)
{
	uchar n;
	RST = 0;
	_nop_();

	SCLK = 0;//先将SCLK置低电平。
	_nop_();
	RST = 1; //然后将RST(CE)置高电平。
	_nop_();

	for (n=0; n<8; n++)//开始传送八位地址命令
	{
		DSIO = addr & 0x01;//数据从低位开始传送
		addr >>= 1;
		SCLK = 1;//数据在上升沿时,DS1302读取数据
		_nop_();
		SCLK = 0;
		_nop_();
	}
	for (n=0; n<8; n++)//写入8位数据
	{
		DSIO = dat & 0x01;
		dat >>= 1;
		SCLK = 1;//数据在上升沿时,DS1302读取数据
		_nop_();
		SCLK = 0;
		_nop_();	
	}	
		 
	RST = 0;//传送数据结束
	_nop_();
}

/*******************************************************************************
* 函 数 名         : Ds1302Read
* 函数功能		   : 读取一个地址的数据
* 输    入         : addr
* 输    出         : dat
*******************************************************************************/

uchar Ds1302Read(uchar addr)
{
	uchar n,dat,dat1;
	RST = 0;
	_nop_();

	SCLK = 0;//先将SCLK置低电平。
	_nop_();
	RST = 1;//然后将RST(CE)置高电平。
	_nop_();

	for(n=0; n<8; n++)//开始传送八位地址命令
	{
		DSIO = addr & 0x01;//数据从低位开始传送
		addr >>= 1;
		SCLK = 1;//数据在上升沿时,DS1302读取数据
		_nop_();
		SCLK = 0;//DS1302下降沿时,放置数据
		_nop_();
	}
	_nop_();
	for(n=0; n<8; n++)//读取8位数据
	{
		dat1 = DSIO;//从最低位开始接收
		dat = (dat>>1) | (dat1<<7);
		SCLK = 1;
		_nop_();
		SCLK = 0;//DS1302下降沿时,放置数据
		_nop_();
	}

	RST = 0;
	_nop_();	//以下为DS1302复位的稳定时间,必须的。
	SCLK = 1;
	_nop_();
	DSIO = 0;
	_nop_();
	DSIO = 1;
	_nop_();
	return dat;	
}

/*******************************************************************************
* 函 数 名         : Ds1302Init
* 函数功能		   : 初始化DS1302.
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void Ds1302Init()
{
	uchar n;
	Ds1302Write(0x8E,0X00);		 //禁止写保护,就是关闭写保护功能
	for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
	{
		Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);	
	}
	Ds1302Write(0x8E,0x80);		 //打开写保护功能
}

/*******************************************************************************
* 函 数 名         : Ds1302ReadTime
* 函数功能		   : 读取时钟信息
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void Ds1302ReadTime()
{
	uchar n;
	for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
	{
		TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
	}
		
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136

4.DS1302.H

#ifndef __DS1302_H_
#define __DS1302_H_

//---包含头文件---//
#include<reg51.h>
#include<intrins.h>

//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint 
#define uint unsigned int
#endif

//---定义ds1302使用的IO口---//
sbit DSIO=P3^4;
sbit RST=P3^5;
sbit SCLK=P3^6;

//---定义全局函数---//
void Ds1302Write(uchar addr, uchar dat);
uchar Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302ReadTime();

//---加入全局变量--//
extern uchar TIME[7];	//加入全局变量

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

5、LCD.H

#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS

/**********************************
包含头文件
**********************************/
#include<reg51.h>

//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint 
#define uint unsigned int
#endif

/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;

/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c);   //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/	
void LcdWriteData(uchar dat);
/*LCD1602初始化子程序*/		
void LcdInit();						  

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/408607
推荐阅读
相关标签
  

闽ICP备14008679号