单片机7-10

发布时间:2024年01月23日

目录

定时器

按键控制LED流水灯关键代码

定时器时钟关键代码

串口通信

?编辑串口向电脑发送数据

电脑通过串口控制LED

LED点阵屏

? LED点阵屏显示图形

LED点阵屏显示动画

DS1302

DS1302时钟显示

DS1302时钟调节

定时器

为什么12MHz的工作周期为一微秒:

12NHz时钟频率下,12MHz = 12,000KHz = 12,000,000Hz,一个时钟振荡周期就是1/12000000秒,亦即1/12微秒,标准MCS51系列单片机的一个机器周期是12个时钟振荡周期,也就是12 * (1/12) = 1微秒;
6MHz时钟频率下,6MHz = 6,000KHz = 6,000,000Hz,一个时钟振荡周期就是1/6000000秒,亦即1/6微秒,标准MCS51系列单片机的一个机器周期是12个时钟振荡周期,也就是12 * (1/6) = 2微秒。

初始化定时器(手写)

void Timer0_Init(){
	//TMOD = 0x01;//选择工作模式1,可能会修改到高位所设定的值;给寄存器赋值需要使用十六位
	TMOD &= 0xF0;//把TMOD的低四位进行清零,高四位保持不变
	TMOD |= 0x01;//把TMOD的最低位设置为1,高四位保持不变
	TF0 = 0;//中断溢出标志
	TR0 = 1;//T0的运行控制位,使其开始工作
	TH0 = 64535 / 256;//高位	为什么是256:一个八位寄存器最大显示255(1111 1111)
	TL0 = 64535 % 256 + 1;//低位	再多就需要其他寄存器存储,这样就能分成高位与低位
	//此时开始计时,到溢出时刚好1ms(1000us);
	ET0 = 1;//中断是否被允许
	EA = 1;//所有中断是否被允许
	PT0 = 0;//中断优先级
}

生成(注意加上中断相关参数)

void Timer0Init(void)		//1微秒@12.000MHz
{
	//AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}
按键控制LED流水灯关键代码

key.c文件

#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  获取独立按键键码
  * @param  无
  * @retval 按下按键的键码,范围 0~4,无按键按下时,返回值为0
  */
unsigned char Key(){
	unsigned char KeyNum = 0;
	
	if(P3_1 == 0){ Delay(20); while(P3_1 == 0) Delay(20); KeyNum = 1;}
	if(P3_0 == 0){ Delay(20); while(P3_0 == 0) Delay(20); KeyNum = 2;}
	if(P3_2 == 0){ Delay(20); while(P3_2 == 0) Delay(20); KeyNum = 3;}
	if(P3_3 == 0){ Delay(20); while(P3_3 == 0) Delay(20); KeyNum = 4;}
	return KeyNum;

}

Timer0.c文件

#include <REGX52.H>
/**
  * @brief  定时器0初始化,1微秒@12.000MHz
  * @param  无
  * @retval 无
  */
void Timer0Init(void)		//1微秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0 = 1;	
	EA = 1;
	PT0 = 0;
}

/*	定时器中断函数模板,中断后要做的事
void Timer0_Routine() interrupt 1{
	static unsigned int T0Count;
	T0Count ++;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	if( T0Count >= 1000 ){
		T0Count = 0;
		P2_0 = ~P2_0;
	}

}
*/

main.c文件

#include <REGX52.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 ){
				LEDMode ++;
				if(LEDMode >= 2) LEDMode = 0;
			}
			
		}
		
	}

}



void Timer0_Routine() interrupt 1{
	static unsigned int T0Count;
	T0Count ++;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	if( T0Count >= 500 ){500ms进行一次操作
		T0Count = 0;
		if(LEDMode == 0)
			P2 = _crol_(P2,1);//左移	越界后会将移出值放到最末位
		if(LEDMode == 1)
			P2 = _cror_(P2,1);//右移
	}
}

定时器时钟关键代码

main.c

#include <REGX52.H>
#include "Timer0.h"
#include "Delay.h"
#include "LCD1602.h"

unsigned char Sec,Min,Hour;

void main(){
	LCD_Init();
	Timer0Init(); 
	
	LCD_ShowString(1,1,"Clock");
	LCD_ShowString(2,3,":");
	LCD_ShowString(2,6,":");
	
	while( 1 ){
		LCD_ShowNum(2,1,Hour,2);
		LCD_ShowNum(2,4,Min,2);
		LCD_ShowNum(2,7,Sec,2);
	}

}

