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);
}