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

模块化编程

 LCD1602调试工具

 矩阵键盘

 MatrixKey.c

#include <STC89C5xRC.H>
#include "Delay.h"
 
unsigned char MatrixKey()
{
	unsigned char KeyNumber=0;
	
	P1=0xFF;
	P13=0;
	if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=1;}
	if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=5;}
	if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=9;}
	if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=13;}
	
	P1=0xFF;
	P12=0;
	if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=2;}
	if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=6;}
	if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=10;}
	if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=14;}
	
	P1=0xFF;
	P11=0;
	if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=3;}
	if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=7;}
	if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=11;}
	if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=15;}
	
	P1=0xFF;
	P10=0;
	if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=4;}
	if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=8;}
	if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=12;}
	if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=16;}
	
	return KeyNumber;
}

矩阵键盘密码锁

#include <STC89C5xRC.H>
#include "LCD1602.h"
#include "Delay.h"
#include "MatrixKey.h"
 
unsigned char KeyNum;
unsigned int Password, Count;
 
void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"Password:");
	while(1)
	{
		KeyNum=MatrixKey();
		if(KeyNum)
		{
			if(KeyNum<=10)  // 如果S1~S10按键按下,输入密码
			{
				if(Count<4)  // 密码四位数
				{
				Password*=10;  //  密码左移一位,这样就可以依次输入密码
				Password+=KeyNum%10;  // 获取一位密码,加入到原密码,此时10为0
				Count++;
				}
			}
			LCD_ShowNum(2,1,Password,4);
			if(KeyNum==11)  // 确认
			{
				if(Password==1234)
				{
					LCD_ShowString(1,14,"OK ");
					Password=0;
					Count=0;
					LCD_ShowNum(2,1,Password,4);
				}
				else
				{
					LCD_ShowString(1,14,"ERR");
					Password=0;
					Count=0;
					LCD_ShowNum(2,1,Password,4);
				}
			}
			if(KeyNum==12)  //取消
			{
					Password=0;
					Count=0;
					LCD_ShowString(1,14,"   ");
					LCD_ShowNum(2,1,Password,4);
			}
		}
	}
}

 定时器

 1、定时器介绍

 2、定时器框图 

  3、定时器工作模式

 4、中断程序流程

  5、定时器和中断系统

独立按键控制流水灯模式,并由定时器执行流水灯。

#include <STC89C5xRC.H>
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H>
 
unsigned char KeyNum,LEDMode;
 
void main()
{
	P2=0xFE;
	Timer0Init();
	while(1)
	{
		KeyNum=Key();		//获取独立按键键码
		if(KeyNum)			//如果按键按下
		{
			if(KeyNum==1)	//如果K1按键按下
			{
				LEDMode++;	//模式切换,按1下按键是模式1,按2下是模式0,默认模式0
				if(LEDMode>=2)LEDMode=0;
			}
		}
	}
}
 
void Timer0_Routine() interrupt 1  //中断函数标识,含优先级
{
	static unsigned int T0Count;  //静态变量,拥有局部作用域,全局生命周期
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;		//T0Count计次,对中断频率进行分频
	if(T0Count>=500)//分频500次,500ms
	{
		T0Count=0;
		if(LEDMode==0)			//模式判断
			P2=_crol_(P2,1);	//LED输出(循环左移函数,即使流水灯循环左移)
		if(LEDMode==1)
			P2=_cror_(P2,1);
	}
}

 定时器时钟

#include <STC89C5xRC.H>
#include "Timer0.h"
#include "Delay.h"
#include "LCD1602.h"
 
unsigned char Sec, Min=59, Hour=23;
 
void main()
{
	Timer0Init();
	LCD_Init();
	LCD_ShowString(1,1,"Clock:");
	while(1)
	{
		LCD_ShowNum(2,1,Hour,2);
		LCD_ShowString(2,3,":");
		LCD_ShowNum(2,4,Min,2);
		LCD_ShowString(2,6,":");
		LCD_ShowNum(2,7,Sec,2);
	}
}
 
void Timer0_Routine() interrupt 1  //中断函数标识,含优先级
{
	static unsigned int T0Count;  //静态变量,拥有局部作用域,全局生命周期
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;		//T0Count计次,对中断频率进行分频
	if(T0Count>=1000)//1000ms
	{
		T0Count=0;
		Sec++;
		if(Sec>=60)
		{
			Sec=0;
			Min++;
			if(Min>=60)
			{
				Min=0;
				Hour++;
				if(Hour>=24)
				{
					Hour=0;
				}
			}
		}
	}
}

 串口通信

