2019-09-06 18:41:00 weixin_44477509 阅读数 582
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4007 人正在学习 去看看 朱有鹏

基于51单片机的电子钟设计

设计要求:
(1) 电源采用12V电池供电;
(2) 采用MCS-51单片机控制,画出控制系统的硬件电路图,并设计PCB板;
(3) 编制控制程序,并画出程序框图,并用Preteus软件进行仿真;
设计内容:
(1) 24进制时间显示;
(2) 调时功能;
(3) 闹钟功能;
(4) 照明功能;
本文附了部分代码和图片展示,全文档请下载!

void main()
{
 TMOD=0x01;
 TH0=(65536-50000)/256;
 TL0=(65536-50000)/256;
 EA=1;
 ET0=1;
 TR0=1;
 option=0;
 alarmflag1=0;
 hour0=0,minute0=0,sceond0=0,hour1=0,minute1=0,sceond1=0,hour2=0,minute2=0;
 while(1)
 {
  functionchoice();
  lightfunction();
  alarmfunction();
  delay();
 }
}
/*******功能选择*******/
void functionchoice()
{
 if(P1_3==1)
  key0=1;
 if(P1_3==0&&key0==1)
 {
  key0=0;
  option++; 
  if(option==3)
   option=0; 
 }
 if(option==0)
 {
  hour1=hour0,minute1=minute0,sceond1=sceond0;
  TR0=1;
  timecontrol();
  timeshow(hour0,minute0,sceond0);
  delay();
 }  
 if(option==1)
 {
  hour0=hour1,minute0=minute1,sceond0=sceond1;
  TR0=0;
  keycontrol(hour1,minute1,sceond1);
  hour1=t[2],minute1=t[1],sceond1=t[0];
  timeshow(hour1,minute1,sceond1);
  delay();
 }
 if(option==2)
 {
  TR0=0;
  keycontrol(hour2,minute2,sceond2);
  hour2=t[2],minute2=t[1],sceond2=t[0];
  timeshow(hour2,minute2,sceond2);
  delay();
 }   
}

PCB电路印刷板设计

电路原理图设计
全文档连接:https://download.csdn.net/download/weixin_44477509/11683217

2018-12-19 22:27:36 lin5103151 阅读数 1468
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4007 人正在学习 去看看 朱有鹏

电子万年历是一种非常广泛日常计时工具,给人们的带来了很大的方便,在社会上越来越流行。 它可以对年、月、日、时、分、秒进行计时,采用直观的数字显示,可以同时显示年月日时分秒和温度等信息,还有时间校准、闹钟等功能。该电子万年历主要采用STC89C52单片机作为主控核心,用DS1302时钟芯片作为时钟、液晶12864显示屏显示。STC89C52单片机是由宏晶公司推出的,功耗小,电压可选用4~6V电压供电;DS1302时钟芯片是美国DALLAS公司推出的具有细电流充电功能的低功耗实时时钟芯片,它可以对年、月、日、星期、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小;数字显示是采用的12864液晶显示屏来显示,可以同时显示年、月、日、星期、时、分、秒和温度等信息。此外,该电子万年历还具有时间校准等功能。

1. 系统总体功能
本设计采用的是宏晶公司的STC89C52单片机为核心,通过单片机与时钟芯片DS1302通信来对时间的读写,保证时钟时间的稳定性,并带有内部电源模块,使系统断电时时钟数据不会丢失,以DS18B20温度感应芯片作为温度电路的核心,向单片机发出获取到的温度数据,并通过LCD1602将时间、显示出来,并可以通过按键调整时间日期和闹钟时间。

2. 总体电路图
在这里插入图片描述
电路组成:

  1. 单片机最小系统
  2. LCD602液晶显示屏电路
  3. 四路独立按键
  4. DS1302时钟电路
  5. DS18B20温度传感器
  6. 系统电源

3. 程序设计
(1) LCD1602驱动程序

sbit rs		= P2^0;
sbit rw		= P2^1;
sbit e  	= P2^2;
#define lcddata P0
sbit busy=P0^7;   //lcd busy bit
void wr_d_lcd(uchar content);
void wr_i_lcd(uchar content);
void clrram_lcd (void);
void init_lcd(void);
void busy_lcd(void);
void rev_row_lcd(uchar row);
void rev_co_lcd(uchar row,uchar col,uchar mode);
void clr_lcd(void);
void wr_co_lcd(uchar row,uchar col,uchar lcddata1,uchar lcddtta2);
void wr_row_lcd(uchar row,char *p);
//**********************************
//液晶初始化
//**********************************
void init_lcd(void)
{
	wr_i_lcd(0x06);  /*光标的移动方向*/
	wr_i_lcd(0x0c);  /*开显示,关游标*/
}
//***********************************
//填充液晶DDRAM全为空格
//**********************************
void clrram_lcd (void)
{
	wr_i_lcd(0x30);
	wr_i_lcd(0x01);
}
//***********************************
//对液晶写数据
//content为要写入的数据
//***********************************
void wr_d_lcd(uchar content)
{
	busy_lcd();
	rs=1;
    rw=0;
	lcddata=content;
	e=1;
	;
	e=0;
}
//********************************
//对液晶写指令
//content为要写入的指令代码
//*****************************
void wr_i_lcd(uchar content)
{
	busy_lcd();
	rs=0;
    rw=0;
	lcddata=content;
	e=1;
	;
	e=0;
}
//********************************
//液晶检测忙状态
//在写入之前必须执行
//********************************
void busy_lcd(void)
{
  lcddata=0xff;
  rs=0;
  rw=1;
  e =1;
  while(busy==1);
  e =0;
}
//********************************
//指定要显示字符的坐标
//*******************************
void gotoxy(unsigned char y, unsigned char x)
{
	if(y==1)
		wr_i_lcd(0x80|x);
	if(y==2)
        wr_i_lcd(0x90|x);
	if(y==3)
		wr_i_lcd((0x80|x)+8);
	if(y==4)
        wr_i_lcd((0x90|x)+8);
}
//**********************************
//液晶显示字符串程序
//**********************************
void print(uchar *str)
{
	while(*str!='\0')
	{
		wr_d_lcd(*str);
		str++;
	}
}

//***************************************
//液晶显示主程序模块
//***************************************
void show_time()   
{
  DS1302_GetTime(&CurrentTime);  //获取时钟芯片的时间数据
  TimeToStr(&CurrentTime);       //时间数据转换液晶字符
  DateToStr(&CurrentTime);       //日期数据转换液晶字符
  ReadTemp();                    //开启温度采集程序
  temp_to_str();                 //温度数据转换成液晶字符
  gotoxy(4,0);
  print("温度");
  gotoxy(4,2);                  //液晶字符显示位置
  print(TempBuffer);             //显示温度
  gotoxy(4,6);
  print("℃");
  gotoxy(3,0);
  print("时间:");
  gotoxy(3,3);
  print(CurrentTime.TimeString); //显示时间
  gotoxy(2,3);
  print(CurrentTime.DateString); //显示日期
  gotoxy(2,0);
  print("星期");
  gotoxy(2,2);
  print(week_value);             //显示星期
  gotoxy(1,1);
  print("【万年历】");
  mdelay(500);                 //扫描延时
}

(2) DS1302驱动程序

//***********************************
//DS1302时钟部分子程序模块
//***********************************
typedef struct __SYSTEMTIME__
{
	uchar Second;
	uchar Minute;
	uchar Hour;
	uchar Week;
	uchar Day;
	uchar Month;
	uchar  Year;
	uchar DateString[11];
	uchar TimeString[9];
}SYSTEMTIME;	//定义的时间类型
SYSTEMTIME CurrentTime;


#define AM(X)	X
#define PM(X)	(X+12)            	  // 转成24小时制
#define DS1302_SECOND	0x80          //时钟芯片的寄存器位置,存放时间
#define DS1302_MINUTE	0x82
#define DS1302_HOUR		0x84 
#define DS1302_WEEK		0x8A
#define DS1302_DAY		0x86
#define DS1302_MONTH	0x88
#define DS1302_YEAR		0x8C 
//**********************************
//实时时钟写入一字节(内部函数)
//**********************************
void DS1302InputByte(uchar d) 	
{ 
    uchar i;
    ACC = d;
    for(i=8; i>0; i--)
    {
        DS1302_IO = ACC0;           	//相当于汇编中的 RRC
        DS1302_CLK = 1;
        DS1302_CLK = 0;
        ACC = ACC >> 1; 
    } 
}
//*************************************
//实时时钟读取一字节(内部函数)
//*************************************
uchar DS1302OutputByte(void) 	
{ 
    uchar i;
    for(i=8; i>0; i--)
    {
        ACC = ACC >>1;         			//相当于汇编中的 RRC 
        ACC7 = DS1302_IO;
        DS1302_CLK = 1;
        DS1302_CLK = 0;
    } 
    return(ACC); 
}
//**************************************
//ucAddr: DS1302地址, ucData: 要写的数据
//**************************************
void Write1302(uchar ucAddr, uchar ucDa)	
{
    DS1302_RST = 0;
    DS1302_CLK = 0;
    DS1302_RST = 1;
    DS1302InputByte(ucAddr);       	// 地址,命令 
    DS1302InputByte(ucDa);       	// 写1Byte数据
    DS1302_CLK = 1;
    DS1302_RST = 0;
} 
//**************************************
//读取DS1302某地址的数据
//**************************************
uchar Read1302(uchar ucAddr)	
{
    uchar ucData;
    DS1302_RST = 0;
    DS1302_CLK = 0;
    DS1302_RST = 1;
    DS1302InputByte(ucAddr|0x01);        // 地址,命令 
    ucData = DS1302OutputByte();         // 读1Byte数据
    DS1302_CLK = 1;
    DS1302_RST = 0;
    return(ucData);
}

