第十五届蓝桥杯嵌入式省赛真题(满分)
第十五届蓝桥杯嵌入式省赛真题
目录
第十五届蓝桥杯嵌入式省赛真题
一、题目
二、分析
1、配置
2、变量定义
3、LCD显示模块
4、按键模块
5、数据分析和处理模块
1、频率突变
2、频率超限
3、数据处理
三、评价结果
一、题目
二、分析
1、配置
首先是配置cubemx的定时器进行PA15和PB4的输入捕获,如图所示:
此图为PA15的配置,我配置为PA15为定时器2的通道1
此图为PB4的配置,我配置为PB4为定时器3的通道1
2、变量定义
uint8_t ucLcd[21]; /* LCD值(\0结束) */
uint8_t Page;
uint8_t Qinchu_flag;
int32_t Fre_A,Fre_B,Per_A,Per_B,Qinchu_Tick;
uint8_t FP_select,P_select;//0表示频率,1表示周期
int32_t PD=1000,PH=5000,NDA,NDB,NHA,NHB;
int32_t PX=0;
uint16_t usCapt_TIM2[2],usCapt_TIM3[2]; /* TIM输入捕捉值 */
3、LCD显示模块
void LCD_Proc(void)
{
static uint32_t LCD_Tick; //
if((uwTick - LCD_Tick) > 200 )
{
LCD_Tick = uwTick;
//__disable_irq();
switch (Page)
{
case 0://数据界面
sprintf((char*)ucLcd," DATA");
LCD_DisplayStringLine(Line1,ucLcd);
if(!FP_select)//频率
{
if(Fre_A>0)
{
if(Fre_A>1000)
{
sprintf((char*)ucLcd," A=%.2fKHz ",((float)Fre_A)/1000);
LCD_DisplayStringLine(Line3,ucLcd);
}
else
{
sprintf((char*)ucLcd," A=%uHz ",Fre_A);
LCD_DisplayStringLine(Line3,ucLcd);
}
}
else
{
sprintf((char*)ucLcd," A=NULL ");
LCD_DisplayStringLine(Line3,ucLcd);
}
if(Fre_B>0)
{
if(Fre_B>1000)
{
sprintf((char*)ucLcd," B=%.2fKHz ",((float)Fre_B)/1000);
LCD_DisplayStringLine(Line4,ucLcd);
}
else
{
sprintf((char*)ucLcd," B=%uHz ",Fre_B);
LCD_DisplayStringLine(Line4,ucLcd);
}
}
else
{
sprintf((char*)ucLcd," B=NULL ");
LCD_DisplayStringLine(Line4,ucLcd);
}
}
else//周期
{
if(Per_A>0)
{
if(Per_A>1000)
{
sprintf((char*)ucLcd," A=%.2fmS ",((float)Per_A)/1000);
LCD_DisplayStringLine(Line3,ucLcd);
}
else
{
sprintf((char*)ucLcd," A=%uuS ",Per_A);
LCD_DisplayStringLine(Line3,ucLcd);
}
}
else
{
sprintf((char*)ucLcd," A=NULL ");
LCD_DisplayStringLine(Line3,ucLcd);
}
if(Per_B>0)
{
if(Per_B>1000)
{
sprintf((char*)ucLcd," B=%.2fmS ",((float)Per_B)/1000);
LCD_DisplayStringLine(Line4,ucLcd);
}
else
{
sprintf((char*)ucLcd," B=%uuS ",Per_B);
LCD_DisplayStringLine(Line4,ucLcd);
}
}
else
{
sprintf((char*)ucLcd," B=NULL ");
LCD_DisplayStringLine(Line4,ucLcd);
}
}
break;
case 1://参数界面
sprintf((char*)ucLcd," PARA");
LCD_DisplayStringLine(Line1,ucLcd);
sprintf((char*)ucLcd," PD=%uHz ",PD);
LCD_DisplayStringLine(Line3,ucLcd);
sprintf((char*)ucLcd," PH=%uHz ",PH);
LCD_DisplayStringLine(Line4,ucLcd);
sprintf((char*)ucLcd," PX=%dHz ",PX);
LCD_DisplayStringLine(Line5,ucLcd);
break;
case 2://统计界面
sprintf((char*)ucLcd," RECD");
LCD_DisplayStringLine(Line1,ucLcd);
sprintf((char*)ucLcd," NDA=%u ",NDA);
LCD_DisplayStringLine(Line3,ucLcd);
sprintf((char*)ucLcd," NDB=%u ",NDB);
LCD_DisplayStringLine(Line4,ucLcd);
sprintf((char*)ucLcd," NHA=%u ",NHA);
LCD_DisplayStringLine(Line5,ucLcd);
sprintf((char*)ucLcd," NHB=%u ",NHB);
LCD_DisplayStringLine(Line6,ucLcd);
break;
default:
break;
}
//__enable_irq();
}
}
4、按键模块
/* 按键扫描 */
void KEY_Proc(void)
{
static uint32_t Key_Tick; //Key_Tick
if((uwTick - Key_Tick) > 2 )
{
Key_Tick = uwTick;
KeyHandle(KEY_Read());
}
}
/* 按键响应 */
void KeyHandle(uint8_t key)
{
switch (Page)
{
case 0://数据界面
switch (key) {
case 0:
break;
case 1:
//LD1 = !LD1;
break;
case 2:
//LD2 = !LD2;
break;
case 3:
FP_select=!FP_select;
break;
case 4:
Page++;
P_select=0;
LCD_Clear(Black);
break;
default:
break;
}
break;
case 1://参数界面
switch (key) {
case 0:
break;
case 1:
switch (P_select)
{
case 0://PD
if(PD<1000) PD+=100;
else PD=100;
break;
case 1://PH
(PH>9900)?PH=1000:(PH+=100);
break;
case 2://PX
(PX>900)?PX=-1000:(PX+=100);
break;
default:
break;
}
break;
case 2:
switch (P_select)
{
case 0://PD
PD<=100?PD=1000:(PD-=100);
break;
case 1://PH
PH<=1000?PH=10000:(PH-=100);
break;
case 2://PX
PX-=100;
if(PX<-1000)
{
PX=1000;
}
break;
default:
break;
}
break;
case 3:
if(++P_select==3)
{
P_select=0;
}
break;
case 4:
Page++;
LCD_Clear(Black);
break;
default:
break;
}
break;
case 2://计录界面
switch (key) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
if(!Qinchu_flag)
{
Qinchu_flag=1;
Qinchu_Tick=uwTick;
}
break;
case 4:
Page=0;
FP_select=0;
LCD_Clear(Black);
break;
default:
break;
}
if(Qinchu_flag&&HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2))
{
Qinchu_flag=0;
if(uwTick-Qinchu_Tick>1000)//按键超过1秒后松开按键,清零该界面下的所有记录值
{
NDA=0;NDB=0;NHA=0;NHB=0;;
}
}
break;
default:
break;
}
}
5、数据分析和处理模块
1、频率突变
因为频率是每1秒更新10个值,所以我就将30个值放在一个数组里面,对应3秒,再进行找大小
void tubian_proc(void) //突变次数计数
{
// 当数组填满30个值时,进行以下处理
if (array_ptr == 30)
{
max1_num=findMax(frqA_array,array_ptr);
min1_num=findMin(frqA_array,array_ptr);
max2_num=findMax(frqB_array,array_ptr);
min2_num=findMin(frqB_array,array_ptr);
if ((max1_num - min1_num) > PD) NDA++;
if ((max2_num - min2_num) > PD) NDB++;
for (uint8_t i=0; i < 30; i++)
{
frqA_array[i] = 0;
frqB_array[i] = 0;
}
array_ptr = 0;
}
}
2、频率超限
我们这里需要注意是当波形处于递增的时候NHA或NHA等于FH才加1,波形递减的时候,不实现,而不是简单的相交,这是一个易错点
int PHA[2],PHB[2];
void PH_beyond(void) //频率超限计数
{
PHA[1]=Fre_A;
PHB[1]=Fre_B;
if(PHA[1]>PH&&PHA[0]<PH) NHA++;
if(PHB[1]>PH&&PHB[0]<PH) NHB++;
PHA[0]=PHA[1];
PHB[0]=PHB[1];
}
3、数据处理
void Data_Proc(void)
{
PH_beyond();
static uint32_t Data_Tick,Data_tick; //
//Get_NHA();
if((uwTick - Data_Tick) > 100)//10次一秒0.1秒1次
{
Data_Tick = uwTick;
TIM2_GetCapture(usCapt_TIM2);
Fre_A=1000000/usCapt_TIM2[0]+PX;
Per_A=1000000/Fre_A;
frqA_array[array_ptr] = Fre_A;
TIM3_GetCapture(usCapt_TIM3);
Fre_B=1000000/usCapt_TIM3[0]+PX;
Per_B=1000000/Fre_B;
frqB_array[array_ptr] = Fre_B;
array_ptr++;
}
}
三、评价结果
最终我们通过4ti官网测评,可以测评出为满分
如果有朋友想需要全部工程代码,可以私信我哦~