串口介绍

串口的硬件电路

电平标准

我们单片机使用的就是TTL电平;(缺点:只能传输10米之内)

CAN总线以及USB使用的是RS485电平,通过两根线的压差来区分,也就是查分信号;而不是用电源正负极来区分电压。(最大传送距离可以达到千米以上)

 接口及引脚定义:

常见的通信接口

串口参数和时序图

串口向电脑发送数据

#include <STC89C5xRC.H>
#include "Delay.h"
#include "UART.h"
 
unsigned char Sec;
 
void main()
{
	UartInit();
	while(1)
	{
		UART_SendByte(Sec);
		Sec++;
		Delay(1);  // 必要的延时,避免误差导致乱码,没误差的时候可以不需要
	}
}
#include <REGX52.H>

/**
  * @brief  串口初始化,4800bps@12.000MHz
  * @param  无
  * @retval 无
  */
void UART_Init()
{
	SCON=0x40;
	PCON |= 0x80;
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xF3;		//设定定时初值
	TH1 = 0xF3;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}

/**
  * @brief  串口发送一个字节数据
  * @param  Byte 要发送的一个字节数据
  * @retval 无
  */
void UART_SendByte(unsigned char Byte)
{
	SBUF=Byte;
	while(TI==0);
	TI=0;
}

 电脑通过串口控制LED

#include <STC89C5xRC.H>
#include "Delay.h"
#include "UART.h"
 
unsigned char Sec;
 
void main()
{
	UartInit();
	while(1)
	{
 
	}
}
 
void UART_Routine() interrupt 4
{
	if(RI==1)
	{
		P2=~SBUF;  // 读寄存器的数据
		UART_SendByte(SBUF);
		RI=0;  // 说明书要求手动复位
	}
}

LED点阵屏与显示图形

1、LED点阵屏介绍

 2、显示原理

 3、74HC595模块原理图

4、74HC595介绍

5、开发板引脚对应关系

6、C51的sfr、sbit 

main.c 

#include <STC89C5xRC.H>
#include "Delay.H"
 
sbit RCK=P3^5;  //RCLK
sbit SCK=P3^6;  //SRCLK
sbit SER=P3^4;	//SER
 
#define MATRIX_LED_PORT  P0
 
void _74HC595_WriteByte(unsigned char Byte)
{
//	SER=Byte&0x80;  //一般是0、1赋值,不过,如果非0,都会当作1
//	SCK=1;
//	SCK=0;
//	SER=Byte&0x60;
//	SCK=1;
//	SCK=0;
	unsigned char i;
	for(i=0;i<8;i++)
	{
		SER=Byte&(0x80>>i);
		SCK=1;
		SCK=0;
	}
		RCK=1;
		RCK=0;
}
 
void MatrixLED_ShowColumn(unsigned char Column, Data)
{
	_74HC595_WriteByte(Data);
//	if(Column==0){P0=~0x80;}
//	if(Column==1){P0=~0x40;}
	MATRIX_LED_PORT=~(0x80>>Column);
	Delay(1);
	MATRIX_LED_PORT=0xFF;
	
}
 
void main()
{
	SCK=0;
	RCK=0;
	while(1)
	{
//		_74HC595_WriteByte(0xAA);
		MatrixLED_ShowColumn(0,0x80);
		MatrixLED_ShowColumn(1,0x40);
		MatrixLED_ShowColumn(2,0x20);
		MatrixLED_ShowColumn(3,0x10);
	}
}

 LED点阵屏显示动画

#include <STC89C5xRC.H>
#include "Delay.H"
#include "MatrixLED.H"
 
unsigned char Animation[]={
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 为了显示更好看,避免第一列直接显示字符本身
0xFF,0x10,0x10,0x10,0xFF,0x00,0x1E,0x29,0x29,0x29,0x18,0x00,0xFE,0x01,0x02,0x00,
0xFE,0x01,0x02,0x00,0x0E,0x11,0x11,0x0E,0x00,0x7D,0x7D,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 为了显示更好看
};
 
void main()
{
	unsigned char i, Offset=1, Count=0;
	while(1)
	{
	for(i=0;i<8;i++)
		{
			MatrixLED_ShowColumn(i,Animation[i+Offset]);
		}
		Count++;
		if(Count>10)
		{
			Count=0;
			Offset++;
			if(Offset>40)
			{
			Offset=0; //防止数组溢出
			}
		}
	}
}

 DS1302实时时钟