//******************************************
//获取时钟芯片的时钟数据到自定义的结构型数组
//******************************************
void DS1302_GetTime(SYSTEMTIME *Time)  
{
	uchar ReadValue;
	ReadValue = Read1302(DS1302_SECOND);
	Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//转换为相应的10进制数
	ReadValue = Read1302(DS1302_MINUTE);
	Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
	ReadValue = Read1302(DS1302_HOUR);
	Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
	ReadValue = Read1302(DS1302_DAY);
	Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);	
	ReadValue = Read1302(DS1302_WEEK);
	Time->Week = ((ReadValue&0x10)>>4)*10 + (ReadValue&0x0F);
	ReadValue = Read1302(DS1302_MONTH);
	Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
	ReadValue = Read1302(DS1302_YEAR);
	Time->Year = ((ReadValue&0xf0)>>4)*10 + (ReadValue&0x0F);	
}
//******************************************
//将时间年,月,日,星期数据转换成液
//晶显示字符串,放到数组里DateString[]
//******************************************
void DateToStr(SYSTEMTIME *Time)    
{   
   uchar tab[ ]={0XD2,0XBB,0XB6,0XFE,0XC8,0XFD,0XCB,0XC4,0XCE,0XE5,0XC1,0XF9,0XC8,0XD5};
   if(hide_year<2)          //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
    {                               
	  Time->DateString[0] = '2';
	  Time->DateString[1] = '0';	 
	  Time->DateString[2] = Time->Year/10 + '0';
	  Time->DateString[3] = Time->Year%10 + '0';
	}
	  else
	    { 
	      Time->DateString[0] = ' ';
	      Time->DateString[1] = ' ';		 
	      Time->DateString[2] = ' ';
	      Time->DateString[3] = ' ';
		}
    Time->DateString[4]='-';
	if(hide_month<2)
	{
	  Time->DateString[5] = Time->Month/10 + '0';
	  Time->DateString[6] = Time->Month%10 + '0';
	}
	  else
	  {
	    Time->DateString[5] = ' ';
	    Time->DateString[6] = ' ';
	  }
    Time->DateString[7]='-';
	if(hide_day<2)
	{
	  Time->DateString[8] = Time->Day/10 + '0';
	  Time->DateString[9] = Time->Day%10 + '0';
	}
	  else
	  {
	    Time->DateString[8] = ' ';
	    Time->DateString[9] = ' ';	    
	  }
	if(hide_week<2)
	{
	  week_value[0] =tab[2*(Time->Week%10)-2];  //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
	  week_value[1] =tab[2*(Time->Week%10)-1];
	}
	  else
	  {
	    week_value[0] = ' ';
		week_value[1]=' ';
	  }
	  week_value[2] = '\0';

	Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符
}
//******************************************
//将时,分,秒数据转换成液晶
//显示字符放到数组 TimeString[]
//*****************************************
void TimeToStr(SYSTEMTIME *Time) 
{   if(hide_hour<2)
    {
	  Time->TimeString[0] = Time->Hour/10 + '0';
	  Time->TimeString[1] = Time->Hour%10 + '0';
	}
	  else
	    {
	      Time->TimeString[0] = ' ';
	      Time->TimeString[1] = ' ';
		}
	Time->TimeString[2] = ':';
    if(hide_min<2)
	{
	  Time->TimeString[3] = Time->Minute/10 + '0';
	  Time->TimeString[4] = Time->Minute%10 + '0';
	}
	  else
	    {
	      Time->TimeString[3] = ' ';
	      Time->TimeString[4] = ' ';
   	    }
	Time->TimeString[5] = ':';
    if(hide_sec<2)
    {
	  Time->TimeString[6] = Time->Second/10 + '0';
	  Time->TimeString[7] = Time->Second%10 + '0';
    }
      else
       {
         Time->TimeString[6] = ' ';
	     Time->TimeString[7] = ' ';
       }
	Time->TimeString[8] = '\0';
}

//******************************
//时钟芯片初始化
//******************************
void Initial_DS1302(void)   
{   
	uchar Second=Read1302(DS1302_SECOND);
	if(Second&0x80)	      //判断时钟芯片是否关闭	  
    {
	Write1302(0x8e,0x00); //写入允许
	Write1302(0x8c,0x07); //以下写入初始化时间 日期:07/07/25.星期: 3. 时间: 23:59:55
	Write1302(0x88,0x07);
	Write1302(0x86,0x25);
	Write1302(0x8a,0x07);
	Write1302(0x84,0x23);
	Write1302(0x82,0x59);
	Write1302(0x80,0x55);
	Write1302(0x8e,0x80); //禁止写入
	}

}

(3)DS18B20驱动程序

/***********ds18b20子程序*************************/

/***********ds18b20延迟子函数(晶振12MHz )*******/ 

void delay_18B20(unsigned int i)
{
	while(i--);
}

/**********ds18b20初始化函数**********************/

void Init_DS18B20(void) 
{
	 unsigned char x=0;
	 DQ = 1;          //DQ复位
	 delay_18B20(8);  //稍做延时
	 DQ = 0;          //单片机将DQ拉低
	 delay_18B20(40); //精确延时 大于 480us
	 DQ = 1;          //拉高总线
	 delay_18B20(7);
	 x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
	 delay_18B20(10);
}

/***********ds18b20读一个字节**************/  

uchar ReadOneChar(void)
{
	uchar i=0;
	uchar dat = 0;
	for (i=8;i>0;i--)
	 {
		  DQ = 0; // 给脉冲信号
		  dat>>=1;
		  DQ = 1; // 给脉冲信号
		  if(DQ)
		  dat|=0x80;
		  delay_18B20(4);
	 }
 	return(dat);
}

/*************ds18b20写一个字节****************/  

void WriteOneChar(uchar dat)
{
 	uchar i=0;
 	for (i=8; i>0; i--)
 	{
  		DQ = 0;
 		DQ = dat&0x01;
    	delay_18B20(5);
 		DQ = 1;
    	dat>>=1;
 }
}

/**************读取ds18b20当前温度************/

void ReadTemp(void)
{
	uchar a=0;
	uchar b=0;
	uchar t;

	Init_DS18B20();
	WriteOneChar(0xCC);    	// 跳过读序号列号的操作
	WriteOneChar(0x44); 	// 启动温度转换

	delay_18B20(100);       // this message is wery important

	Init_DS18B20();
	WriteOneChar(0xCC); 	//跳过读序号列号的操作
	WriteOneChar(0xBE); 	//读取温度寄存器等(共可读9个寄存器) 前两个就是温度

	delay_18B20(50);

	a=ReadOneChar();    	//读取温度值低位
	b=ReadOneChar();   		//读取温度值高位
	t=b&0xf8;
	if(t)
	{
	  TempBuffer[0]=':';
	  TempBuffer[1]='-';
  	  temp_value=b<<4;
	  temp_value+=(a&0xf0)>>4;  
	  temp_value=~temp_value+1;
	  temp1_value=~a&0x0f;
	}
	else
	{  
        temp_value=b<<4;
        temp_value+=(a&0xf0)>>4; 
		 temp1_value=a&0x0f;
	    TempBuffer[0]=':';
	    TempBuffer[1]=temp_value/100+'0';  //百位
       if(TempBuffer[1]=='1')
       {
            TempBuffer[1]='1';
       }
       else
       {
           TempBuffer[1]=' ';
       } 
    }
}
void temp_to_str()   //温度数据转换成液晶字符显示
{		

  TempBuffer[2]=temp_value%100/10+'0';  //十位
  TempBuffer[3]=temp_value%10+'0';  //个位
  TempBuffer[4]='.';
  TempBuffer[5]=temp1_value*625/1000%10+'0';
  TempBuffer[6]=temp1_value*625/100%10+'0';
  TempBuffer[7]=temp1_value*625/10%10+'0';
  //TempBuffer[8]=temp1_value*625%10+'0';
  TempBuffer[8]='\0';
}
//**********************************************
//延时子程序模块
//**********************************************
void mdelay(uint delay)
{	uint i;
 	for(;delay>0;delay--)
   		{for(i=0;i<80;i++) //1ms延时.
       		{;}
   		}
}

(4) 按键驱动程序

