AutoLeaders控制组—51单片机学习笔记(二)中任务

1.任务要求

整体功能介绍:
数码管显示时间, 通过矩阵键盘中的 S4 和 S8 切换模式, 按下 S4 进入时间调节模式, 此时
可以通过 S1-S3 和 S5-S7 对时间的时、 分、 秒进行调整, 调节时间的某一位时, 该位需要闪
烁; 按下 S8 进入计时模式, 从刚刚设定的时间开始计时, 数码管显示从 DS1302 获取的时
间。
具体要求:
1、 初始状态:
初始状态下 DS1302 时间初始化为 12:00:00, 数码管显示从 DS1302 获取的时间
显示格式:
其中“-” 以 1s 为周期闪烁(指一段时间内亮灭各占一半, 不是每隔 1 秒就闪一下下)
1 2 - 0 0 - 0 0
12 时 闪烁 0 分 闪烁 0 秒2、 调节模式:
按下矩阵键盘中的 S4 进入调节模式
按键功能:
其中 S1 对小时进行加, S5 对小时进行减
S2 对分钟进行加, S6 对分钟进行减
S3 对 秒 进行加, S7 对 秒 进行减
显示格式:
当调整某一位时, 该位数字以 500ms 为周期闪烁, 其余位保持不动(闪烁说明同上)
1 2 - 0 0 - 0 0
小时位 间隔 分钟位 间隔 秒位
调整该位时闪烁 固定 调整该位时闪烁 固定 调整该位时闪烁
例如: 当按下 S1 或者 S5 时, 小时位闪烁, 并且能够通过 S1 或者 S5 对该位数值进行调整;
之后当按下 S2 或者 S6 时, 小时位停止闪烁, 同时分钟位开始闪烁, 并且能够通过 S2 或者
S6 对该位数值进行调整。
3、 计时模式:
按下矩阵键盘中的 S8 进入计时模式
按下 S8 时首先要将 DS1302 的时间设置为调节模式中调整的时间, 然后切换到计时模式
该模式下显示从 DS1302 中获取的时间
显示格式:
其中“-” 以 1s 为周期闪烁

2.代码

main.c主函数

#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Key.h"
#include "Timer0.h"
#include "MatrixKey.h"
#include "Delay.h"
#include "NixieTable.h"
unsigned char KeyNum;
unsigned char KeySet;//标志按下哪个按键
unsigned char TimeSetFlashFlag,MODE;
unsigned char TimeSetSelect;
void Init()//初始显示模式
{ 
	  DS1302_ReadTime();
	  Nixie(1,DS1302_Time[3]/10);
		Nixie(2,DS1302_Time[3]%10);
		Nixie(4,DS1302_Time[4]/10);
		Nixie(5,DS1302_Time[4]%10);
		Nixie(7,DS1302_Time[5]/10);
		Nixie(8,DS1302_Time[5]%10);
		if(TimeSetFlashFlag==0)
		{
			Nixie(3,10);
			Nixie(6,10);
		}
		if(DS1302_Time[3]>23){DS1302_Time[3]=0;}
		if(DS1302_Time[4]>59){DS1302_Time[4]=0;}
		if(DS1302_Time[5]>59){DS1302_Time[5]=0;}
}

void Set()//调节模式S4
{
	Nixie(3,10);
	Nixie(6,10);
	if(KeyNum==1)
	{
		DS1302_Time[3]++;
		KeySet=1;
		if(DS1302_Time[3]>23){DS1302_Time[3]=0;}
	}
	if(KeyNum==2)
	{
		DS1302_Time[4]++;
		KeySet=2;
		if(DS1302_Time[4]>59){DS1302_Time[4]=0;}
	}
	if(KeyNum==3)
	{
		DS1302_Time[5]++;
		KeySet=3;
		if(DS1302_Time[5]>59){DS1302_Time[5]=0;}
	}
	if(KeyNum==5)
	{
		DS1302_Time[3]--;
		KeySet=5;
	  if(DS1302_Time[3]<0){DS1302_Time[3]=23;}
	}
	if(KeyNum==6)
	{
		DS1302_Time[4]--;
		KeySet=6;
		if(DS1302_Time[4]<0){DS1302_Time[4]=59;}
	}
	if(KeyNum==7)
	{
		DS1302_Time[5]--;
		KeySet=7;
		if(DS1302_Time[5]<0){DS1302_Time[5]=59;}
	}
	if((KeySet==1||KeySet==5)&&TimeSetFlashFlag==0){Nixie(1,11);Nixie(2,11);	}
		else{Nixie(1,DS1302_Time[3]/10);Nixie(2,DS1302_Time[3]%10);}
	if((KeySet==2||KeySet==6)&&TimeSetFlashFlag==0){Nixie(4,11);Nixie(5,11);	}
		else{Nixie(4,DS1302_Time[4]/10);Nixie(5,DS1302_Time[4]%10);}
	if((KeySet==3||KeySet==7)&&TimeSetFlashFlag==0){Nixie(7,11);Nixie(8,11);	}
		else{Nixie(7,DS1302_Time[5]/10);Nixie(8,DS1302_Time[5]%10);}
		
}

