蓝桥杯嵌入式-电子定时器

https://blog.csdn.net/ReCclay/article/details/87902240
文章借鉴了这位大佬的代码思想!

#读题
1.本题的初始化设置难度正常,而对于逻辑的考察是重点
2.本题自己认为需要解读出的潜在信息:
1)按键B1只有在定时器停止状态才能切换储存位置;
2)“短按B2键进入时间设置状态”指要体现出从其他状态进入设置状态的代码,并且这里我认为只能从停止状态进入设置,运行和暂停不能进入设置状态。
3)“如果是临时设置定时时间,则不需储存,直接按定时器启动按键”和下面按键B4的短按功能相对应。
4)注意倒计时的计算变量应化成以秒为单位,而储存和显示时化为时分秒的形式。
#知识点
高亮某一行中的某几个字符
运用到LCD_DisplayChar()函数
LCD分辨率为240X320,共10行,每行24*320,行从上到下Line0-Line9,列是 从右往左0-319;两个字符同时显示,至少要隔15个像素,不然会产生覆盖,不美观。
设置单个字符颜色用到了LCD_DisplayChar函数,同时要注意只能操作一个数字,并且该函数传入的是数字对应的ASCII,所以需要加上0x30,或者加上字符0,即’0’.

#上主函数代码(初始化部分不在呈现)

#include"led.h"
#include"stm32f10x.h"
#include"pwm.h"
#include"key.h"
#include"timer.h"
#include"lcd.h"
#include"i2c.h"
#include"e2prom.h"
#include"stdio.h"


/*     变量声明区     */
extern u32 delaytime;
extern u8 flag200ms;
extern u8 flag1s;
extern u8 flag500ms;
u8 str[20];
u32 LED_MODE=0xffff;
u8 modeflag=0;//模式:0-停止;1-设置;2-运行;3-暂停;
u8 packflag=0;//存储位置:0,1,2,3,4;
u8 lightflag=1;//高亮选择:0-不高亮;1-高亮时;2-高亮分;3-高亮秒;
int sum;//作为总时间:单位秒,判断时有负数
u8 hour=0;
u8 min=0;
u8 sec=0;

/*     函数声明区     */
void delay_ms(u32 time);
void KeyAction(int code,u8 sta);
void ReadE2Time(void);
void WriteE2Time(void);
void KeyUp(void);
void Display(void);//刷新屏幕的时间总是200ms