//************************************
//跳出调整模式,返回默认显示
//************************************
void outkey()                    
{ uchar Second;
  if(out==0)         
  { mdelay(5); 
	count=0;
	hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;
	Second=Read1302(DS1302_SECOND);
    Write1302(0x8e,0x00); //写入允许
	Write1302(0x80,Second&0x7f);
	Write1302(0x8E,0x80);          //禁止写入
	done=0;           
  }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//*************************
//升序按键
//*************************
void Upkey()
{	   
		Up=1;
	            if(Up==0)
		          {
				   mdelay(5);
				       switch(count)
				          {case 1:
                                  temp=Read1302(DS1302_SECOND);  //读取秒数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //秒数加1
                                  up_flag=1;    //数据调整后更新标志
								  if((temp)>59)   //超过59秒,清零
                                  temp=0;	
							  	  temp=temp/10*16+temp%10;
								  break;
				           case 2:
                                  temp=Read1302(DS1302_MINUTE);  //读取分数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //分数加1
                                  up_flag=1;
								  if(temp>59)          //超过59分,清零
								  temp=0;
								  temp=temp/10*16+temp%10;
								  break;
				           case 3:
                                  temp=Read1302(DS1302_HOUR);  //读取小时数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //小时数加1
                                  up_flag=1;
								  if(temp>23)   //超过23小时,清零
								  temp=0;
								  temp=temp/10*16+temp%10;
								  break;
				           case 4:
                                  temp=Read1302(DS1302_WEEK);  //读取星期数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //星期数加1
                                  up_flag=1;
								  if(temp>7)  
								  temp=1;
								  temp=temp/10*16+temp%10;
								  break;
				           case 5:
                                  temp=Read1302(DS1302_DAY);  //读取日数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //日数加1
                                  up_flag=1;
								  if(temp>31)
								  temp=1;
								  temp=temp/10*16+temp%10;
								  break;
				           case 6:
                                  temp=Read1302(DS1302_MONTH);  //读取月数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //月数加1
                                  up_flag=1;
								  if(temp>12)
								  temp=1;
								  temp=temp/10*16+temp%10;
								  break;
				           case 7:
                                  temp=Read1302(DS1302_YEAR);  //读取年数
								  temp=((temp&0xf0)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //年数加1
                                  up_flag=1;
								  if(temp>99)
								  temp=0;
								  temp=temp/10*16+temp%10;
								  break;
					       default:break;
				          }
					  
				 //  while(Up==0);
				  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
//************************
//降序按键
//************************
void Downkey()
{	    
		Down=1;
	    if(Down==0)
		          {
				   mdelay(5);
				     switch(count)
				          {case 1:
                                  temp=Read1302(DS1302_SECOND);  //读取秒数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;						    //秒数减1
                                  down_flag=1;       //数据调整后更新标志
								  if(temp==-1)     //小于0秒,返回59秒
								  temp=59;
								  temp=temp/10*16+temp%10;
								  break;
				           case 2:
                                  temp=Read1302(DS1302_MINUTE);  //读取分数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //分数减1
                                  down_flag=1;
								  if(temp==-1)
								  temp=59;      //小于0秒,返回59秒
								  temp=temp/10*16+temp%10;
								  break;
				           case 3:
                                  temp=Read1302(DS1302_HOUR);  //读取小时数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //小时数减1
                                  down_flag=1;
								  if(temp==-1)
								  temp=23;
								  temp=temp/10*16+temp%10;
								  break;
				           case 4:
                                  temp=Read1302(DS1302_WEEK);  //读取星期数;
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //星期数减1
                                  down_flag=1;
								  if(temp==0)
								  temp=7;
								  temp=temp/10*16+temp%10;
								  break;
				           case 5:
                                  temp=Read1302(DS1302_DAY);  //读取日数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //日数减1
                                  down_flag=1;
								  if(temp==0)
								  temp=31;
								  temp=temp/10*16+temp%10;
								  break;
				           case 6:
                                  temp=Read1302(DS1302_MONTH);  //读取月数
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //月数减1
                                  down_flag=1;
								  if(temp==0)
								  temp=12;
								  temp=temp/10*16+temp%10;
								  break;
				           case 7:
                                  temp=Read1302(DS1302_YEAR);  //读取年数
								  temp=((temp&0xf0)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //年数减1
                                  down_flag=1;
								  if(temp==-1)
								  temp=99;
								  temp=temp/10*16+temp%10;
								  break;
					      default:break;
				         }
					 
				 //  while(Down==0);
				  }
}

//**************************
//模式选择按键
//**************************
void Setkey()
{
		Set=1;
		if(Set==0)
	    {
           mdelay(5);
           count=count+1;	 //Setkey按一次,count就加1
		   done=1;			 //进入调整模式
           while(Set==0);
		 }

}

//*************************
//按键功能执行
//*************************
void keydone()
{        
		uchar Second;
		/* if(flag==0)    //关闭时钟,停止计时
         { Write1302(0x8e,0x00); //写入允许
           temp=Read1302(0x80);
           Write1302(0x80,temp|0x80);
	       Write1302(0x8e,0x80); //禁止写入
           flag=1;
         }*/
         Setkey();				            //扫描模式切换按键
		 switch(count)
		 {
		 	case 1:do					        //count=1,调整秒
		       {
                   outkey();			   //扫描跳出按钮
				   Upkey();                //扫描加按钮
				   Downkey();              //扫描减按钮
				   if(up_flag==1||down_flag==1)  //数据更新,重新写入新的数据
				   {
				     Write1302(0x8e,0x00); //写入允许
				     Write1302(0x80,temp); //写入新的秒数
				     Write1302(0x8e,0x80); //禁止写入
				     up_flag=0;
			    	 down_flag=0;
				  }
                     if(Down!=0&&Up!=0)
                     {
						hide_sec++;
				        if(hide_sec>3)
				        hide_sec=0;
                     }
					 else hide_sec=0;
					 show_time();         //液晶显示数据
				  }while(count==2);break;  
		  case 2:do					        //count=2,调整分
		          {
				   hide_sec=0;
				   outkey();
				   Upkey();
				   Downkey();
				   if(temp>0x60)
				     temp=0;
				   if(up_flag==1||down_flag==1)
				   {
				     Write1302(0x8e,0x00); //写入允许
				     Write1302(0x82,temp); //写入新的分数
				     Write1302(0x8e,0x80); //禁止写入
				     up_flag=0;
				     down_flag=0;
				  }
                     if(Down!=0&&Up!=0)
                     {
						hide_min++;
				        if(hide_min>3)
				        hide_min=0;
                     }
					 else hide_min=0;
					 show_time();
				  }while(count==3);break;
		  case 3:do					        //count=3,调整小时
		          {
                   hide_min=0; 
				   outkey();
				   Upkey();
				   Downkey();
				   if(up_flag==1||down_flag==1)
				   {
				      Write1302(0x8e,0x00); //写入允许
				      Write1302(0x84,temp); //写入新的小时数
				      Write1302(0x8e,0x80); //禁止写入
				      up_flag=0;
				      down_flag=0;
				   }
                      if(Down!=0&&Up!=0)
                     {
						hide_hour++;
				        if(hide_hour>3)
				        hide_hour=0;
                     }
					 else  hide_hour=0;
					  show_time();
				  }while(count==4);break;
		  case 4:do					        //count=4,调整星期
		          {
                   hide_hour=0; 
				   outkey();
				   Upkey();
				   Downkey();
				   if(up_flag==1||down_flag==1)
				   {
				     Write1302(0x8e,0x00); //写入允许
				     Write1302(0x8a,temp); //写入新的星期数
				     Write1302(0x8e,0x80); //禁止写入
				     up_flag=0;
				     down_flag=0;
				   }
                     if(Down!=0&&Up!=0)
                     {
					   hide_week++;
				       if(hide_week>3)
				       hide_week=0;
                     }
					 else hide_week=0;
					 show_time();
				  }while(count==5);break;
		  case 5:do					        //count=5,调整日
		          {
				   hide_week=0; 
				   outkey();
				   Upkey();
				   Downkey();
				   if(up_flag==1||down_flag==1)
				   {
				     Write1302(0x8e,0x00); //写入允许
				     Write1302(0x86,temp); //写入新的日数
				     Write1302(0x8e,0x80); //禁止写入
				     up_flag=0;
				     down_flag=0;
				   }
                     if(Down!=0&&Up!=0)
				     {
						hide_day++;
				        if(hide_day>3)
				        hide_day=0;
					 }
				    else hide_day=0;
                     show_time();
				  }while(count==6);break;
		  case 6:do					        //count=6,调整月
		          {
                   hide_day=0; 
				   outkey();
				   Upkey();
				   Downkey();
				   if(up_flag==1||down_flag==1)
				   {
				      Write1302(0x8e,0x00); //写入允许
				      Write1302(0x88,temp); //写入新的月数
				      Write1302(0x8e,0x80); //禁止写入
				      up_flag=0;
				      down_flag=0;
				   }
                     if(Down!=0&&Up!=0)
				     {
						 hide_month++;
				         if(hide_month>3)
				         hide_month=0;
					 }
					else hide_month=0;
                     show_time();
				  }while(count==7);break;
		  case 7:do					        //count=7,调整年
		          {
                   hide_month=0; 
				   outkey();
				   Upkey();
				   Downkey();
				   if(up_flag==1||down_flag==1)
				   {
				      Write1302(0x8e,0x00); //写入允许
				      Write1302(0x8c,temp); //写入新的年数
				      Write1302(0x8e,0x80); //禁止写入
				      up_flag=0;
				      down_flag=0;
				  }
                      if(Down!=0&&Up!=0)
				      {
					 	 hide_year++;
				         if(hide_year>3)
				         hide_year=0;
                      }
					  else hide_year=0;
                      show_time();
				  }while(count==8);break;
		  case 8: count=0;hide_year=0;  //count8, 跳出调整模式,返回默认显示状态
	              Second=Read1302(DS1302_SECOND);
                  Write1302(0x8e,0x00); //写入允许
	              Write1302(0x80,Second&0x7f);
	              Write1302(0x8E,0x80);          //禁止写入
				  done=0;
		  break; //count=7,开启中断,标志位置0并退出
		  default:break;

		 }

}

(5) 主程序

main()
{
  //  flag=1;           //时钟停止标志
	init_lcd();
	clrram_lcd();
	Init_DS18B20( ) ;      //DS18B20初始化
	Initial_DS1302(); //时钟芯片初始化
	up_flag=0;
	down_flag=0;
	done=0;           //进入默认液晶显示
	while(1)
	{   
        while(done==1)
          keydone();    //进入调整模式
		while(done==0)
 	    {  
            show_time();                //液晶显示数据
           // flag=0;                  
  		    Setkey();				 //扫描各功能键
 		}		
	}
}

源码+AD电路图 下载:关注公众号,首页回复“万年历”获取资料
在这里插入图片描述

2019-07-13 09:07:12 qq_40564448 阅读数 197
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4007 人正在学习 去看看 朱有鹏

2019/07/13

单片机数字钟(调时,调时闪烁,万年历,年月日)超详细解析

发表日期:2019/07/13
单片机开发板:巫妖王2.0,
使用同款开发板可直接上板测试

文档说明:
实现功能 : 一分钟闹钟 , 调时 ,调闹钟时间 , 年月日与日期切换 ,闹钟年月日与日期切换 , 停止计时 , 调时闪烁:调哪位低位闪烁
实现功能的学习板: 巫妖王 2.0 (不同的开发板,外围电路连接不同)(对应的显示模块等都有不同)
巫妖王 2.0 :
p0.0~p0.7,对应七段译码的a,b,c… p2.2,p2.3,p2.4 对应3-8译码器,结果对应位选
Key1 = P3^3; 计时停止(可停止时间调时,可不停止时间,直接调时)
Key2 = P3^2; 调位
Key3 = P3^1; 加一
Key4 = P3^0; 切换(按一下日期的年月日,按两下闹钟的时间,按三下闹钟的年月日,按4下,日期; 4次一循环)
flag = P1^5; 蜂鸣器
显示格式 : 时-分-秒 年(后两位)-月-日
闪烁 : XX-XX-XX (当调节相应位时,相应位闪烁)
程序框图:
在这里插入图片描述
将定时器工作方式改为方式1,定时10ms
蜂鸣器:判断年,月,日,时,分相同时闹:则闹钟调秒无用,闹钟时间为1分钟
(到下次分钟数不一样)

代码:

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar a []={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,0x7f, 0x6f};  //0~9译码
uchar second=00,minute=41,hour=13,year=19,month=5,day=31,count;
uchar nsecond=00,nminute=21,nhour=14,nyear=19,nmonth=5,nday=31,ns;
uchar flag2,flag3,flag4,flag1;
#define SEG_CS P0   ///连接数码管
//3-8译码位选,单片机动态显示,不同单片机显示各有不同,**需读者自己针对开发板更改显示代码**
sbit ga = P2^2;
sbit gb = P2^3;
sbit gc = P2^4;
//
///功能键
sbit Key1 = P3^3; //计时停止
sbit Key2 = P3^2; //调位
sbit Key3 = P3^1; //加一
sbit Key4 = P3^0; //切换
///
sbit flag = P1^5; //蜂鸣器 高电平有效
sbit LED1 = P1^0; //是否停止计时指示灯

/////一毫秒的延迟函数
void Delayms(uint t)  
		{
			uint i,j;
			for(i=0;i<t;i++)
			for(j=0;j<125;j++);
		}
/////

void Dispaly1(uchar second,uchar minute,uchar hour)//时分秒  格式xx(时)-xx(分)-xx(秒)
{
   		//位选一		
		ga=1;gb=1;gc=1;
		SEG_CS = a[hour/10]; //第1位数码管       
		Delayms(1);
		SEG_CS = 0x00;
			//位选二
		ga=0;gb=1;gc=1;      
		if(flag1==3)            ////对其调时时闪烁
			{
				if(count>50)
					{
					SEG_CS = a[hour%10];
					Delayms(1);	
					}
				else
					{
					SEG_CS = 0x00;
					Delayms(1);
					}
			}
		else
			{	
				SEG_CS = a[hour%10];//第2位数码管   
				Delayms(1);
				SEG_CS = 0x00;
			}
		//位选三
	
		ga=1;gb=0;gc=1;
		SEG_CS = 0x40;      //第3位数码管   横线  
		Delayms(1);
		SEG_CS = 0x00;
		//位选四	
		ga=0;gb=0;gc=1;
		SEG_CS = a[minute/10]; //第4位数码管   
		Delayms(1);
		SEG_CS = 0x00;
	//位选五	
		ga=1;gb=1;gc=0;   //第5位数码管   
		if(flag1==2)          
			{
				if(count>50)
					{
						SEG_CS = a[minute%10];
						Delayms(1);	
					}
				else
					{
						SEG_CS = 0x00;
						Delayms(1);
					}
			}
	else
			{
				SEG_CS = a[minute%10];
				Delayms(1);
				SEG_CS = 0x00;
			}
	//位选六	
		ga=0;gb=1;gc=0;
		SEG_CS = 0x40;					//第6位数码管   横线
		Delayms(1);
		SEG_CS = 0x00;
	//位选七
		ga=1;gb=0;gc=0;
		SEG_CS = a[second/10];//第7位数码管   
		Delayms(1);
		SEG_CS = 0x00;
		//位选八	
		ga=0;gb=0;gc=0;
		if(flag1==1)
			{
				if(count>50)
					{
						SEG_CS = a[second%10];
						Delayms(1);	
					}		//第8位数码管        
				else
					{
						SEG_CS = 0x00;
						Delayms(1);
					}
			}	
		else
			{
				SEG_CS = a[second%10];
				Delayms(1);
				SEG_CS = 0x00;
			}
    		 
}


void Dispaly2(uchar day,uchar month,uchar year) //同理时分秒
	{			
		ga=1;gb=1;gc=1;
		SEG_CS = a[day/10];
		Delayms(1);
		SEG_CS = 0x00;
			
		ga=0;gb=1;gc=1;
		if(flag2==3)
			{
				if(count>50)
					{
						SEG_CS = a[day%10];
						Delayms(1);	
					}
				else
					{
						SEG_CS = 0x00;
						Delayms(1);}
					}
		else
			{
				SEG_CS = a[day%10];
				Delayms(1);
				SEG_CS = 0x00;
			}
			
    ga=1;gb=0;gc=1;
    SEG_CS = 0x40;
    Delayms(1);
		SEG_CS = 0x00;
			
    ga=0;gb=0;gc=1;
    SEG_CS = a[month/10];
    Delayms(1);
		SEG_CS = 0x00;
		
    ga=1;gb=1;gc=0;
	  if(flag2==2)
	    {
				if(count>50)
	        {
						SEG_CS = a[month%10];
            Delayms(1);
					}
				else
					{
						SEG_CS = 0x00;
						Delayms(1);
					}
			}
		else
			{
				SEG_CS = a[month%10];
				Delayms(1);
				SEG_CS = 0x00;
			}
			
		ga=0;gb=1;gc=0;
		SEG_CS = 0x40;
		Delayms(1);
		SEG_CS = 0x00;
			
		ga=1;gb=0;gc=0;
		SEG_CS = a[year/10];
		Delayms(1);
		SEG_CS = 0x00;
			
		ga=0;gb=0;gc=0;
		if(flag2==1)
			{
				if(count>50)
				{
					SEG_CS = a[year%10];
					Delayms(1);
				}
				else
					{
						SEG_CS = 0x00;
						Delayms(1);
					}
			}
		else
			{
				SEG_CS = a[year%10];
				Delayms(1);
				SEG_CS = 0x00;
			}
}
	void Dispaly3(uchar nsecond,uchar nminute,uchar nhour)//时分秒  格式xx-xx-xx
{
   		//位选一	
		ga=1;gb=1;gc=1;
		SEG_CS = a[nhour/10]; //第1位数码管       
		Delayms(1);
		SEG_CS = 0x00;
			//位选二	
		ga=0;gb=1;gc=1;//第2位数码管 
		if(flag3==3)
			{
				if(count>50)
					{
						SEG_CS = a[nhour%10];
						Delayms(1);	
					}
				else
					{
						SEG_CS = 0x00;
						Delayms(1);
					}
			}
		else
			{
				SEG_CS = a[nhour%10];  
				Delayms(1);
				SEG_CS = 0x00;
			}
		//位选三
	
		ga=1;gb=0;gc=1;
		SEG_CS = 0x40;      //第3位数码管   横线  
		Delayms(1);
		SEG_CS = 0x00;
		//位选四	
		ga=0;gb=0;gc=1;
		SEG_CS = a[nminute/10]; //第4位数码管   
		Delayms(1);
		SEG_CS = 0x00;
	//位选五	
		ga=1;gb=1;gc=0;//第5位数码管
		 if(flag3==2)
			{
				if(count>50)
					{
						SEG_CS = a[nminute%10];
						Delayms(1);	
					}
				else
					{
						SEG_CS = 0x00;
						Delayms(1);
					}
			}
		else{
				SEG_CS = a[nminute%10];   
				Delayms(1);
				SEG_CS = 0x00;
				}
	//位选六	
		ga=0;gb=1;gc=0;
		SEG_CS = 0x40;					//第6位数码管   横线
		Delayms(1);
		SEG_CS = 0x00;
	//位选七
		ga=1;gb=0;gc=0;
		SEG_CS = a[nsecond/10];//第7位数码管   
		Delayms(1);
		SEG_CS = 0x00;
		//位选八	
	
		ga=0;gb=0;gc=0;
		if(flag3==1)
			{
				if(count>50)
					{
						SEG_CS = a[nsecond%10];
						Delayms(1);	
					}
				else
					{
						SEG_CS = 0x00;
						Delayms(1);
					}
			}
	else
			{
				SEG_CS = a[nsecond%10]; //第8位数码管   
				Delayms(1);
				SEG_CS = 0x00;
			}
}


void Dispaly4(uchar nday,uchar nmonth,uchar nyear) //同理时分秒
	{			
		ga=1;gb=1;gc=1;
		SEG_CS = a[nday/10];
		Delayms(1);
		SEG_CS = 0x00;
			
		ga=0;gb=1;gc=1;
		if(flag4==3)
			{
				if(count>50)
					{
						SEG_CS = a[nday%10];
						Delayms(1);
					}
				else
					{
						SEG_CS = 0x00;
						Delayms(1);
					}
			}
	else
			{
				SEG_CS = a[nday%10];
				Delayms(1);
				SEG_CS = 0x00;
			}
			
		ga=1;gb=0;gc=1;
		SEG_CS = 0x40;
		Delayms(1);
		SEG_CS = 0x00;
			
		ga=0;gb=0;gc=1;
		SEG_CS = a[nmonth/10];
		Delayms(1);
		SEG_CS = 0x00;
		
		ga=1;gb=1;gc=0;
		if(flag4==2)
			{
			if(count>50)
				{
					SEG_CS = a[nmonth%10];
					Delayms(1);	}
			else
				{
					SEG_CS = 0x00;
					Delayms(1);
				}
			}
		else
				{
					SEG_CS = a[nmonth%10];
					Delayms(1);
					SEG_CS = 0x00;
				}
			
		ga=0;gb=1;gc=0;
		SEG_CS = 0x40;
		Delayms(1);
		SEG_CS = 0x00;
			
		ga=1;gb=0;gc=0;
		SEG_CS = a[nyear/10];
		Delayms(1);
		SEG_CS = 0x00;
	
		if(flag4==1)
			{
				if(count>50)
					{
						SEG_CS = a[nyear%10];
						Delayms(1);
					}
				else
					{
						SEG_CS = 0x00;
						Delayms(1);
					}
			}
		else
			{	
				ga=0;gb=0;gc=0;
				SEG_CS = a[nyear%10];
				Delayms(1);
				SEG_CS = 0x00;
			}
 }

void Keyscan1()
{
		static uchar i=0,j=0; 
		if(Key1==0) 
			{
				Delayms(10); 
				if(Key1==0) 
				while(!Key1); //key按下并释放后  停止计时(关定时器 TR0=0) 
				i++;
			}
				if(i%2==1) 
					{
						LED1=0;
						TR0=0;
					}
				if(i%2==0)
					{
						LED1=1;
						TR0=1; 
					}
		if(Key2==0) 
			{
				Delayms(10); 
				if(Key2==0)
				while(!Key2);
				j++; 
			}
		if(j%4==0)
			{
				flag1=0	;              ///调位标志(等于0 调秒,等于1 调分。。。。。。)
			}
		if(j%4==1)
			{
				flag1=1	;		
				if(Key3==0)
					{
						Delayms(10); 
						if(Key3==0)        
						while(!Key3);     ////key3按下后  对应位加一
						second++;
						if(second==60)
						second=0;
					}
			}
		if(j%4==2)
			{
				flag1=2;
				if(Key3==0)
					{
						Delayms(10); 
						if(Key3==0)
						while(!Key3);
						minute++;
						if(minute==60)
						minute=0; 
					}
				}
		if(j%4==3)
			{ 
				flag1=3;
				if(Key3==0)
					{ 
						Delayms(10); 
						if(Key3==0)
						while(!Key3);
						hour++;
						if(hour==24)
						hour=0; 
				}
			}
}
void Keyscan2()
{
	static uchar m=0,n=0; 
	if(Key1==0) 
		{
			Delayms(10); 
			if(Key1==0)
			while(!Key1);	  
			m++;
		}
	if(m%2==1) 
		{
			LED1=0;
			TR0=0;
		}
	if(m%2==0)
		{
			LED1=1;
			TR0=1; 
		}
	if(Key2==0) 
		{
			Delayms(10); 
			if(Key2==0)
			while(!Key2);
			n++; 
		}
	if(n%4==0)
		{
			flag2=0	;
		}
	if(n%4==1)
		{
			flag2=1;
			if(Key3==0)
				{
					Delayms(10); 
					if(Key3==0)
					while(!Key3);
					day++;
					if(day==30)
					day=0;
				}
		}
	if(n%4==2)
		{
			flag2=2;
		if(Key3==0)
			{ 
				Delayms(10); 
				if(Key3==0)
				while(!Key3);
				month++;
				if(month==12)
				month=0; 
			}
		}
	if(n%4==3)
		{
			flag2=3;
			if(Key3==0)
				{ 
				Delayms(10); 
				if(Key3==0)
				while(!Key3);
				year++;
				if(year==99)
				year=0; 
				}
    }



//////////////////////////////////////////////闹钟
}void Keyscan3()
{
		static uchar i=0,j=0; 
		if(Key1==0) 
		{
			Delayms(10); 
			if(Key1==0) 
			while(!Key1); 
			i++;
		}
				if(i%2==1) 
				{
					LED1=0;
					TR0=0;
				}
				if(i%2==0)
				{
					LED1=1;
					TR0=1; 
				}
		if(Key2==0) 
		{
			Delayms(10); 
			if(Key2==0)
			while(!Key2);
			j++; 
		}
		if(j%4==0)
		{
      flag3=0	;
		}
		if(j%4==1)
		{
			flag3=1;
			if(Key3==0)
				{
					Delayms(10); 
					if(Key3==0)
					while(!Key3);
					nsecond++;
					if(second==60)
					nsecond=0;
				}
		}
		if(j%4==2)
			{
				flag3=2;
			if(Key3==0)
				{
				Delayms(10); 
				if(Key3==0)
				while(!Key3);
				nminute++;
				if(minute==60)
				nminute=0; 
				}
			}
		if(j%4==3)
		{
			flag3=3;
			if(Key3==0)
			{ 
				Delayms(10); 
				if(Key3==0)
				while(!Key3);
				nhour++;
				if(hour==24)
				nhour=0; 
			}
		}
}
void Keyscan4()
{
	static uchar m=0,n=0; 
	if(Key1==0) 
	{
		Delayms(10); 
		if(Key1==0)
		while(!Key1);	  
		m++;
	}
	if(m%2==1) 
	{
		LED1=0;
		TR0=0;
	}
	if(m%2==0)
	{
		LED1=1;
		TR0=1; 
	}
	if(Key2==0) 
	{
		Delayms(10); 
		if(Key2==0)
		while(!Key2);
		n++; 
	}
	if(n%4==0)
		{
      flag4=0	;
		}
	if(n%4==1)
	{
		flag4=1;
		if(Key3==0)
		{
			Delayms(10); 
			if(Key3==0)
			while(!Key3);
			nday++;
			if(day==30)
			nday=0;
		}
	}
	if(n%4==2)
		{
			flag4=2;
		if(Key3==0)
			{ 
			Delayms(10); 
			if(Key3==0)
			while(!Key3);
			nmonth++;
			if(month==12)
			nmonth=0; 
			}
		}
	if(n%4==3)
		{
			flag4=3;
			if(Key3==0)
			{ 
			Delayms(10); 
			if(Key3==0)
			while(!Key3);
			nyear++;
			if(year==99)
			nyear=0; 
			}
       }
}
//////////////////////////////////////////////////////////////////////
void main()
{


	TMOD=0x01;///利用方式一
	//TMOD=0x02;///利用T0方式二
	TH0=(65536-10000)/256;
	TL0=(65536-10000)%256;
	//TH0=0x00;//赋初值
	//TL0=0x06;
	EA=1;      ///开总中断
	ET0=1;     
	TR0=1;   
	while(1)
	{
		static uchar h=0; 
		
		if (nyear==year)
				if(nmonth==month)
					if(nday==day)
						if(nhour==hour)
							if(nminute==minute)   ////当年月日时分(不含秒)相等时,蜂鸣器响,这样做是为了闹钟持续闹一分钟
								{
							    flag=1;/////蜂鸣器  放首歌 啦啦啦nn
									Delayms(1);
									flag=0;
									Delayms(1);
								}
		if(Key4==0)    ///key4  切换(切换顺序  年月日--闹钟时间--闹钟年月日--时间)
		{
			Delayms(10); 
			if(Key4==0)
			while(!Key4);
			h++;
		}
		if(h%4==1) 
		{
			Dispaly2(year,month,day);
			Keyscan2();
		}
		if(h%4==2)
		{
			Dispaly3(nsecond,nminute,nhour);
			Keyscan3(); 
		}
		if(h%4==3)
		{
			Dispaly4(nyear,nmonth,nday);
			Keyscan4(); 
		}
		if(h%4==0)
		{
			Dispaly1(second,minute,hour);
			Keyscan1(); 
		}
	}
}
void int(void) interrupt 1
{
	TH0=(65536-10000)/256;
	TL0=(65536-10000)%256;
	//TH0=0x00;  
	//TL0=0x06;  
	//ns++;
//	if(ns==40){
		//ns=0;
		count++;
	if(count==100)
	{
		count=0;
		second++;
		if(second==60)
		{
		second=0;
		minute++;
		if(minute==60)
			{
			minute=0;
			hour++;
			if(hour==24)
				{
				hour=0;
				day++;
				if(day==30)
					{
						day=0;
						month++;
						if(month==12)
						{
							month=0;
							year++;
							if(year==99)
							{
							 year=0;
							}
						}
					}
				}
			}
		}
	}			
//}

}
2017-08-29 11:45:25 GithubHujinhan 阅读数 2858
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4007 人正在学习 去看看 朱有鹏

一、实验要求:

  设计一个基于51单片机的电子时钟, 具有显示年、月、日、星期、时、分、秒、闹钟功能

二、主要电子元件:

  • STC89C52单片机
  • 1602LCD显示屏
  • 无源蜂鸣器
  • 11.0592MHz晶振
  • 排阻
  • 电容、电阻、三极管等

三、原理图

原理图—基于51单片的电子时钟

四、程序代码

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit BF = P0^7;
sbit EN = P2^5;
sbit RS = P1^0;
sbit RW = P1^1;       
sbit dula=P2^6;
sbit wela=P2^7;
sbit s1=P3^0;
sbit s2=P3^1;
sbit s3=P3^2;
sbit s4=P3^3;
sbit rd=P3^7;
sbit fm=P2^3;
uint num;
unsigned long int dat,nian=2016;
char miao=55,shi=23,fen=59,xingqi=6,kg,ri=31,yue=12,count,s1num,s4num,cshi=0,cfen=0,cmiao=0,zt;
uchar code table[]="     -  -       ";
uchar code table1[]="      :  :      ";
uchar code *table2[7]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
uchar code *table3[2]={"OF","ON"};
uchar code alarm[]={"  alarm setting "};
void delayms(uint z)//延时
{
    uint i,j;
    for(j=z;j>0;j--)
        for(i=110;i>0;i--);
}
void wait(void)//判忙
{
     P0=0xFF;
     do{
         RS=0;
         RW=1;
         EN=0;
         EN=1;
     }
     while (BF==1);
     EN=0;
}

void w_dat(uchar dat)//数据写入
{
    wait();
    EN=0;
    P0=dat;
    RS=1;
    RW=0;
    EN=1;
    EN=0;
}

void w_cmd(uchar cmd)//命令写入
{
    wait();
    EN=0;
    P0=cmd;
    RS=0;
    RW=0;
    EN=1;
    EN=0;
}

void w_sfm(uchar add,uchar date)//时分秒写入
{
    uchar shi,ge;
    shi=date/10;
    ge=date%10;
    w_cmd(0x80+add);
    w_dat(0x30+shi);
    w_dat(0x30+ge);
}

void w_nian(uchar add, unsigned long int dat) //年份写入
{
    uchar qian,bai,shi,ge;
    ge=dat%10;
    shi=(dat/10)%10;
    bai=(dat/100)%10;
    qian=(dat/1000)%10;
    w_cmd(0x80+add);
    w_dat(0x30+qian);
    w_dat(0x30+bai);
    w_dat(0x30+shi);
    w_dat(0x30+ge);
}
void xianshi(void)//显示函数
{
    w_cmd(0x80);
    for(num=0;num<16;num++){
        w_dat(table[num]);
    }                       //显示日期
    w_cmd(0x80+0x40);
    for(num=0;num<16;num++){
        w_dat(table1[num]);
    }
    w_nian(1,nian);
    w_sfm(6,yue);
    w_sfm(9,ri);
    w_cmd(0x80+12);
    for(num=0;num<3;num++)
        w_dat(table2[xingqi][num]);
    w_sfm(0x40+4,shi);
    w_sfm(0x40+7,fen);
    w_sfm(0x40+10,miao);                        //显示时间
}
void Init_LCD1602(void)//初始化
{
    dula=0;
    wela=0;
    w_cmd(0x38);
    w_cmd(0x0c);
    w_cmd(0x06);
    w_cmd(0x01);
    w_cmd(0x80);
    xianshi();          
    TMOD=0x01;
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    EA=1;
    ET0=1;
    TR0=1;
}
void keyscan()//扫描按键
{
    rd=0;
    if(s1==0){
        delayms(5);
        if(s1==0){  
            s1num++;
            while(!s1);
        }
            if(s1num==1){
                s4num=0;
                TR0=0;
                w_cmd(0x80+0x40+11);
                w_cmd(0x0f);
            }

            if(s1num==2){
                w_cmd(0x80+0x40+8);
            }
            if(s1num==3){
                w_cmd(0x80+0x40+5);
            }
            if(s1num==4){
                w_cmd(0x80+14);
            }
            if(s1num==5){
                w_cmd(0x80+10);
            }       
            if(s1num==6){
                w_cmd(0x80+7);
            }
            if(s1num==7){
                w_cmd(0x80+4);
            }
            if(s1num==8){
                s1num=0;
                w_cmd(0x0c);
                TR0=1;
            }


        }
        if(s1num!=0){
            if(s2==0)
            {
                delayms(5);
                if(s2==0){
                    while(!s2);
                    if(s1num==1){
                        miao++;
                        if(miao==60)
                            miao=0;
                        w_sfm(0x40+10,miao);
                        w_cmd(0x80+0x40+11);                                                
                    }
                    if(s1num==2){
                        fen++;
                        if(fen==60)
                            fen=0;
                        w_sfm(0x40+7,fen);
                        w_cmd(0x80+0x40+8);
                    }
                    if(s1num==3){
                        shi++;
                        if(shi==24)
                            shi=0;
                        w_sfm(0x40+4,shi);
                        w_cmd(0x80+0x40+5);
                    }
                    if(s1num==4){
                        uint num;
                        xingqi++;
                        if(xingqi==7)
                            xingqi=0;
                        w_cmd(0x80+12);
                        for(num=0;num<3;num++)
                            w_dat(table2[xingqi][num]);
                        w_cmd(0x80+14);
                    }
                    if(s1num==5){
                        ri++;
                        if(ri==29&&yue==2&&(nian%4!=0))
                            ri=1;
                        if(ri==29&&yue==2&&nian%100==0&&nian%400!=0)
                            ri=1;
                        if(ri==30&&yue==2&&((nian%100==0&&nian%400==0)||(nian%100!=0&&nian%4==0)))
                            ri=1;
                        if(ri==31&&(yue==4||yue==6||yue==9||yue==11))
                            ri=1;
                        if(ri==32&&(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12))
                            ri=1;
                        w_sfm(9,ri);
                        w_cmd(0x80+10);
                    }
                    if(s1num==6){
                        yue++;
                        if(yue==13)
                            yue=1;
                        w_sfm(6,yue);
                        w_cmd(0x80+7);
                    }
                    if(s1num==7){
                        nian++;
                        w_nian(1,nian);
                        w_cmd(0x80+4);
                    }

                }
            }
            if(s3==0){
                delayms(5);
                if(s3==0){
                    while(!s3);
                    if(s1num==1){
                        miao--;
                        if(miao==-1)
                            miao=59;
                        w_sfm(0x40+10,miao);
                        w_cmd(0x80+0x40+11);
                    }
                    if(s1num==2){
                        fen--;
                        if(fen==-1)
                            fen=59;
                        w_sfm(0x40+7,fen);
                        w_cmd(0x80+0x40+8);
                    }
                    if(s1num==3){
                        shi--;
                        if(shi==-1)
                            shi=23;
                        w_sfm(0x40+4,shi);
                        w_cmd(0x80+0x40+5);
                    }
                    if(s1num==4){
                        uint num;
                        xingqi--;
                        if(xingqi==-1)
                            xingqi=6;
                        w_cmd(0x80+12);
                        for(num=0;num<3;num++)
                            w_dat(table2[xingqi][num]);
                        w_cmd(0x80+14);
                    }
                    if(s1num==5){
                        ri--;
                        if(ri==0&&yue==2&&(nian%4!=0))
                            ri=28;
                        if(ri==0&&yue==2&&nian%100==0&&nian%400!=0)
                            ri=28;
                        if(ri==0&&yue==2&&((nian%100==0&&nian%400==0)||(nian%100!=0&&nian%4==0)))
                            ri=29;
                        if(ri==0&&(yue==4||yue==6||yue==9||yue==11))
                            ri=30;
                        if(ri==0&&(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12))
                            ri=31;
                        w_sfm(9,ri);
                        w_cmd(0x80+10);
                    }
                    if(s1num==6){
                        yue--;
                        if(yue==0)
                            yue=12;
                        w_sfm(6,yue);
                        w_cmd(0x80+7);
                    }
                    if(s1num==7){
                        nian--;
                        w_nian(1,nian);
                        w_cmd(0x80+4);
                    }
                }
            }
        }
        if(s4==0){
            delayms(5);
            if(s4==0){
                zt=1;
                s4num++;
                while(!s4);
            }
            if(s4num==1){
                s1num=0;
                w_cmd(0x80);
                for(num=0;num<16;num++){
                    w_dat(alarm[num]);
                }
                w_cmd(0x80+0x40+14);
                for(num=0;num<2;num++){
                    w_dat(table3[kg][num]);
                }
                w_sfm(0x40+4,cshi);
                w_sfm(0x40+7,cfen);
                w_sfm(0x40+10,cmiao);
                w_cmd(0x80+0x40+15);
                w_cmd(0x0f);
            }
            if(s4num==2){
                w_cmd(0x80+0x40+11);
            }
            if(s4num==3){
                w_cmd(0x80+0x40+8);
            }   
            if(s4num==4){
                w_cmd(0x80+0x40+5);
            }   
            if(s4num==5){
                zt=0;
                delayms(10);
                s4num=0;
                w_cmd(0x0c);
            }
        }
        if(s4num!=0){
            if(s2==0){
                delayms(5);
                if(s2==0){
                    while(!s2);
                    if(s4num==1){
                        kg++;
                        if(kg==2)
                            kg=0;
                        w_cmd(0x80+0x40+14);
                        for(num=0;num<2;num++){
                             w_dat(table3[kg][num]);
                        }
                        w_cmd(0x80+0x40+15);
                    }
                    if(s4num==2){
                        cmiao++;
                        if(cmiao==60)
                            cmiao=0;
                        w_sfm(0x40+10,cmiao);
                        w_cmd(0x80+0x40+11);                                
                    }
                    if(s4num==3){
                        cfen++;
                        if(cfen==60)
                            cfen=0;
                        w_sfm(0x40+7,cfen);
                        w_cmd(0x80+0x40+8);
                    }
                    if(s4num==4){
                        cshi++;
                        if(cshi==24)
                            cshi=0;
                        w_sfm(0x40+4,cshi);
                        w_cmd(0x80+0x40+5);
                    }
                }
            }
            if(s3==0){
                delayms(5);
                if(s3==0){
                    while(!s3);
                    if(s4num==1){
                        kg--;
                        if(kg==-1)
                            kg=1;
                        w_cmd(0x80+0x40+14);
                        for(num=0;num<2;num++){
                             w_dat(table3[kg][num]);
                        }
                        w_cmd(0x80+0x40+15);
                    }
                    if(s4num==2){
                        cmiao--;
                        if(cmiao==-1)
                            cmiao=59;
                        w_sfm(0x40+10,cmiao);
                        w_cmd(0x80+0x40+11);                                
                    }
                    if(s4num==3){
                        cfen--;
                        if(cfen==-1)
                            cfen=59;
                        w_sfm(0x40+7,cfen);
                        w_cmd(0x80+0x40+8);
                    }
                    if(s4num==4){
                        cshi--;
                        if(cshi==-1)
                            cshi=23;
                        w_sfm(0x40+4,cshi);
                        w_cmd(0x80+0x40+5);
                    }
                }
            }

        }
}            
main()
{
    Init_LCD1602();
    while(1){
        keyscan();
        if(kg&&miao==cmiao&&fen==cfen&&shi==cshi){
            fm=0;
            delayms(10000);
            fm=1;
        }

    }

}
void timer0() interrupt 1
{
    TH0=(65536-46080)/256;
    TL0=(65536-46080)%256;
    count++;
    if(count==20){
        count=0;
        miao++;
        if(miao==60){
            miao=0;
            fen++;
            if(fen==60){
                fen=0;
                shi++;
                if(shi==24){                            
                    shi=0;
                    ri++;xingqi++;
                    if(ri==29&&yue==2&&(nian%4!=0))
                        ri=1;
                    if(ri==29&&yue==2&&nian%100==0&&nian%400!=0)
                        ri=1;
                    if(ri==30&&yue==2&&((nian%100==0&&nian%400==0)||(nian%100!=0&&nian%4==0)))
                        ri=1;
                    if(ri==31&&(yue==4||yue==6||yue==9||yue==11))
                        ri=1;
                    if(ri==32&&(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12))
                        ri=1;
                    if(ri==1){
                        yue++;
                        if(yue==13){
                            yue=1;
                            nian++;
                        }
                    }
                    if(xingqi==7)
                        xingqi=0;
                }
            }
        }
        if(zt==0) xianshi();            
    }
}
2018-05-06 11:19:40 qq_15041159 阅读数 1428
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4007 人正在学习 去看看 朱有鹏

单片机初级应用:时钟+闹钟+秒表+定时器

作者:AntoniotheFuture

关键词:单片机,时钟,C语言,C51

开发平台:Keil μVersion4

平台版本上限:未知

平台版本下限:未知

开发语言:C

简介: 用单片机实现一个具有四大功能(时钟,闹钟,秒表,定时器)的时钟,可以记录8组秒表,8个闹钟。

不同的单片机需要作不同的设置

>>led.c

#include<reg52.h>
#include<Timer.h>
#include<STCc52.h>
#define uchar unsigned char
#define uint unsigned int
//时间计数
uchar count=0;
uchar SWCount=0;
uchar TCount = 0;

//状态控制
uint LEDP = 1;
uchar SMOD = 1; //显示模式  1-1 时钟运行 1-2 调整时 1-3 调整分 1-4重置时间 2-1闹钟查看 2-2闹钟设置时 2-3闹钟设置分 2-4删除当前闹钟  3-1 秒表5键开始/计数、4键停止/继续 3-2秒表查看 3-3清空秒表 4-1定时器准备 4-2定时器设置分 4-3定时器设置秒 4-4删除定时器
uchar FMOD = 1; //功能模式 1:时钟 2:秒表 3:闹钟 4:定时器
bit SWRUN = 0;
bit keyp2 =0;
bit keyp3 =0;
bit keyp4 =0;
bit keyp5 =0;
bit ACRun = 0;
bit TACRUN = 0;
bit TRUN = 0;
uchar dot;
bit show = 1;

//时间参数
uint SWMSEC = 0;
int TSEC = 0;
int TMIN = 0;
char SEC = 30;
char MIN = 25;
char HOR = 17;

//循环参数

uchar x = 0;
uchar y = 0;
uchar swy = 0;
uchar swdy = 0;
uchar i;

//硬件映射
sbit fm = P2^3;

//闹钟数组:时分、0 = 启用。
uint ACs[8][3] = {{8,0,0},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1}};
uint SWs[8] = {0};

//计时器
void timer0()interrupt 1{
	TH0=(65536-46080)/256;
	TL0=(65536-46080)%256;
	count++;
	if (SWRUN){SWCount++;}
	if (TRUN){TCount++;}	 
}

//流水灯
void TLED(){
	if (TRUN&TCount%2 == 0 ){LEDP++;
		if (LEDP == 9){LEDP = 0;}
   	LEDSW (LEDP,0);
	}}

void main()
{
	TMOD=0x01;
	TH0= (65536-46080)/256;
	TL0= (65536-46080)%256;
	EA =1;
	ET0 =1;
	TR0 = 1;
	while (1){
	//时钟
	if (count == 20){
		SEC ++;
		count = 0;
		if(SEC == 60){
			SEC = 0;
			MIN ++;
			ACRun = 1;
			TACRUN = 0;
			if(MIN == 60){
				MIN = 0;
				HOR ++;
				if (HOR == 24){
					HOR = 0;}
			}
		}
	}
	//小数点闪烁
	if (SEC%2 == 0 ) dot =1; else dot = 0;
	//闹钟
	if (ACRun&dot == 1){
		for (x = 0;x < sizeof(ACs) / sizeof(ACs[0]);x++){
			if(ACs[x][2] == 0&HOR == ACs[x][0]&MIN == ACs[x][1]){
				if(count == 0||count == 5||count == 10||count == 15){fm = 0;}
				if(count == 3||count == 8||count == 13||count == 18){fm = 1;}
			}break;
		}
	}
	//定时器闹钟
	if(TACRUN&dot == 1){
		if(TCount == 0||TCount == 10){fm = 0;}
		if(TCount == 5||TCount == 15){fm = 1;}
	}
	else {fm = 1;}
	
	//秒表
	if (SWRUN){
	if (SWCount == 2){
		SWMSEC ++;
		SWCount = 0;
		if(SWMSEC == 6000){SWRUN = 0;SWMSEC = 5999;}
		}
	}
	//定时器
	if (TRUN){
	if (TCount == 20){
		TSEC --;
		TCount = 0;
		if(TSEC == -1&TMIN == 0){TRUN = 0;TSEC = 0;TACRUN = 1;}
		else if(TSEC == -1){TSEC = 59;TMIN --;}
		}
	}
	
	//功能改变
	if (~keyp2&ShortPress(2)){FMOD++;SMOD = 1;keyp2 = 1;display (0,0,0,0,0,0,0,0);
		if (FMOD == 5){FMOD = 1;}}
	else if (~ShortPress(2)){keyp2 = 0;}

	//状态改变
	if (~keyp3&ShortPress(3)){SMOD++;keyp3 = 1;
		if (FMOD == 3&SMOD == 4){SMOD = 1;}
		else if (SMOD == 5){SMOD = 1;}
	}
	else if (~ShortPress(3)){keyp3 = 0;}
	//关闭闹钟
	if (ACRun){
		if (~keyp5&ShortPress(5)){ACRun = 0;keyp5 = 1;show=1;}
		else if (~ShortPress(5)){keyp5 = 0;}
	}	

	//显示
	switch(FMOD){
	case 1:
		switch(SMOD){
			case 1:
				TLED();
				if (show){
				display (HOR/10,0,HOR%10,dot,MIN/10,0,MIN%10,0);}
				if (~keyp5&ShortPress(4)){Delay(100);show = ~show;keyp4 = 1;refresh();}
				else if (~ShortPress(4)){keyp4 = 0;}
				break;
			case 2:
				display (HOR/10,dot,HOR%10,dot,MIN/10,0,MIN%10,0);
			   	if (~keyp4&ShortPress(4)){HOR--;keyp4 = 1;
					if (HOR == -1){HOR = 23;}}
				else if (~ShortPress(4)){keyp4 = 0;}
				if (~keyp5&ShortPress(5)){HOR++;keyp5 = 1;
					if (HOR == 24){HOR = 0;}}
				else if (~ShortPress(5)){keyp5 = 0;}show=1;break;
			case 3:
				display (HOR/10,0,HOR%10,0,MIN/10,dot,MIN%10,dot);
			   	if (~keyp4&ShortPress(4)){SEC = 0;MIN--;keyp4 = 1;
					if (MIN == -1){MIN = 59;}}
				else if (~ShortPress(4)){keyp4 = 0;}
				if (~keyp5&ShortPress(5)){SEC = 0;MIN++;keyp5 = 1;
					if (MIN == 60){MIN = 0;}}
				else if (~ShortPress(5)){keyp5 = 0;}show=1;break;
			case 4:
				display (0x7c,dot,0,dot,0,dot,0,dot);
				if (~keyp5&ShortPress(5)){keyp5 = 1;HOR = 0;MIN = 0;SEC = 0;SMOD = 1;}
				else if (~ShortPress(5)){keyp5 = 0;}show=1;break;
	}break;
	case 2:
		show=1;
		for (x = 0;x < sizeof(ACs) / sizeof(ACs[0]);x++){
			LEDSW (x+1,ACs[x][2]);}
			LEDSW (y+1,dot);
		switch(SMOD){
			case 1:
			   	if (~keyp4&ShortPress(4)){y--;keyp4 = 1;
					if (y == -1){y = 7;}}
				else if (~ShortPress(4)){keyp4 = 0;}
				if (~keyp5&ShortPress(5)){y++;keyp5 = 1;
					if (y == 8){y = 0;}}
				else if (~ShortPress(5)){keyp5 = 0;}
				display (ACs[y][0]/10,0,ACs[y][0]%10,dot,ACs[y][1]/10,0,ACs[y][1]%10,0);
				break;
			case 2:
				display (ACs[y][0]/10,dot,ACs[y][0]%10,dot,ACs[y][1]/10,0,ACs[y][1]%10,0);
				if (~keyp4&ShortPress(4)){ACs[y][0]--;keyp4 = 1;
					if (ACs[y][0] == -1){ACs[y][0] = 23;}}
				else if (~ShortPress(4)){keyp4 = 0;}
				if (~keyp5&ShortPress(5)){ACs[y][0]++;keyp5 = 1;
					if (ACs[y][0] == 24){ACs[y][0] = 0;}}
				else if (~ShortPress(5)){keyp5 = 0;}
				break;
			case 3:
				display (ACs[y][0]/10,0,ACs[y][0]%10,0,ACs[y][1]/10,dot,ACs[y][1]%10,dot);
				if (~keyp4&ShortPress(4)){ACs[y][1]--;keyp4 = 1;
					if (ACs[y][1] == -1){ACs[y][1] = 59;}}
				else if (~ShortPress(4)){keyp4 = 0;}
				if (~keyp5&ShortPress(5)){ACs[y][1]++;keyp5 = 1;
					if (ACs[y][1] == 60){ACs[y][1] = 0;}}
				else if (~ShortPress(5)){keyp5 = 0;}
				break;
			case 4:
				display (0,dot,0x7c,dot,0,dot,0,dot);
				if (~keyp5&ShortPress(5)){keyp5 = 1;
					if(ACs[y][2] == 1) ACs[y][2] = 0;
					else ACs[y][2] = 1;
					SMOD = 1;}
				else if (~ShortPress(5)){keyp5 = 0;}
				break;
		}
		for (x = 0;x < 8;x++){LEDSW (x+1,1);}
		break;
	case 3:show=1;
		for (x = 0;x < sizeof(SWs) / sizeof(SWs[0]);x++){
			if (SWs[x]>0){LEDSW (x+1,0);}
			else break;}
		switch(SMOD){
		case 1:
			if(~SWRUN) dot = 1;
			LEDSW (x+1,dot);
			display (SWMSEC/600,dot,(SWMSEC%600)/100,0,(SWMSEC%100)/10,dot,SWMSEC%10,0);
			if (~keyp4&ShortPress(4)){SWRUN = ~SWRUN;keyp4 = 1;}
			else if (~ShortPress(4)){keyp4 = 0;}
			if (x <8&SWRUN&~keyp5&ShortPress(5)){SWs[x] = SWMSEC;keyp5 = 1;}
			else if (~ShortPress(5)){keyp5 = 0;}
			swy = x;
			break;
		case 2:
			SWRUN = 0;
			LEDSW (swy+1,dot);
			if (~keyp4&ShortPress(4)){swy--;keyp4 = 1;LEDSW (x,1);}
				if (swy == -1){if (x >1) swy = x;else swy = 0;}
			else if (~ShortPress(4)){keyp4 = 0;}
			if (~keyp5&ShortPress(5)){swy++;keyp5 = 1;LEDSW (x,1);}
			else if (~ShortPress(5)){keyp5 = 0;}
			if (swy == x){display (SWMSEC/600,1,(SWMSEC%600)/100,0,(SWMSEC%100)/10,1,SWMSEC%10,0);}
			else {display (SWs[swy]/600,1,(SWs[swy]%600)/100,0,(SWs[swy]%100)/10,1,SWs[swy]%10,0);}
			if (swy == x+1){swy = 0;}
			break;
		case 3:
			display (0,dot,0,dot,0x7c,dot,0,dot);
			if (~keyp5&ShortPress(5)){
				for (x = 0;x < 8;x++){
					SWs[x] = 0;LEDSW (x+1,1);}
				keyp5 = 1;
				SWCount = 0;
				SWMSEC = 0;
				SMOD = 1;
			}
			else if (~ShortPress(5)){keyp5 = 0;}
			break;	
		}break;
	case 4:
		show=1;
		switch(SMOD){
		case 1:
			TLED();
			if(~TRUN) dot = 1;
			display (TMIN/10,0,TMIN%10,dot,TSEC/10,0,TSEC%10,0);
			if (~keyp4&ShortPress(4)){
				if (TSEC == 0 & TMIN ==0){TACRUN = 0;}
				else {TRUN = ~TRUN;}
				keyp4 = 1;}
			else if (~ShortPress(4)){keyp4 = 0;}
			if (~keyp5&ShortPress(5)){TSEC += 30;keyp5 = 1;
				if (TSEC >= 60) {TSEC = 59;TMIN ++;
					if (TMIN == 60){TMIN = 59;}}}
			else if (~ShortPress(5)){keyp5 = 0;}break;
		case 2:
			TRUN = 0;
			display (TMIN/10,dot,TMIN%10,dot,TSEC/10,0,TSEC%10,0);
			if (~keyp4&ShortPress(4)){TMIN--;keyp4 = 1;
				if(TMIN == -1){TMIN=59;}}
			else if (~ShortPress(4)){keyp4 = 0;}
			if (~keyp5&ShortPress(5)){TMIN++;keyp5 = 1;
				if(TMIN == 60){TMIN=0;}}
			else if (~ShortPress(5)){keyp5 = 0;}break;
		case 3:
			TRUN = 0;
			display (TMIN/10,0,TMIN%10,0,TSEC/10,dot,TSEC%10,dot);
			if (~keyp4&ShortPress(4)){TSEC--;keyp4 = 1;
				if(TSEC == -1){TSEC =59;}}
			else if (~ShortPress(4)){keyp4 = 0;}
			if (~keyp5&ShortPress(5)){TSEC++;keyp5 = 1;
				if(TSEC == 60){TSEC=0;}}
			else if (~ShortPress(5)){keyp5 = 0;}break;
		case 4:
			display (0,dot,0,dot,0,dot,0x7c,dot);
				if (~keyp5&ShortPress(5)){keyp5 = 1;TMIN = 0;TSEC = 0;SMOD = 1;}
				else if (~ShortPress(5)){keyp5 = 0;}show=1;break;
	break;	
	}
}
for (x = 1;x<9;x++){LEDSW (x,1);}
}
}


>STCc52.c


#include<reg52.h>
#include<Timer.h>
#include<STCc52.h>
//硬件映射
sbit s1 = P2^4;
sbit s2 = P2^5;
sbit s3 = P2^6;
sbit s4 = P2^7;
sbit l1 = P1^0;
sbit l2 = P1^1;
sbit l3 = P1^2;
sbit l4 = P1^3;
sbit l5 = P1^4;
sbit l6 = P1^5;
sbit l7 = P1^6;
sbit l8 = P1^7;
sbit k2 = P3^4;
sbit k3 = P3^5;
sbit k4 = P3^6;
sbit k5 = P3^7;
bit stop =1;
#define uchar unsigned char
#define dula P0
#define wela P2
unsigned char code weitable[] = {0x8f,0x4f,0x2f,0x1f};
code unsigned char table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
code unsigned char table1[] = {0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
//数显管控制
void display1 (uchar wei,uchar shu,uchar dot)//对应位显示对应数字,
{	
	wei = wei -1;
	wela |= 0xf0;
	if (dot == 1)	
		P0 = table1[shu];
	else
		P0 = table[shu];
	wela = wela&weitable[wei];
	Delay (5);	
}
//刷新数显管
void refresh(){
	s1 =0;s2 =0;s3 =0;s4 =0;Delay (100);
}

//四位数显管
void display (uchar a,uchar ad,uchar b,uchar bd,uchar c,uchar cd,uchar d,uchar dd)
{
	display1 (4,a,ad);
	display1 (3,b,bd);
	display1 (2,c,cd);
	display1 (1,d,dd);
}
		
//判断某个键是否短按
bit ShortPress(unsigned int KN)
{
	switch(KN){
	case 2:	
		if (k2 == 0){Delay(10);
			if (k2 == 0){while(k2 == 1){return 1;}}
			else{return 0;}}
		else{return 0;}
		break;
	case 3:								   
		if (k3 == 0){Delay(10);
			if (k3 == 0){while(k3 == 1){return 1;}}
			else{return 0;}}
		else{return 0;}
		break;
	case 4:
		if (k4 == 0){Delay(10);
			if (k4 == 0){while(k4 == 1){return 1;}}
			else{return 0;}}
		else{return 0;}
		break;
	case 5:
		if (k5 == 0){Delay(10);
			if (k5 == 0){while(k5 == 1){return 1;}}
			else{return 0;}}
		else{return 0;}
		break;
	default:return 0;break;
	}
}
//对应LED亮
void LEDSW (int Lwei,uchar LB)
{
	switch(Lwei){
	case 1: l1 = LB;break;
	case 2: l2 = LB;break;
	case 3: l3 = LB;break;
	case 4: l4 = LB;break;
	case 5: l5 = LB;break;
	case 6: l6 = LB;break;
	case 7: l7 = LB;break;
	case 8: l8 = LB;break;
	}
}

>>Timer.c

//时间函数
#include<Timer.h>
void Delay (unsigned int xms)
{
	unsigned int i,j;
	for (i=xms;i>0;i--)
		for (j = 112;j>0;j--);
}

>>STCC52.h

#define uchar unsigned char
void display1 (uchar wei,uchar shu,uchar dot);
void display (uchar a,uchar ad,uchar b,uchar bd,uchar c,uchar cd,uchar d,uchar dd);
bit ShortPress(unsigned int KN);
void LEDSW (int Lwei,uchar LB);
void refresh();


>>TIMER.h

//时间头文件
void Delay (unsigned int xms);


共同学习,共同提高!



51单片机时钟——利用中断

博文 来自: newcong0123
没有更多推荐了,返回首页