第九届省赛真题电子定时器
第九届省赛真题
主函数代码(不包含各模块初始化代码)
#include "main.h"
#include "rcc.h"
#include "led_key.h"
#include "lcd.h"
#include "tim.h"
#include "i2c.h"
//***通过滴答定时器实现执行速度控制变量
__IO uint32_t uwTick_LED_Speed_Ctrl;
__IO uint32_t uwTick_KEY_Speed_Ctrl;
__IO uint32_t uwTick_LCD_Speed_Ctrl;
__IO uint32_t uwTick_KEY_Time_Count;
__IO uint32_t uwTick_Time_Count_down_Crtl;
__IO uint32_t uwTick_LED_BuLingBuLing_Crtl;
//***全局变量区
uint8_t ucLED; //控制LED的变量
//*按键三行代码变量
uint8_t key_value,key_up,key_down;
static uint8_t key_old;
uint8_t LCD_String_Disp[21];
uint8_t Status_Selection = 0; //状态选择变量 默认为0
uint8_t Storage_Location = 1; //存储位置 1-2-3-4-5-1 默认为1
uint8_t Time_Set[3]; //时间设置
__IO uint32_t Time_Count_down_temp; //开始计时时用于存储总秒数的变量
//*子函数声明区
void SystemClock_Config(void);
void LED_Proc(void);
void KEY_Proc(void);
void LCD_Proc(void);
void KEY_B3_Proc(void);
//***主函数区
int main(void)
{
HAL_Init();
SystemClock_Config();
//*初始化函数区
LED_KEY_Init();
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(Magenta);
TIM3_Init();
//HAL_TIM_PWM_Start(&htim3 , TIM_CHANNEL_1);
I2CInit();
//*掉电重启后 显示存储位置1的定时时间
I2C_24c02_read(Time_Set , 0 , 3); //将默认为存储位置1的数据读入Time_Set
while (1)
{
LED_Proc();
KEY_Proc();
LCD_Proc();
}
}
//***子函数区
//*LED处理子函数
void LED_Proc(void)
{
if((uwTick - uwTick_LED_Speed_Ctrl)<100) return;
uwTick_LED_Speed_Ctrl = uwTick; //控制子函数执行速度为100ms
LED_Disp(ucLED);
}
//*按键B3处理
void KEY_B3_Proc(void)
{
if(Status_Selection == 1) //高亮小时状态
{
Time_Set[0]+=1; //小时+1
if(Time_Set[0] == 24)
Time_Set[0] = 0;
}
else if(Status_Selection == 2) //高亮分钟状态
{
Time_Set[1]+=1; //分钟+1
if(Time_Set[1] == 60)
Time_Set[1] = 0;
}
else if(Status_Selection == 3) //高亮秒状态
{
Time_Set[2]+=1; //秒+1
if(Time_Set[2] == 60)
Time_Set[2] = 0;
}
}
//*KEY处理子函数
void KEY_Proc(void)
{
if((uwTick - uwTick_KEY_Speed_Ctrl)<50) return;
uwTick_KEY_Speed_Ctrl = uwTick; //控制子函数执行速度为50ms
key_value = KEY_Scan();
key_down = key_value & (key_value ^ key_old);
key_up = ~key_value & (key_value ^ key_old);
key_old = key_value;
if(key_down)
{
uwTick_KEY_Time_Count = uwTick;
}
if((uwTick - uwTick_KEY_Time_Count) < 800) //短按
{
switch(key_up)
{
case 1: //B1按下 切换存储位置
if(Status_Selection == 0)
{
if( ++Storage_Location == 6)
Storage_Location = 1;
I2C_24c02_read(Time_Set, 3*(Storage_Location-1) ,3); //将对应存储位置的值从EEPROM中读出
}
break;
case 2: //B2短按 来回切换时分秒的高亮位置
if( ++Status_Selection == 4)
Status_Selection = 1;
break;
case 3: //B3短按 对应选中的高亮时间+1
KEY_B3_Proc();
break;
case 4: //B4短按 在除Running状态下的任何状态下按下着切换到Running状态 在Running状态下按下则切换至Pause状态
if(Status_Selection != 4)
{
Status_Selection = 4;
HAL_TIM_PWM_Start(&htim3 , TIM_CHANNEL_1); //定时器开启 PA6口输出PWM信号
}
else
{
Status_Selection = 5;
HAL_TIM_PWM_Stop(&htim3 , TIM_CHANNEL_1); //定时器暂停 停止输出PWM信号
ucLED = 0x00; //关闭LED
}
uwTick_Time_Count_down_Crtl = uwTick; //在B4按下后便开始计时
Time_Count_down_temp = Time_Set[0]*3600 + Time_Set[1]*60 + Time_Set[2]; //计时时间的总秒数
break;
}
}
else //长按
{
switch(key_value)
{
case 2: //长按B2 状态选择从时间Seeting界面进入Standby界面 并存储设置的时间
if(Status_Selection == 1||Status_Selection == 2||Status_Selection == 3)
{
Status_Selection = 0; //切换到状态0-Standby界面
//将设置状态的时间写入EEPROM对应的存储位置中 显示在Standby状态的相应存储位置
I2C_24c02_write(Time_Set, 3*(Storage_Location-1) ,3);
}
break;
case 3: //B3长按 对应选中的高亮时间持续+1
KEY_B3_Proc();
break;
case 4: //短按B4 退出Running界面 进入Standby界面
Status_Selection = 0;
//将EEPROM存储在对应位置的定时时间读入Time_Set
I2C_24c02_read(Time_Set, 3*(Storage_Location-1) ,3);
HAL_TIM_PWM_Stop(&htim3 , TIM_CHANNEL_1); //定时器关闭 停止输出PWM信号
ucLED = 0x00; //关闭LED
break;
}
}
}
void LCD_Proc(void)
{
if((uwTick - uwTick_LCD_Speed_Ctrl)<100) return;
uwTick_LCD_Speed_Ctrl = uwTick; //控制子函数执行速度为100ms
memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
sprintf((char*)LCD_String_Disp , " No %1d ",Storage_Location);
LCD_DisplayStringLine(Line0 , LCD_String_Disp);
//***只在状态4-Running界面和状态5-Pause界面有效
if(Status_Selection == 4 || Status_Selection==5)
{
if((uwTick - uwTick_Time_Count_down_Crtl)>=1000)
{
uwTick_Time_Count_down_Crtl = uwTick; //每秒执行一次
if(Status_Selection == 4) //在状态4-定时器Running状态下 开始倒计时
Time_Count_down_temp -= 1; //时间减少1s
}
//*开启倒计时后以秒为单位变化的时间
Time_Set[0] = Time_Count_down_temp/3600; //小时
Time_Set[1] = Time_Count_down_temp%3600/60; //分钟
Time_Set[2] = Time_Count_down_temp%3600%60; //秒
}
//***只在状态4定时器开启 Running界面有效
if(Status_Selection ==4)
{
if((uwTick - uwTick_LED_BuLingBuLing_Crtl)>=500) //定时器开启 LED以0.5s频率闪烁
{
uwTick_LED_BuLingBuLing_Crtl = uwTick;
ucLED ^=0x01;
}
}
//void LCD_DisplayChar(u8 Line, u16 Column, u8 Ascii); //LCD字符显示函数
//第一个参数代表行
//第二个参数代表列第i列的公式为320-(16*i),则代表是i列
//第三个参数为需要显示的Ascii码值 数字需要+0x30 字符' '
//***时间显示处理(包含高亮处理)
if(Status_Selection == 1) LCD_SetBackColor(Blue); //状态1-Seeting状态 高亮显示小时
LCD_DisplayChar(Line4 , (320 - (16 * 6)) , Time_Set[0]/10 + 0x30);
LCD_DisplayChar(Line4 , (320 - (16 * 7)) , Time_Set[0]%10 + 0x30);
LCD_SetBackColor(Black);
LCD_DisplayChar(Line4 , (320 - (16 * 8)) , ':');
if(Status_Selection == 2) LCD_SetBackColor(Blue); //状态2-Seeting状态 高亮显示分钟
LCD_DisplayChar(Line4 , (320 - (16 * 9)) , Time_Set[1]/10 + 0x30);
LCD_DisplayChar(Line4 , (320 - (16 * 10)) , Time_Set[1]%10 + 0x30);
LCD_SetBackColor(Black);
LCD_DisplayChar(Line4 , (320 - (16 * 11)) , ':');
if(Status_Selection == 3) LCD_SetBackColor(Blue); 状态3-Seeting状态 高亮显示秒
LCD_DisplayChar(Line4 , (320 - (16 * 12)) , Time_Set[2]/10 + 0x30);
LCD_DisplayChar(Line4 , (320 - (16 * 13)) , Time_Set[2]%10 + 0x30);
LCD_SetBackColor(Black);
//***不同状态对应的界面
if(Status_Selection == 0) //状态0
{
memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
sprintf((char*)LCD_String_Disp , " Standby ");
LCD_DisplayStringLine(Line7 , LCD_String_Disp);
}
else if(Status_Selection == 4) //状态4
{
memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
sprintf((char*)LCD_String_Disp , " Running ");
LCD_DisplayStringLine(Line7 , LCD_String_Disp);
}
else if(Status_Selection == 5) //状态4
{
memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
sprintf((char*)LCD_String_Disp , " Pause ");
LCD_DisplayStringLine(Line7 , LCD_String_Disp);
}
else //状态1-2-3
{
memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
sprintf((char*)LCD_String_Disp , " Setting ");
LCD_DisplayStringLine(Line7 , LCD_String_Disp);
}
}