时序图中是对CE(操作使能)、SCLK(时钟)、I/O(数据)三个引脚的操作,

在SCLK的上升沿,MCU向时钟写入数据,在SCLK的下降沿,时钟向MCU写入数据,也等价于MCU向时钟读取数据;

I/O引脚,左边半部分是表示命令字,从左到右是命令字八个位的从低位到高位;右边半部分表示要写入的字节,从左到右也是字节的从低位到高位。

main.c

#include <STC89C5xRC.H>
#include "LCD1602.h"
#include "DS1302.h"
 
//  unsigned char Second, Minute;
 
void main()
{
	LCD_Init();
	DS1302_Init();
	
//	DS1302_WriteByte(0x8E, 0x00);  // 解除芯片写保护,避免数值不动
//	DS1302_WriteByte(0x80, 0x54);
	
	DS1302_SetTime();
	
	while(1)
	{
		DS1302_ReadTime();
		LCD_ShowNum(1,1,DS1302_TIME[0],2);
		LCD_ShowNum(1,4,DS1302_TIME[1],2);
		LCD_ShowNum(1,7,DS1302_TIME[2],2);
		LCD_ShowNum(2,1,DS1302_TIME[3],2);
		LCD_ShowNum(2,4,DS1302_TIME[4],2);
		LCD_ShowNum(2,7,DS1302_TIME[5],2);
 
//		Second=DS1302_ReadByte(0x81);
//		Minute=DS1302_ReadByte(0x83);
//		LCD_ShowNum(2,1,Second/16*10+Second%16,2);
//		LCD_ShowNum(2,3,Minute/16*10+Minute%16,2);
	}
}

DS1302.c

#include <STC89C5xRC.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
 
 
unsigned char DS1302_TIME[]={19,11,16,12,59,55,6};
 
void DS1302_Init(void)
{
	DS1302_CE=0;
	DS1302_SCLK=0;
}
 
void DS1302_WriteByte(unsigned char Command, Data)
{
	unsigned char i;
	DS1302_CE=1;
	
//	DS1302_IO=Command&0x01;
//	DS1302_SCLK=1;  // 速度慢可以不加延时,有些速度快的芯片需要增加延时
//	DS1302_SCLK=0;
//	
//	DS1302_IO=Command&0x02;
//	DS1302_SCLK=1;
//	DS1302_SCLK=0;
	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; //完成一次操作,释放IO
}
 
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i,Data=0x00;
	Command|=0x01;  //
	DS1302_CE=1;
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=0;  //根据时序操作
		DS1302_SCLK=1;
	}
//	DS1302_SCLK=0;
//	DS1302_SCLK=1;
//	if(DS1302_IO)
//	{
//		Data=Data|0x01;
//	}
//	DS1302_SCLK=0;
//	DS1302_SCLK=1;
//	if(DS1302_IO)
//	{
//		Data=Data|0x02;
//	}
		for(i=0;i<8;i++)
	{
		DS1302_SCLK=1;  //重复置1是去掉一个周期,为的是满足时序
		DS1302_SCLK=0;
		if(DS1302_IO){Data|=(0x01<<i);}
	}
	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,0x00);
}
 
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;
}

 DS1302可调时钟

#include <STC89C5xRC.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Key.h"
#include "Timer0.h"
 
unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag;
 
void TimeShow(void)//时间显示功能
{
	DS1302_ReadTime();//读取时间
	LCD_ShowNum(1,1,DS1302_Time[0],2);//显示年
	LCD_ShowNum(1,4,DS1302_Time[1],2);//显示月
	LCD_ShowNum(1,7,DS1302_Time[2],2);//显示日
	LCD_ShowNum(2,1,DS1302_Time[3],2);//显示时
	LCD_ShowNum(2,4,DS1302_Time[4],2);//显示分
	LCD_ShowNum(2,7,DS1302_Time[5],2);//显示秒
}
 