void Timing()
{
	  DS1302_ReadTime();
	  Nixie(1,DS1302_Time[3]/10);
		Nixie(2,DS1302_Time[3]%10);
		Nixie(4,DS1302_Time[4]/10);
		Nixie(5,DS1302_Time[4]%10);
		Nixie(7,DS1302_Time[5]/10);
		Nixie(8,DS1302_Time[5]%10);
		if(TimeSetFlashFlag==0)
		{
			Nixie(3,10);
			Nixie(6,10);
		}
		if(DS1302_Time[3]>23){DS1302_Time[3]=0;}
		if(DS1302_Time[4]>59){DS1302_Time[4]=0;}
		if(DS1302_Time[5]>59){DS1302_Time[5]=0;}
	
}

void main()
{
	DS1302_Init();
	Timer0Init();
	DS1302_SetTime();
	UART_Init();
	while(1)
	{	
		KeyNum=MatrixKey();
		if(KeyNum)//每执行一次MatrixKey函数KeyNum就会清零
		{
			if(KeyNum==4){MODE=1;DS1302_SetTime();}
			else if(KeyNum==8){MODE=2;DS1302_SetTime();}
		}
		switch(MODE)
		{	
			case 0:Init();break;
			case 1:Set();break;
			case 2:Timing();break;
		}
		
	}
	
	
}

//定时器0.5s
void Timer0_Routine() interrupt 1
{
	  static unsigned int T0Count;
		TL0 = 0x66;		//设置定时初值
	  TH0 = 0xFC;		//设置定时初值
		T0Count++;
		if( T0Count>=500)
		{
			T0Count=0;
			TimeSetFlashFlag=~TimeSetFlashFlag;//1/0变化
		}
}

NixieTable.c模块

#include <REGX52.H>
#include "Delay.h"
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40,0x00};
//第10位是-,11位不显示

void Nixie(unsigned char Location,Number)
{
	switch(Location)
	{
		case 1:P2_4=1;P2_3=1;P2_2=1;break;
		case 2:P2_4=1;P2_3=1;P2_2=0;break;
		case 3:P2_4=1;P2_3=0;P2_2=1;break;
		case 4:P2_4=1;P2_3=0;P2_2=0;break;
		case 5:P2_4=0;P2_3=1;P2_2=1;break;
		case 6:P2_4=0;P2_3=1;P2_2=0;break;
		case 7:P2_4=0;P2_3=0;P2_2=1;break;
		case 8:P2_4=0;P2_3=0;P2_2=0;break;
	}
	P0=NixieTable[Number];
    Delay (1);
	P0=0x00;
}	

DS1302.c模块

#include <REGX52.H>

sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;

#define DS1302_SECOND   0x80
#define DS1302_MINUTE   0x82
#define DS1302_HOUR     0x84
#define DS1302_DATE     0x86
#define DS1302_MONTH    0x88
#define DS1302_DAY      0x8A
#define DS1302_YEAR     0x8C
#define DS1302_WP       0x8E

char DS1302_Time[]={1,2,0,12,00,00,6};//年 月 日 时 分 秒 星期

void DS1302_Init()
{
	//上电时引脚都自动置1,所以要先初始化置0
	DS1302_CE=0;
	DS1302_SCLK=0;
}
/**
  * @brief  DS1302写一个字节
  * @param  Command 命令字/地址
  * @param  Data 要写入的数据,已经存在后八位寄存器里了
  * @retval 无
  */
void DS1302_WriteByte(unsigned char Command,Data)
{
	unsigned char i;
	DS1302_CE=1;//打开开关,可以开始写了
	
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	
		for(i=0;i<8;i++)
	{
		DS1302_IO=Data&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	DS1302_CE=0;
}

/**
  * @brief  DS1302读一个字节
  * @param  Command 命令字/地址,读完之后就知道我要显示哪种类型的数据(h?min?s?)
  * @param  返回已经已经存入,后八位寄存器里的数据(这里由DS1302自己控制)
  * @retval 无
  */
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i,Data=0x00;
	//Command|=0x01;	//将指令转换为读指令
	Command|=0x01;
	DS1302_CE=1;
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=0;//读和写相反
		DS1302_SCLK=1;
	}
	for(i=0;i<8;i++)
	{
		DS1302_SCLK=1;//过滤掉一个脉冲,先置1
		DS1302_SCLK=0;
		if(DS1302_IO){Data|=(0x01<<i);}//记录输出数据,每当输出1时,Data的这一位记录为1
	}
		DS1302_CE=0;
	  DS1302_IO=0;//必须置0,否则数据会出错
    return Data;
}

void DS1302_SetTime(void)
{
	DS1302_WriteByte(DS1302_WP,0x00);//关闭写保护
	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);
	DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
	DS1302_WriteByte(DS1302_DATE,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
	DS1302_WriteByte(DS1302_HOUR,DS1302_Time[3]/10*16+DS1302_Time[3]%10);
	DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[4]/10*16+DS1302_Time[4]%10);
	DS1302_WriteByte(DS1302_SECOND,DS1302_Time[5]/10*16+DS1302_Time[5]%10);
	DS1302_WriteByte(DS1302_DAY,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
	DS1302_WriteByte(DS1302_WP,0x80);//打开写保护
}

void DS1302_ReadTime(void)
{
	unsigned char Temp;
	Temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[0]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DATE);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_HOUR);
	DS1302_Time[3]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MINUTE);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_SECOND);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DAY);
	DS1302_Time[6]=Temp/16*10+Temp%16;

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值