int main()
{  	
	SysTick_Config(SystemCoreClock/1000);	
	led_Init();
	TIM4_Init(2000,72);//2ms刷新定时器
	STM3210B_LCD_Init();
	i2c_init();

	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);

	ReadE2Time();//先读取E2中:时,分,秒
	while(1)						
	{
		KeyDriver();
		if(flag200ms)//刷新屏幕的时间总是200ms
		{
			Display();
			flag200ms=0;
		}
		if(flag1s)
		{
			if(modeflag==2)//处于运行模式才倒计时
			{
				sum=hour*3600+min*60+sec; 
				sum--;//倒计时1s减一
				if(sum<0)
				{
					sum=0;
				}
				hour=sum/3600;
				min=sum%3600/60;
				sec=sum%3600%60;
			}
			flag1s=0;
		}

	}
}
void Display()
{
	sprintf((char*)str,"  NO %d",packflag+1);
	LCD_DisplayStringLine(Line1,str);
	
	/* 解决复位停止状态时的高亮 */
	if(modeflag==0)
	{
		lightflag=0;
	}
	/* 时间显示 */
	if(lightflag==1)
	{
		LCD_SetTextColor(Green);
	}
	else 
	{
		LCD_SetTextColor(White);
	}
	LCD_DisplayChar(Line4,240,hour/10+'0');
	LCD_DisplayChar(Line4,225,hour%10+'0');
	LCD_SetTextColor(White);
	LCD_DisplayChar(Line4,210,':');
	

	if(lightflag==2)
	{
		LCD_SetTextColor(Green);
	}
	else 
	{
		LCD_SetTextColor(White);
	}
	LCD_DisplayChar(Line4,195,min/10+'0');
	LCD_DisplayChar(Line4,180,min%10+'0');
	LCD_SetTextColor(White);
	LCD_DisplayChar(Line4,165,':');

	if(lightflag==3)
	{
		LCD_SetTextColor(Green);
	}
	else 
	{
		LCD_SetTextColor(White);
	}
	LCD_DisplayChar(Line4,150,sec/10+'0');
	LCD_DisplayChar(Line4,135,sec%10+'0');
	LCD_SetTextColor(White);

	/* 状态显示  */
	switch(modeflag)
	{
		case 0 : LCD_DisplayStringLine(Line7,(u8*)"       Standby");break;
		case 1 : LCD_DisplayStringLine(Line7,(u8*)"       Setting");break;
		case 2 : LCD_DisplayStringLine(Line7,(u8*)"       Running");break;
		case 3 : LCD_DisplayStringLine(Line7,(u8*)"         Pause");break;//保持尾对齐,避免出现乱码Pauseng
		default : break;
	}
	/* LED和PWM输出 */
	if(modeflag==2)
	{
		if(flag500ms==1)
		{
			PWM_Init(1000,80,1);
			LED_MODE^=(1<<8);
			flag500ms=0;
		}		
	}
	else
	{
		PWM_Init(1000,80,0);
		LED_MODE|=(1<<8);
	}
	GPIOC->ODR=LED_MODE;
	GPIOD->ODR|=(1<<2);
	GPIOD->ODR&=~(1<<2);
		
}
void WriteE2Time()
{
	switch(packflag)
	{
		case 0: E2Write(0x00,hour);delay_ms(5);E2Write(0x01,min);delay_ms(5);E2Write(0x02,sec);delay_ms(5);break;
		case 1: E2Write(0x03,hour);delay_ms(5);E2Write(0x04,min);delay_ms(5);E2Write(0x05,sec);delay_ms(5);break;
	    case 2: E2Write(0x06,hour);delay_ms(5);E2Write(0x07,min);delay_ms(5);E2Write(0x08,sec);delay_ms(5);break;
		case 3: E2Write(0x09,hour);delay_ms(5);E2Write(0x0A,min);delay_ms(5);E2Write(0x0B,sec);delay_ms(5);break;
		case 4: E2Write(0x0C,hour);delay_ms(5);E2Write(0x0D,min);delay_ms(5);E2Write(0x0E,sec);delay_ms(5);break;
		default : break;
	}	
}
void ReadE2Time()
{
	switch(packflag)
	{
		case 0 : hour=E2Read(0x00);delay_ms(5);min=E2Read(0x01);delay_ms(5);sec=E2Read(0x02);delay_ms(5);break;	
		case 1 : hour=E2Read(0x03);delay_ms(5);min=E2Read(0x04);delay_ms(5);sec=E2Read(0x05);delay_ms(5);break;
		case 2 : hour=E2Read(0x06);delay_ms(5);min=E2Read(0x07);delay_ms(5);sec=E2Read(0x08);delay_ms(5);break;
		case 3 : hour=E2Read(0x09);delay_ms(5);min=E2Read(0x0A);delay_ms(5);sec=E2Read(0x0B);delay_ms(5);break;
		case 4 : hour=E2Read(0x0C);delay_ms(5);min=E2Read(0x0D);delay_ms(5);sec=E2Read(0x0E);delay_ms(5);break;
		default : break;
	}	
}
void KeyUp()
{
	switch(lightflag)
	{
		case 1 : hour++;if(hour>24)hour=0;break;
		case 2 : min++;if(min>60)   min=0;break;
		case 3 : sec++;if(sec>60)   sec=0;break;
		default : break; 
	}	
}

void KeyAction(int code,u8 sta)
{
	if(sta==0)//短按操作
	{
	 	if(code==1)
		{
			if(modeflag==0)//只有在停止状态才能切换存储位置
			{
				packflag++;
				if(packflag>4)
				{
					packflag=0;
				}
				ReadE2Time();	
			}
		}
		else if(code==2)
		{
			if(modeflag==0)//处于停止状态时,B2按下进入设置状态;并且运行和暂停状态时,B2不会改变状态
			{
				modeflag=1;
				lightflag=1;//保证进入设置时有高亮显示
			}
			else if(modeflag==1)//设置
			{
				lightflag++;
				if(lightflag>3)
				{
					lightflag=1;
				}
			}
		}
		else if(code==3)
		{
			if(modeflag==1)
			{
				KeyUp();
			}
		}
		else if(code==4)
		{
			if(modeflag==0)//处于停止状态,B4按下后进入运行
			{
				modeflag=2;
			}
			else if(modeflag==1)//处于设置状态,B4按下后进入运行,但不保存数据???
			{
				modeflag=2;
			}
			else if(modeflag==2)
			{
				modeflag=3;
			}
			else if(modeflag==3)
			{
				modeflag=2;
			}
		}
	}
	else if(sta==1)//长按操作
	{  
		if(code==2)
		{
			if(modeflag==1)
			{
				modeflag=0;
				WriteE2Time();
			}
		}
		else if(code==3)
		{
			if(modeflag==1)
			{
				KeyUp();
			}
		}
		else if(code==4)
		{
			if(modeflag==2||modeflag==3)
			{
				modeflag=0;
			}
		}	
	}		
}
void delay_ms(u32 time)
{
	delaytime=time;
	while(delaytime!=0);
}















发布了7 篇原创文章 · 获赞 0 · 访问量 111

猜你喜欢

转载自blog.csdn.net/weixin_43636084/article/details/105164907