void TimeSet(void)//时间设置功能
{
	if(KeyNum==2)//按键2按下
	{
		TimeSetSelect++;//设置选择位加1
		TimeSetSelect%=6;//越界清零
	}
	if(KeyNum==3)//按键3按下
	{
		DS1302_Time[TimeSetSelect]++;//时间设置位数值加1
		if(DS1302_Time[0]>99){DS1302_Time[0]=0;}//年越界判断
		if(DS1302_Time[1]>12){DS1302_Time[1]=1;}//月越界判断
		if( DS1302_Time[1]==1 || DS1302_Time[1]==3 || DS1302_Time[1]==5 || DS1302_Time[1]==7 || 
			DS1302_Time[1]==8 || DS1302_Time[1]==10 || DS1302_Time[1]==12)//日越界判断
		{
			if(DS1302_Time[2]>31){DS1302_Time[2]=1;}//大月
		}
		else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 || DS1302_Time[1]==9 || DS1302_Time[1]==11)
		{
			if(DS1302_Time[2]>30){DS1302_Time[2]=1;}//小月
		}
		else if(DS1302_Time[1]==2)
		{
			if(DS1302_Time[0]%4==0)
			{
				if(DS1302_Time[2]>29){DS1302_Time[2]=1;}//闰年2月
			}
			else
			{
				if(DS1302_Time[2]>28){DS1302_Time[2]=1;}//平年2月
			}
		}
		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;}//秒越界判断
	}
	if(KeyNum==4)//按键3按下
	{
		DS1302_Time[TimeSetSelect]--;//时间设置位数值减1
		if(DS1302_Time[0]<0){DS1302_Time[0]=99;}//年越界判断
		if(DS1302_Time[1]<1){DS1302_Time[1]=12;}//月越界判断
		if( DS1302_Time[1]==1 || DS1302_Time[1]==3 || DS1302_Time[1]==5 || DS1302_Time[1]==7 || 
			DS1302_Time[1]==8 || DS1302_Time[1]==10 || DS1302_Time[1]==12)//日越界判断
		{
			if(DS1302_Time[2]<1){DS1302_Time[2]=31;}//大月
			if(DS1302_Time[2]>31){DS1302_Time[2]=1;}
		}
		else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 || DS1302_Time[1]==9 || DS1302_Time[1]==11)
		{
			if(DS1302_Time[2]<1){DS1302_Time[2]=30;}//小月
			if(DS1302_Time[2]>30){DS1302_Time[2]=1;}
		}
		else if(DS1302_Time[1]==2)
		{
			if(DS1302_Time[0]%4==0)
			{
				if(DS1302_Time[2]<1){DS1302_Time[2]=29;}//闰年2月
				if(DS1302_Time[2]>29){DS1302_Time[2]=1;}
			}
			else
			{
				if(DS1302_Time[2]<1){DS1302_Time[2]=28;}//平年2月
				if(DS1302_Time[2]>28){DS1302_Time[2]=1;}
			}
		}
		if(DS1302_Time[3]<0){DS1302_Time[3]=23;}//时越界判断
		if(DS1302_Time[4]<0){DS1302_Time[4]=59;}//分越界判断
		if(DS1302_Time[5]<0){DS1302_Time[5]=59;}//秒越界判断
	}
	//更新显示,根据TimeSetSelect和TimeSetFlashFlag判断可完成闪烁功能
	if(TimeSetSelect==0 && TimeSetFlashFlag==1){LCD_ShowString(1,1,"  ");}
	else {LCD_ShowNum(1,1,DS1302_Time[0],2);}
	if(TimeSetSelect==1 && TimeSetFlashFlag==1){LCD_ShowString(1,4,"  ");}
	else {LCD_ShowNum(1,4,DS1302_Time[1],2);}
	if(TimeSetSelect==2 && TimeSetFlashFlag==1){LCD_ShowString(1,7,"  ");}
	else {LCD_ShowNum(1,7,DS1302_Time[2],2);}
	if(TimeSetSelect==3 && TimeSetFlashFlag==1){LCD_ShowString(2,1,"  ");}
	else {LCD_ShowNum(2,1,DS1302_Time[3],2);}
	if(TimeSetSelect==4 && TimeSetFlashFlag==1){LCD_ShowString(2,4,"  ");}
	else {LCD_ShowNum(2,4,DS1302_Time[4],2);}
	if(TimeSetSelect==5 && TimeSetFlashFlag==1){LCD_ShowString(2,7,"  ");}
	else {LCD_ShowNum(2,7,DS1302_Time[5],2);}
}
 