void Timer0_Routine() interrupt 1{
	static unsigned int T0Count;
	T0Count ++;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	if( T0Count >= 1000 ){//每一秒进行操作
		T0Count = 0;
		Sec ++;
		if(Sec >= 60){
			Sec = 0;
			Min ++;
			if(Min >= 60){
				Min = 0;
				Hour ++;
				if(Hour >= 24){
					Hour = 0;
				}
			}
		}
	}

}

串口通信

注意:使用生成代码工具时,记得查看表单是否所有选项均正确,记得点击生成C代码,而不是直接复制粘贴

波特率计算

找到起始值TH1 = 0xF4? ? ? ? 用256减去起始值TH1得12us溢出一次? ? ? ? 获得溢出率为1/12MHz

再看是否设置翻倍,(如果有则先/2)没有则直接 /16即得到波特率当前单位为MHz



串口向电脑发送数据

UART.c

#include <REGX52.H>

/**
  * @brief  串口初始化,4800bps@12.000MHz
  * @param  无
  * @retval 无
  */
void UART_Init(){
	SCON = 0x40;//0100 0000配置SCON寄存器
	PCON |= 0x80;		//使能波特率倍速位SMOD,将最高位置一,使得波特率加倍 
	
	//初始化定时器0
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器1模式,配置为模式2,八位自动重装
	TL1 = 0xF3;		//设定定时初值
	TH1 = 0xF3;		//设定定时器重装值
	ET1 = 0;			//禁止定时器1中断
	TR1 = 1;		//定时器1开始计时
	
}

/**
  * @brief  串口发送一个字节数据
  * @param  Byte 要发送的一个字节
  * @retval 无
  */
void UART_SendByte(unsigned char Byte){
	SBUF = Byte;//写入SBUF
	while(TI == 0);//数据发送未完成,TI为0,数据发送完成时,TI才会置1
	TI = 0;//数据发送完成后,将TI 的值重新赋值为0(未赋值前TI应为0)
}

main.c

#include <REGX52.H>
#include "Delay.h"
#include "UART.h"

unsigned char Sec;

void main(){
	UART_Init();
	
	while( 1 ){
		
		UART_SendByte(Sec); 
		Sec++;
		Delay(1000);
		 
	}

}
电脑通过串口控制LED

这里改了TL1以及TL2才成功,我买的单片机晶振频率为11.0592,大伙注意一下,修改一下生成的需求列表。

UART.c

#include <REGX52.H>

/**
  * @brief  串口初始化,4800bps@12.000MHz
  * @param  无
  * @retval 无
  */
void UART_Init(){
	SCON = 0x50;//0101 0000配置SCON寄存器,并设置为可接收
	PCON |= 0x80;		//使能波特率倍速位SMOD,将最高位置一,使得波特率加倍 
	
	//初始化定时器1
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器1模式,配置为模式2,八位自动重装
	TL1 = 0xF4;		//设定定时初值
	TH1 = 0xF4;		//设定定时器重装值,
	ET1 = 0;			//禁止定时器1中断
	TR1 = 1;		//定时器1开始计时
	
	//中断配置
	EA = 1;	//CPU开放中断
	ES = 1;	//允许串行口中断
}

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

/**
  * @brief  串口中断函数模板
  * @param  无
  * @retval 无
  */
//中断服务函数
void UART_Routine() interrupt 4{
	if(RI == 1){//为真则说明SBUF中有数据
		
		RI = 0;
	}
}

main.c

#include <REGX52.H>
#include "Delay.h"
#include "UART.h"

void main(){
	UART_Init();
	
	while( 1 ){
		
		
		 
	}

}

//中断服务函数
void UART_Routine() interrupt 4{
	if(RI == 1){//为真则说明SBUF中有数据
		P2 = ~SBUF;//低电平才会亮 ,将SBUF中的值读出
		UART_SendByte(SBUF);
		Delay(1);
		RI = 0;
	}
}

LED点阵屏

点阵上方的跳线帽放左边两个。

? LED点阵屏显示图形

main.c

#include <REGX52.H>
#include "Delay.h"

sbit RCK = P3^5;	//特殊位声明,RCLK,上升沿锁存,P3的第五位等同P3_5
sbit SCK = P3^6;	//特殊位声明,串行时钟,SERCLK,上升沿移位
sbit SER = P3^4;	//特殊位声明,输入,SER

#define MATRIX_LED_PORT	P0

/**
  * @brief  74HC595写入一个字节
  * @param  Byte	要写入的字节
  * @retval 无
  */

