蓝桥杯(嵌入式)总决赛
- 总结
-
- 试题分析
- 参赛感想
- 代码分享
总结
试题分析
这一届国赛试题总体来说难度很小,和省赛的难度差不多。考到了LED,KEY,ADC,PWM的输入捕获和PWM的输出,和第八届国赛有点相似,所以试题挺简单,就看你的细节以及选择题做的怎么样了。原本想拿国一,可实力不允许呀,拿了国二👀
参赛感想
好不容易进了决赛,很遗憾北京没有去成/(ㄒoㄒ)/~~,拿了国二,成绩不算好,也还说得过去.原本以为今年国赛会挺难的,毕竟省赛很简单,结果国赛和省赛的难度差不多.程序上就靠细节拉分了,再就是看选择题谁猜得准了.别人我不知道,反正我的选择题猜了好几个😄,感觉选择题很难准备,考的范围比较大,让俺无从下手,所以俺就听天由命,猜对一个是一个🤭.考了五个小时,坐着硬硬的板凳,敲着脏脏键盘,仰着脖子,不好受呀,我的电脑还老提醒我更新,隔一个小时提醒一次🤮,我就只能让它再等一个小时,再等一个小时…不容易呀
代码分享
led.c文件
#include "led.h"
//LED初始化
void LED_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOD Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC, ENABLE);
/* Configure PD0 and PD2 in output pushpull mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_Init(GPIOC, &GPIO_InitStructure);
LED_Control(0x00);
}
//LED控制函数
void LED_Control(u8 status)
{
GPIOC->ODR=(~status)<<8;
GPIOD->BSRR=GPIO_Pin_2;
GPIOD->BRR=GPIO_Pin_2;
}
key.c文件
#include "key.h"
#include "main.h"
//初始化
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOD Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA, ENABLE);
/* Configure PD0 and PD2 in output pushpull mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_8;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
extern _KEY_ENUM KEY_Short;//定义的枚举型变量,在main.h中展示
//按键的宏定义
#define K1_Read (GPIOA->IDR&GPIO_Pin_0)
#define K2_Read (GPIOA->IDR&GPIO_Pin_8)
#define K3_Read (GPIOB->IDR&GPIO_Pin_1)
#define K4_Read (GPIOB->IDR&GPIO_Pin_2)
//按键的读取
void KEY_Read(void)
{
static u8 KEY_Clear=0;
static FlagStatus KEY_Wait=RESET;
static _KEY_ENUM KEY_Temp=KOFF;
if(K1_Read==0||K2_Read==0||K3_Read==0||K4_Read==0)
{
if(++KEY_Clear>=3) //消抖处理
{
if(K1_Read==0) KEY_Temp=K1;
else if(K2_Read==0) KEY_Temp=K2;
else if(K3_Read==0) KEY_Temp=K3;
else if(K4_Read==0) KEY_Temp=K4;
KEY_Wait=SET;
}
}
else
{
KEY_Clear=0;
if(KEY_Wait!=RESET)
{
KEY_Wait= RESET;
KEY_Short=KEY_Temp;
KEY_Temp=KOFF;
}
}
}
tim2.c文件(PWM的输入捕获)
//初始化
void TIM_Input(void)
{
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* GPIOA clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Enable the TIM3 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* TIM3 channel 2 pin (PA.07) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period =0xffff;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_Cmd(TIM2, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM2, TIM_IT_CC2|TIM_IT_CC3, ENABLE);
}
//中断服务函数
u8 OC2_Mode=0;
u32 OC2_H=0;
u32 OC2_HL=0;
u8 OC3_Mode=0;
u32 OC3_H=0;
u32 OC3_HL=0;
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
switch(OC2_Mode)
{
case 0:
{
OC2_H=0;
OC2_HL=0;
OC2_Mode=1;
TIM_SetCounter(TIM2,0x00);
TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Falling);
break;
}
case 1:
{
OC2_H=TIM_GetCounter(TIM2);
OC2_Mode=2;
TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Rising);
break;
}
case 2:
{
OC2_HL=TIM_GetCounter(TIM2);
OC2_Mode=3;
TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Rising);
break;
}
default:break;
}
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);
switch(OC3_Mode)
{
case 0:
{
OC3_H=0;
OC3_HL=0;
OC3_Mode=1;
TIM_SetCounter(TIM2,0x00);
TIM_OC3PolarityConfig(TIM2,TIM_ICPolarity_Falling);
break;
}
case 1:
{
OC3_H=TIM_GetCounter(TIM2);
OC3_Mode=2;
TIM_OC3PolarityConfig(TIM2,TIM_ICPolarity_Rising);
break;
}
case 2:
{
OC3_HL=TIM_GetCounter(TIM2);
OC3_Mode=3;
TIM_OC3PolarityConfig(TIM2,TIM_ICPolarity_Rising);
break;
}
default:break;
}
}
}
tim3.c文件(PWM的输出)
//我这里用的是比较输出,输出的占空比固定为50%
u32 TIM3_Fre=0;
u32 TIM3_Dut=0;
void TIM_Output(u32 Fre)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* GPIOA and GPIOB clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*GPIOB Configuration: TIM3 channel1, 2, 3 and 4 */
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM3_Fre=1000000/Fre;
TIM3_Dut=TIM3_Fre*50/100;
TIM_TimeBaseStructure.TIM_Period = 0xffff;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = TIM3_Fre;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);
TIM_ARRPreloadConfig(TIM3, DISABLE);
TIM_ITConfig(TIM3, TIM_IT_CC2 , ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
//中断服务函数
u32 capture=0;
u8 TIM3_Flag=0;
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
capture = TIM_GetCapture2(TIM3);
if(TIM3_Flag)
{
TIM_SetCompare2(TIM3, capture + TIM3_Dut);
}
else
{
TIM_SetCompare2(TIM3, capture + TIM3_Fre - TIM3_Dut);
}
TIM3_Flag^=1;
}
}
main.h文件(一些结构体.枚举类型变量的定义)
typedef enum
{
K1=1,
K2=2,
K3=3,
K4=4,
KOFF=0,
}_KEY_ENUM;//按键
typedef struct
{
float AO1;
float AO2;
u32 PULS1;
u32 PULS2;
}_DATA_Struct;//主界面显示的数据
typedef struct
{
u8 VD;
u8 FD;
u8 VD1;
u8 FD1;
}_LED_Struct;//报警的灯
adc.c文件
//初始化
void ADCx2_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
/* Configure PC.04 (ADC Channel14) as analog input -------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel14 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_55Cycles5);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
}
//
u32 Get_ADC(u8 channel)
{
u32 temp;
ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_55Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
ADC_ClearFlag(ADC1,ADC_FLAG_EOC);
temp=ADC1->DR;
ADC_SoftwareStartConvCmd(ADC1, DISABLE);
return temp;
}
//简单的一个均值滤波
u32 Filt_Num(u8 channel)
{
u8 i;
u32 sum=0;
for(i=0;i<10;i++)
{
sum+=Get_ADC(channel);
}
return sum/10;
}
main.c文件(逻辑地实现)
u32 TimingDelay = 0;
u8 string[20];
_KEY_ENUM KEY_Short=KOFF;
_DATA_Struct DATA_Val={0.0,0.0,2000,1000,};
_LED_Struct LED_Show={1,2,1,2};
FlagStatus LCD_Sow_Flag=RESET; //zhu jie mian
FlagStatus _10ms_EN=RESET;
FlagStatus _100ms_EN=RESET;
FlagStatus _500ms_EN=RESET;
FlagStatus _800ms_EN=RESET;
u32 Pin7_Fre;
u8 count=0;
u8 status=0;
u8 LED_Status=0x00;
extern u8 OC2_Mode;
extern u32 OC2_H;
extern u32 OC2_HL;
extern u8 OC3_Mode;
extern u32 OC3_H;
extern u32 OC3_HL;
//相关函数的声明
void Delay_Ms(u32 nTime);
void LCD_Pro(void);
void Get_Volt(void);
void KEY_Pro(void);
//Main Body
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SysTick_Config(SystemCoreClock/1000);
Delay_Ms(200);
STM3210B_LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
LED_init();
ADCx2_Init();
KEY_Init();
TIM_Input();
count=count+1;
while(1)
{
if(_10ms_EN!=RESET)
{
KEY_Pro();
_10ms_EN=RESET;
}
if(_100ms_EN!=RESET)
{
LCD_Pro();
Get_Volt();
_100ms_EN=RESET;
LED_Control(LED_Status);
}
if(count==1)
{
Pin7_Fre=DATA_Val.PULS1;
count++;
}
if(_800ms_EN!=RESET)
{
if(status==0)
{
Pin7_Fre=DATA_Val.PULS1;
}
else if(status==1)
{
Pin7_Fre=DATA_Val.PULS2;
}
_800ms_EN=RESET;
TIM_Output(Pin7_Fre);
}
}
}
//LCD显示函数
void LCD_Pro(void)
{
if(LCD_Sow_Flag==RESET)
{
LCD_DisplayStringLine(Line1,(u8*)" DATA ");
sprintf((char*)string," V1:%2.1fV ",DATA_Val.AO1);
LCD_DisplayStringLine(Line3,string);
sprintf((char*)string," V2:%2.1fV ",DATA_Val.AO2);
LCD_DisplayStringLine(Line4,string);
if(_500ms_EN!=RESET)
{
_500ms_EN=RESET ;
if(OC2_Mode==3)
{
DATA_Val.PULS1=1000000/OC2_HL;
sprintf((char*)string," F1:%dHz ",DATA_Val.PULS1);
LCD_DisplayStringLine(Line5,string);
OC2_Mode=0;
}
if(OC3_Mode==3)
{
DATA_Val.PULS2=1000000/OC3_HL;
sprintf((char*)string," F2:%dHz ",DATA_Val.PULS2);
LCD_DisplayStringLine(Line6,string);
OC3_Mode=0;
}
if(DATA_Val.PULS1>DATA_Val.PULS2)
{
LED_Status|=0x01<<(LED_Show.FD1-1);
}
else
LED_Status&=~(0x01<<(LED_Show.FD1-1));
}
}
else if(LCD_Sow_Flag!=RESET)
{
LCD_DisplayStringLine(Line1,(u8*)" PARA ");
sprintf((char*)string," VD:LD%d ",LED_Show.VD);
LCD_DisplayStringLine(Line3,string);
sprintf((char*)string," FD:LD%d ",LED_Show.FD);
LCD_DisplayStringLine(Line4,string);
LCD_DisplayStringLine(Line5,(u8*)" ");
LCD_DisplayStringLine(Line6,(u8*)" ");
}
}
//获取两个通道的电压值
void Get_Volt(void)
{
DATA_Val.AO1=Filt_Num(4)*3.3/4095.0;
DATA_Val.AO2=Filt_Num(5)*3.3/4095.0;
if(DATA_Val.AO1>DATA_Val.AO2)
{
LED_Status|=0x01<<(LED_Show.VD1-1);
}
else
LED_Status&=~(0x01<<(LED_Show.VD1-1));
}
//案件处理函数
void KEY_Pro(void)
{
KEY_Read();
switch(KEY_Short)
{
case KOFF:break;
case K1:
{
KEY_Short=KOFF;
if(LCD_Sow_Flag==RESET)
{
LCD_Sow_Flag=SET;
}
else if(LCD_Sow_Flag!=RESET)
{
LED_Status=0x00;
LCD_Sow_Flag=RESET;
LED_Show.VD1=LED_Show.VD;
LED_Show.FD1=LED_Show.FD;
}
break;
}
case K2:
{
KEY_Short=KOFF;
if(LCD_Sow_Flag!=RESET)
{
if(LED_Show.VD==8)
{
if(LED_Show.FD!=1)
LED_Show.VD=1;
else
LED_Show.VD=2;
}
else if(LED_Show.VD==7)
{
if(LED_Show.FD!=8)
LED_Show.VD=LED_Show.VD+1;
else
LED_Show.VD=1;
}
else if(LED_Show.VD<7)
{
if((LED_Show.VD+1)!=LED_Show.FD)
LED_Show.VD=LED_Show.VD+1;
else
LED_Show.VD=LED_Show.VD+2;
}
}
break;
}
case K3:
{
KEY_Short=KOFF;
if(LCD_Sow_Flag!=RESET)
{
if(LED_Show.FD==8)
{
if(LED_Show.VD!=1)
LED_Show.FD=1;
else
LED_Show.FD=2;
}
else if(LED_Show.FD==7)
{
if(LED_Show.VD!=8)
LED_Show.FD=LED_Show.FD+1;
else
LED_Show.FD=1;
}
else if(LED_Show.FD<7)
{
if((LED_Show.FD+1)!=LED_Show.VD)
LED_Show.FD=LED_Show.FD+1;
else
LED_Show.FD=LED_Show.FD+2;
}
}
break;
}
case K4:
{
KEY_Short=KOFF;
if(status==0)
{
status=1;
}
else if(status==1)
{
status=0 ;
}
break;
}
}
}
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
//滴答定时器
void SysTick_Handler(void)
{
static u32 _10ms_Flag=0,_100ms_Flag=0,_500ms_Flag=0,_800ms_Flag=0;
_10ms_Flag++;
_100ms_Flag++;
_500ms_Flag++;
_800ms_Flag++;
if(_800ms_Flag>=1000)
{
_800ms_Flag=0;
_800ms_EN=SET;
}
if(_10ms_Flag>=10)
{
_10ms_Flag=0;
_10ms_EN=SET;
}
if(_100ms_Flag>=100)
{
_100ms_Flag=0;
_100ms_EN=SET;
}
if(_500ms_Flag>=500)
{
_500ms_Flag=0;
_500ms_EN=SET;
}
TimingDelay--;
}