目录
系列文章目录
第十一届省赛
第十三届省赛第一场
第十三届省赛第二场
第十五届4T模拟赛 加部分更新
前言
本次记录的是蓝桥杯嵌入式第十四届省赛的程序设计题目。说实话,这次的题目,我费解了许久,因为在练习真题之前没有学习过脉冲捕获这个模块,所以这里是完完全全的小白,虽然很多人说很简单。接下来就一起进入我的打怪旅程吧
一、题目
二、模块实现
1.LED+LCD
/***************************************LED显示部分*******************************************/
//控制所有LED灯的亮灭
void Control_All_Led()
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}
//控制单个LED灯的亮灭
void Control_Single_Led(unsigned char location,unsigned char state)
{
HAL_GPIO_WritePin(GPIOC, (location<<8), state);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}
//为了避免LED和LCD显示冲突进行的处理
void Invoid_Complict()
{
HAL_GPIO_WritePin(GPIOC,0xff00,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}
void Display_Led()
{
Invoid_Complict();
//LED1
if(menu%3==0)
Control_Single_Led(0x01,0);
else
Control_Single_Led(0x01,1);
//LED2
if(freq==4000 || freq==8000)
{
Control_Single_Led(0x02,1);
//打开定时器
}
else
{
led2_sta^=1;
Control_Single_Led(0x02,led2_sta);
}
//LED3
if(status)
Control_Single_Led(0x04,1);
else
Control_Single_Led(0x04,0);
}
/***************************************LCD显示部分*******************************************/
void Display_Menu()
{
char str[30];
//数据界面显示
if(menu%3==0)
{
sprintf(str," DATA ");
LCD_DisplayStringLine(Line1,(u8*)str);
if(mode==0)
{
sprintf(str," M=L ");
LCD_DisplayStringLine(Line3,(u8*)str);
speed_l=(freq_l*2*3.14*r)/(100*k);
sprintf(str," V=%.1f ",speed_l);
LCD_DisplayStringLine(Line5,(u8*)str);
}
else
{
sprintf(str," M=H ");
LCD_DisplayStringLine(Line3,(u8*)str);
speed_h=(freq_h*2*3.14*r)/(100*k);
sprintf(str," V=%.1f ",speed_h);
LCD_DisplayStringLine(Line5,(u8*)str);
}
sprintf(str," P=%.1f%% ",duty);
LCD_DisplayStringLine(Line4,(u8*)str);
sprintf(str,"freq=%d ",freq);
LCD_DisplayStringLine(Line8,(u8*)str);
}
//参数界面显示
else if(menu%3==1)
{
sprintf(str," PARA ");
LCD_DisplayStringLine(Line1,(u8*)str);
sprintf(str," R=%d ",r);
LCD_DisplayStringLine(Line3,(u8*)str);
sprintf(str," K=%d ",k);
LCD_DisplayStringLine(Line4,(u8*)str);
sprintf(str," ");
LCD_DisplayStringLine(Line5,(u8*)str);
}
//统计界面显示
else
{
sprintf(str," RECD ");
LCD_DisplayStringLine(Line1,(u8*)str);
sprintf(str," N=%d ",n);
LCD_DisplayStringLine(Line3,(u8*)str);
sprintf(str," MH=%.1f ",speed_high_max);
LCD_DisplayStringLine(Line4,(u8*)str);
sprintf(str," ML=%.1f ",speed_low_max);
LCD_DisplayStringLine(Line5,(u8*)str);
}
}
2.定时器+key
定时器回调函数实现:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
//与按键一起使用
if(htim->Instance==TIM3)
{
keys[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
keys[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
keys[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
keys[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch(keys[i].key_pro)
{
case 0:
{
if(keys[i].key_sta==0)
{
keys[i].key_pro=1;
keys[i].key_tim=0;
}
break;
case 1:
{
if(keys[i].key_sta==0)
{
keys[i].key_pro=2;
keys[i].key_tim++;
}
else
keys[i].key_pro=0;
}
break;
case 2:
{
if(keys[i].key_sta==1)
{
keys[i].key_pro=0;
if(keys[i].key_tim<=70)
keys[i].key_sflg=1;
}
else
{
keys[i].key_tim++;
if(keys[i].key_tim>70)
keys[i].key_lflg=1;
}
}
break;
}
}
}
}
if(htim->Instance==TIM4)
{
if(is_change_mode==0)
{
count_tim++;
Change_Freq();
Display_Led();
if(count_tim==50)
is_change_mode=1;
}
}
}
按键功能实现:
/*************************按键控制****************************/
void Key_Function()
{
//切换显示界面
if(keys[0].key_sflg==1)
{
menu++;
keys[0].key_sflg=0;
change_flag=1;
Display_Led();
}
//"选择"按键
if(keys[1].key_sflg==1)
{
//数据界面下
if(menu%3==0)
{
if(is_change_mode)
{
mode=mode^1;
n++;
Display_Led();
is_change_mode=0; //不允许切换模式
HAL_TIM_Base_Start_IT(&htim4);
count_tim=0;
led2_sta=0;
Control_Single_Led(0x02,led2_sta);
}
}
//参数界面下
if(menu%3==1)
{
if(change_flag==1)
{
change_para=0;
change_flag=0;
}
else
change_para=change_para^1;
}
keys[1].key_sflg=0;
}
//加 按键
if(keys[2].key_sflg==1)
{
if(change_para==0)
{
if(r==10)
r=1;
else
r++;
}
else
{
if(k==10)
k=1;
else
k++;
}
keys[2].key_sflg=0;
}
if(keys[3].key_sflg==1)
{
if(menu%3==1)
{
if(change_para==0)
{
if(r==1)
r=10;
else
r--;
}
else
{
if(k==1)
k=10;
else
k--;
}
}
keys[3].key_sflg=0;
}
if(keys[3].key_lflg==1)
{
if(menu%3==0)
{
status=status^1;
Display_Led();
}
keys[3].key_lflg=0;
keys[3].key_tim=0;
}
}
/********************************END******************************************/
3.ADC+pwm+脉冲捕获
/*************************ADC*********************************/
float Get_ADC()
{
HAL_ADC_Start(&hadc2);
int value;
value=HAL_ADC_GetValue(&hadc2);
HAL_ADC_Stop(&hadc2);
return value*3.3/4096;
}
//电位器调节pwm输出信号占空比
void Pwm_Duty_Change()
{
if(status) //可以解锁
{
float volt=Get_ADC();
if(volt<=1.0)
{
duty=10;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,100);
}
else if(volt>=3.0)
{
duty=85;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,850);
}
else
{
duty=(0.375*volt-0.275)*100;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,(0.375*volt-0.275)*1000);
}
}
}
/********************************END******************************************/
//PA1输出信号的频率切换期间频率的均匀变化
void Change_Freq()
{
if(mode==0) //从高频到低频
{
if(freq!=4000)
{
freq=freq-100; //每次降低100HZ
__HAL_TIM_SetAutoreload(&htim2,4000000/(freq)-1);//设置自动重载数值
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,4000000/(freq)*(duty/100)); //保持占空比不变
}
}
else //从低频到高频
{
if(freq!=8000)
{
freq=freq+100; //每次增加100HZ
__HAL_TIM_SetAutoreload(&htim2,4000000/(freq)-1);//设置自动重载数值
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,4000000/(freq)*(duty/100)); //保持占空比不变
}
}
}
//PA7频率测量
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
uint16_t value=0;
if(htim->Instance==TIM17)
{
value=__HAL_TIM_GET_COUNTER(&htim17);
__HAL_TIM_SetCounter(&htim17,0);
if(mode)
freq_h=1000000/value;
else
freq_l=1000000/value;
HAL_TIM_IC_Start_IT(&htim17,TIM_CHANNEL_1);
}
}
void Get_Speed_Max()
{
speed_h=(freq_h*2*3.14*r)/100/k;
speed_l=(freq_l*2*3.14*r)/100/k;
if(speed_h>speed_high_max)
speed_high_max=speed_h;
if(speed_l>speed_low_max)
speed_low_max=speed_l;
}
总结
以上就是这次打怪过程中的一些主要函数,LED的基本亮灭函数可以去前面几篇文章里面查看,因为都是一样的,所以这里就偷下懒没加喽
这次的程序设计题目感觉比之前的要多一些细节,所以在完成的过程中可能情绪有点波动