void _74HC595_WriteByte(unsigned char Byte){
	unsigned char i;
	for( i = 0; i < 8; i++){
		SER = Byte & 0x80 >> i;//将一位(从最高位到最低位)值取出赋值给SER
		SCK = 1;//进行移位
		SCK = 0;//重置	
	}
	//P2 = Byte;//这里点亮LED进行测试0xf0,最高位控制D8,高位8~5为1故灭,低位4~1为0亮
	RCK = 1;//输出
	RCK = 0;//重置
}

/**
  * @brief  LED点阵屏显示一列数据
  * @param  Column	列号,范围:0~7,0在最左侧
	* @param	Data	选择列显示的数据,范围:0~0xFF,1为亮,0为灭
  * @retval 无
  */

void MatrixLED_ShowColumn(unsigned char Column,Data){//操作列,
	_74HC595_WriteByte(Data);//将设置亮的位置写入点阵中,
	//1为点亮,这里是列写入数据,为阳极,故1才能点亮
	
	 MATRIX_LED_PORT = ~(0x80 >> Column);//选择列,0为选中,列为阴极,故0才能选中
	
	 Delay(1);//消影
	 MATRIX_LED_PORT = 0xFF;//位清零
	
}

void main(){
	SCK = 0;//初始化,当这个值为高电平时,进行移位操作
	RCK = 0;//初始化,当这个值为高电平时,进行输出操作
	
	while( 1 ){
		MatrixLED_ShowColumn(0,0x3C);//这里各位为1才亮
		MatrixLED_ShowColumn(1,0x42);//这里各位为1才亮
		MatrixLED_ShowColumn(2,0xA9);//这里各位为1才亮
		MatrixLED_ShowColumn(3,0x85);//这里各位为1才亮
		MatrixLED_ShowColumn(4,0x85);//这里各位为1才亮
		MatrixLED_ShowColumn(5,0xA9);//这里各位为1才亮
		MatrixLED_ShowColumn(6,0x42);//这里各位为1才亮
		MatrixLED_ShowColumn(7,0x3C);//这里各位为1才亮
	}

}
LED点阵屏显示动画

MatrixLED.c

#include <REGX52.H>
#include "Delay.h"

sbit RCK = P3^5;	//特殊位声明,RCLK,上升沿锁存,P3的第五位等同P3_5
sbit SCK = P3^6;	//特殊位声明,串行时钟,SERCLK,上升沿移位
sbit SER = P3^4;	//特殊位声明,输入,SER

#define MATRIX_LED_PORT	P0

/**
  * @brief  74HC595写入一个字节
  * @param  Byte	要写入的字节
  * @retval 无
  */
void _74HC595_WriteByte(unsigned char Byte){
	unsigned char i;
	for( i = 0; i < 8; i++){
		SER = Byte & 0x80 >> i;//将一位(从最高位到最低位)值取出赋值给SER
		SCK = 1;//进行移位
		SCK = 0;//重置	
	}
	//P2 = Byte;//这里点亮LED进行测试0xf0,最高位控制D8,高位8~5为1故灭,低位4~1为0亮
	RCK = 1;//输出
	RCK = 0;//重置
}

/**
  * @brief  点阵屏初始化
  * @param  无
  * @retval 无
  */
void MatrixLED_Init(){
	SCK = 0;//初始化,当这个值为高电平时,进行移位操作
	RCK = 0;//初始化,当这个值为高电平时,进行输出操作
}

/**
  * @brief  LED点阵屏显示一列数据
  * @param  Column	列号,范围:0~7,0在最左侧
	* @param	Data	选择列显示的数据,范围:0~0xFF,1为亮,0为灭
  * @retval 无
  */
void MatrixLED_ShowColumn(unsigned char Column,Data){//操作列,
	_74HC595_WriteByte(Data);//将设置亮的位置写入点阵中,
	//1为点亮,这里是按为写入列数据,横向为阳极,故1才能点亮
	
	 MATRIX_LED_PORT = ~(0x80 >> Column);//选择列,0为选中,列为阴极,故0才能选中
	
	 Delay(1);//消影
	 MATRIX_LED_PORT = 0xFF;//位清零
	
}

main.c

#include <REGX52.H>
#include "Delay.h"
#include "MatrixLED.h"

unsigned char code Animation[] = {//放入flash存储中
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0xFF,0x08,0x08,0x08,0xFF,0x00,0x1E,0x25,
	0x25,0x25,0x19,0x00,0xFE,0x01,0x02,0x00,
	0xFE,0x01,0x02,0x00,0x1C,0x22,0x41,0x22,
	0x1C,0x00,0x7D,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};