void main()
{
	LCD_Init();
	DS1302_Init();
	Timer0Init();
	LCD_ShowString(1,1,"  -  -  ");//静态字符初始化显示
	LCD_ShowString(2,1,"  :  :  ");
	
	DS1302_SetTime();//设置时间
	
	while(1)
	{
		KeyNum=Key();//读取键码
		if(KeyNum==1)//按键1按下
		{
			if(MODE==0){MODE=1;TimeSetSelect=0;}//功能切换
			else if(MODE==1){MODE=0;DS1302_SetTime();}
		}
		switch(MODE)//根据不同的功能执行不同的函数
		{
			case 0:TimeShow();break;
			case 1:TimeSet();break;
		}
	}
}
 
void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;
	if(T0Count>=500)//每500ms进入一次
	{
		T0Count=0;
		TimeSetFlashFlag=!TimeSetFlashFlag;//闪烁标志位取反
	}
}

任务

main.c

#include <REGX52.H>
#include "Delay.h"
#include "Timer.h"
#include "Keyscan.h"
#include "DS1302.h"
#include "Nixie.h"

unsigned char KeyNum,Select,Mode,flag1,flag2,flag3,flag4;

void ShowTime(){
		DS1302_ReadTime();
		Nixie(1,DS1302_Time[3]/10);
		Nixie(2,DS1302_Time[3]%10);
		if(flag1){		
			Nixie(3,11);
			Nixie(6,11);
		}else{
			Nixie(3,12);
			Nixie(6,12);
		}
		Nixie(4,DS1302_Time[4]/10);
		Nixie(5,DS1302_Time[4]%10);
		Nixie(7,DS1302_Time[5]/10);
		Nixie(8,DS1302_Time[5]%10);
}

void SetTime(){
	if(Select==0){		
	Nixie(1,DS1302_Time[3]/10);
	Nixie(2,DS1302_Time[3]%10);
	Nixie(3,11);
	Nixie(6,11);
	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(KeyNum==1||KeyNum==5) Select=3;	
	if(Select==3){
		if(Select==3&&flag2){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);
		Nixie(3,11);
		Nixie(6,11);
		if(KeyNum==1){
			DS1302_Time[Select]++;
			if (DS1302_Time[3] > 23) DS1302_Time[3] = 0;
		}
		else if(KeyNum==5){
			DS1302_Time[Select]--;
			if (DS1302_Time[3] < 0) DS1302_Time[3] = 23;
		}
	}
	if(KeyNum==2||KeyNum==6) Select=4;		
	if(Select==4){
		if(Select==4&&flag2){Nixie(4,DS1302_Time[4]/10);Nixie(5,DS1302_Time[4]%10);}		
		Nixie(1,DS1302_Time[3]/10);
		Nixie(2,DS1302_Time[3]%10);
		Nixie(7,DS1302_Time[5]/10);
		Nixie(8,DS1302_Time[5]%10);
		Nixie(3,11);
		Nixie(6,11);
		if(KeyNum==2){
			DS1302_Time[Select]++;
			if (DS1302_Time[4] > 59) DS1302_Time[4] = 0;
		}
		else if(KeyNum==6){
			DS1302_Time[Select]--;
			if (DS1302_Time[4] < 0) DS1302_Time[4] = 59;
		}
	}
	if(KeyNum==3||KeyNum==7) Select=5;		
	if(Select==5){
		if(Select==5&&flag2){Nixie(7,DS1302_Time[5]/10);Nixie(8,DS1302_Time[5]%10);}		
		Nixie(4,DS1302_Time[4]/10);
		Nixie(5,DS1302_Time[4]%10);
		Nixie(1,DS1302_Time[3]/10);
		Nixie(2,DS1302_Time[3]%10);
		Nixie(3,11);
	  Nixie(6,11);
		if(KeyNum==3){
			DS1302_Time[Select]++;
			if (DS1302_Time[5] > 59) DS1302_Time[5] = 0;
		}
		else if(KeyNum==7){
			DS1302_Time[Select]--;
			if (DS1302_Time[5] < 0) DS1302_Time[5] = 59;
		}
	}
}

void main(){
	DS1302_Init();
	Timer0_Init();
	DS1302_SetTime();
	while(1){
		KeyNum=Key();	
		if(KeyNum==8) {Mode=0;Select=0;DS1302_SetTime();}
		else if(KeyNum==4) {Mode=1;}
	switch(Mode){		
		case 0:ShowTime();break;
		case 1:SetTime();break;
		}
void Timer0_Routine() interrupt 1
{
	static unsigned int T0count; 
	TL0 = 0x66;
	TH0 = 0xFC;
	T0count++;
	if(T0count>=500){
		T0count=0;
		if(Mode==0) flag1=!flag1;		
		if(Mode==1) flag2=!flag2;		
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值