void main(){
	
	unsigned char i,offset=0,Count=0;
	void MatrixLED_Init();
	
	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

点阵上方跳线帽放右边2个。?

DS1302时钟显示

DS1302.c

#include <REGX52.H>

//引脚定义
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;

//寄存器写入地址/指令定义
#define DS1302_SEC		0x80
#define DS1302_MIN		0x82
#define DS1302_HOUR			0x84
#define DS1302_DAY			0x86
#define DS1302_MONTH		0x88
#define DS1302_WEEK			0x8A
#define DS1302_YEAR			0x8C
#define DS1302_WP			0x8E

//时间数组,索引0~6分别为年、月、日、时、分、秒、星期
unsigned char DS1302_Time[]={24,1,20,23,59,55,6};

/**
  * @brief  DS1302初始化
  * @param  无
  * @retval 无
  */
void DS1302_Init(void)
{
	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 命令字/地址
  * @retval 读出的数据
  */
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;
	}
	for(i=0;i<8;i++)
	{
		DS1302_SCLK=1;
		DS1302_SCLK=0;
		if(DS1302_IO){Data|=(0x01<<i);}
	}
	DS1302_CE=0;
	DS1302_IO=0;	//读取后将IO设置为0,否则读出的数据会出错
	return Data;
}

/**
  * @brief  DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
  * @param  无
  * @retval 无
  */
void DS1302_SetTime(void)
{
	DS1302_WriteByte(DS1302_WP,0x00);
	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码后写入
	DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
	DS1302_WriteByte(DS1302_DAY,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_MIN,DS1302_Time[4]/10*16+DS1302_Time[4]%10);
	DS1302_WriteByte(DS1302_SEC,DS1302_Time[5]/10*16+DS1302_Time[5]%10);
	DS1302_WriteByte(DS1302_WEEK,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
	DS1302_WriteByte(DS1302_WP,0x80);
}

/**
  * @brief  DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
  * @param  无
  * @retval 无
  */
void DS1302_ReadTime(void)
{
	unsigned char Temp;
	Temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取
	Temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DAY);
	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_MIN);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_SEC);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_WEEK);
	DS1302_Time[6]=Temp/16*10+Temp%16;
}

main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "instrins.h"

void main(){
	
	LCD_Init();
	DS1302_Init(); 
	
	LCD_ShowString(1,3,"-  -  ");
	LCD_ShowString(2,3,":  :  ");
	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);//显示秒
		//LCD_ShowNum(2,12,DS1302_Time[6],1);//显示周几
	}

}
DS1302时钟调节

main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Timer0.h"
#include "Key.h"

unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag;

/**
  * @brief  从DS1302_Time数组中进行时间读取操作
  * @param  无
  * @retval 无
  */
void TimeShow(){
		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);//显示秒
		//LCD_ShowNum(2,12,DS1302_Time[6],1);//显示周几
}

/**
  * @brief  进行时间修改操作
  * @param  无
  * @retval 无
  */
void TimeSet(){
	if(KeyNum == 2)
	{
		//if(TimeSetSelect > 5)TimeSetSelect = 0;
		TimeSetSelect++;
		TimeSetSelect %= 6;//越界判断
	}
	if(KeyNum == 3)
	{
		DS1302_Time[TimeSetSelect] ++;//判断越界
		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;}
					else
					{
						if(DS1302_Time[2] > 28){DS1302_Time[2] = 1;}
					}
				} 
		}
		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){
		DS1302_Time[TimeSetSelect] --;
		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;}
					if(DS1302_Time[2] > 29){DS1302_Time[2] = 1;}
					else
					{
						if(DS1302_Time[2] < 1){DS1302_Time[2] = 28;}
						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;}
	}
		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);}

	LCD_ShowNum(2,10,TimeSetSelect,2);
	LCD_ShowNum(2,13,TimeSetFlashFlag,2);
	
}

void main(){
	
	LCD_Init();
	DS1302_Init(); 
	Timer0Init();
	
	LCD_ShowString(1,3,"-  -  ");
	LCD_ShowString(2,3,":  :  ");
	DS1302_SetTime();//设置时间
	
	while( 1 ){
		
		KeyNum = Key();
		if(KeyNum == 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;
		}
		
	}

}

/**
  * @brief  中断操作
  * @param  无
  * @retval 无
  */
void Timer0_Routine() interrupt 1{
	static unsigned int T0Count;
	T0Count ++;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	if( T0Count >= 500 ){
		T0Count = 0;
		TimeSetFlashFlag = !TimeSetFlashFlag; //是否修改标志位
	}

}

文章来源:https://blog.csdn.net/qq_45981247/article/details/135682654
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。