前言
报名参加了15届的蓝桥杯嵌入式,输入捕获乍一看不难可是,对于我来说,这次考试的两大功能频率突变和超限报警是很有难度的一部分,然后就是长按功能因为没有好好复习导致考试的时候没有第一时间做出来,丢了这个分数有点遗憾,主要是觉得长按不会考(狗头保命)
试题部分
cubemax配置部分
这次需要的基础功能比较简单,并没有很多的基础功能呢,而且并没有考串口
代码部分
lcd模块
根据最近几年的led还有4t官网的模拟题我发现,led部分越来越考单独控制,我认为学会led单独控制非常重要
#include "led.h"
uint8_t led_sta=0x00;
void LED_Disp(uint8_t dsLED)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,dsLED<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void LED_Chg(uint8_t num,uint8_t sta)
{
uint8_t pos=0x01;
pos=pos<<(num-1);
if(sta==1)
{
led_sta=(led_sta&(~pos))|pos;
}
else
{led_sta=(led_sta&(~pos));}
LED_Disp(led_sta);
}
按键部分
按键部分就比一般多了一个长按,我考试的时候没有写,很遗憾,可以去看看b站的视频很多长按的
#include "my_main.h"
struct Bkeys bkey[5]={0,0};
uint8_t key_read()
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0) return 1;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0) return 2;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0) return 3;
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0) return 4;
else return 0;
}
void key_serv()
{
uint8_t key_sta=key_read();
if(key_sta!=0)
{
bkey[key_sta].age++;
if(bkey[key_sta].age==2)
{bkey[key_sta].flag=1;}
}
else
{
for(int i=0;i<5;i++)
{bkey[i].age=0;}
}
}
主函数部分
我的习惯是新建一个my_main函数,主要是跟着b站指针老师学的哈,像这样的
#include "my_main.h"
uint view=0;
uint view_data=0;
extern struct Bkeys bkey[];
extern uint keylong;
float frq_R39;
float frq_R40;
float frq_R39_duty;
float frq_R40_duty;
float T_R39;
float T_R40;
uint PD=1000;
uint PH=5000;
int PX=0;
uint NHA=0;
uint NHB=0;
uint NDA=0;
uint NDB=0;
float NH_frqR40=0;
float NH_frqR39=0;
uint NH_duty40=0;
uint NH_duty39=0;
uint ND_duty40=0;
uint ND_duty39=0;
uint PARA_duty=0;
uint32_t time500ms;
uint ND_time;
float frq_40_back_max;
float frq_40_back_min;
float frq_39_back_max;
float frq_39_back_min;
void setup()
{
LCD_Init();
LCD_Clear(Black);
LCD_SetTextColor(White);
LCD_SetBackColor(Black);
HAL_TIM_Base_Start_IT(&htim6);
LED_Disp(0x00);
time500ms=uwTick;
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
// HAL_TIM_Base_Start_IT(&htim7);
}
void loop()
{
// char text[30];
// sprintf(text," DATA=%f",frq_40_back_min);
// LCD_DisplayStringLine(Line8,(uint8_t *)text);
view_proc();
key_proc();
T_R39=1/frq_R39_duty*1000000.0f;
T_R40=1/frq_R40_duty*1000000.0f;
frq_R39_duty=frq_R39+PX;
frq_R40_duty=frq_R40+PX;
NH_frqR40=frq_R40_duty;
NH_frqR39=frq_R39_duty;
NH_proc();
ND_proc();
if(view==0)
{
LED_Chg(1,1);
}
if(view==1)
{
LED_Chg(1,0);
}
if(frq_R40_duty>PH)
{LED_Chg(2,1);}
else
{LED_Chg(2,0);}
if(frq_R39_duty>PH)
{LED_Chg(3,1);}
else
{LED_Chg(3,0);}
if(NDA>3||NDB>3)
{LED_Chg(8,1);}
else
{LED_Chg(8,0);}
// if(view==2)
// {
// if(keylong==1)
// {
// NDA=0;
// NDB=0;
// NHA=0;
// NHB=0;
// keylong=0;
// }
}
void NH_proc()
{//超限
if(NH_frqR40>PH)
{NH_duty40=NH_duty40+1;
HAL_Delay(50);}
if(NH_duty40==1)
{
NHA=NHA+1;
NH_duty40=2;
}
if(frq_R40_duty<=PH)
{NH_duty40=0;}//Ԑbug
if(NH_frqR39>PH)
{NH_duty39=NH_duty39+1;
HAL_Delay(50);}
if(NH_duty39==1)
{
NHB=NHB+1;
NH_duty39=2;
}
if(frq_R39_duty<=PH)
{NH_duty39=0;}//Ԑbug
}
void ND_proc()
{//突变
if(uwTick-time500ms>500)//ɽīŚ
{
ND_time=ND_time+1;
time500ms=uwTick;
}
if(ND_time==1)
{
frq_40_back_min=frq_40_back_max=frq_R40_duty;
frq_39_back_min=frq_39_back_max=frq_R39_duty;
}
if(ND_time<6)
{
if(frq_R40_duty-frq_40_back_max>0)
{frq_40_back_max=frq_R40_duty;}
if(frq_R40_duty-frq_40_back_min<0)
{frq_40_back_min=frq_R40_duty;}
if(frq_40_back_max-frq_40_back_min>PD)
{ ND_duty40=ND_duty40+1;
HAL_Delay(50);
if(ND_duty40==1)
{
NDA=NDA+1;
ND_duty40=2;
}
}
if(frq_R39_duty-frq_39_back_max>0)
{frq_39_back_max=frq_R39_duty;}
if(frq_R39_duty-frq_39_back_min<0)
{frq_39_back_min=frq_R39_duty;}
if(frq_39_back_max-frq_39_back_min>PD)
{ND_duty39=ND_duty39+1;
HAL_Delay(5);
if(ND_duty39==1)
{
NDB=NDB+1;
ND_duty39=2;
}
}
}
if(ND_time>6)
{ND_time=0;
ND_duty40=0;
ND_duty39=0;}
}
void key_proc()
{
if(bkey[1].flag==1)
{
if(view==1)
{
if(PARA_duty==0)
{PD=PD+100;
if(PD>1000)
{PD=1000;}}
if(PARA_duty==1)
{PH=PH+100;
if(PH>10000)
{PH=10000;}}
if(PARA_duty==2)
{PX=PX+100;
if(PX>1000)
{PX=1000;}}
}
bkey[1].flag=0;
}
if(bkey[2].flag==1)
{
if(view==1)
{
if(PARA_duty==0)
{PD=PD-100;
if(PD<100)
{PD=100;}}
if(PARA_duty==1)
{PH=PH-100;
if(PH<1000)
{PH=1000;}}
if(PARA_duty==2)
{PX=PX-100;
if(PX<-1000)
{PX=-1000;}}
}
bkey[2].flag=0;
}
if(bkey[3].flag==1)
{
if(view==1)
{
PARA_duty=PARA_duty+1;
if(PARA_duty==3)
{PARA_duty=0;}
}
if(view==0)
{view_data=!view_data;}
//长按功能未完成
bkey[3].flag=0;
}
if(bkey[4].flag==1)
{
view=view+1;
if(view==1)
{PARA_duty=0;}
if(view==3)
{view=0;}
LCD_Clear(Black);
bkey[4].flag=0;
}
}
void view_proc()
{
char text[30];
if(view==0)
{
if(view_data==0)
{
sprintf(text," DATA ");
LCD_DisplayStringLine(Line1,(uint8_t *)text);
if(frq_R40_duty>1000.0f)
{
sprintf(text," A=%.2fKHz ",frq_R40_duty/1000.0f);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
}
if(frq_R40_duty<0.0f)
{
sprintf(text," A=NULL ");
LCD_DisplayStringLine(Line3,(uint8_t *)text);
}
if(frq_R40_duty<=1000.0f&&frq_R40_duty>=0.0f)
{
sprintf(text," A=%.0fHz ",frq_R40_duty);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
}
if(frq_R39_duty>1000.0f)
{
sprintf(text," B=%.2fKHz ",frq_R39_duty/1000.0f);
LCD_DisplayStringLine(Line4,(uint8_t *)text);
}
if(frq_R39_duty<0.0f)
{
sprintf(text," B=NULL ");
LCD_DisplayStringLine(Line4,(uint8_t *)text);
}
if(frq_R39_duty<=1000.0f&&frq_R39_duty>=0.0f)
{
sprintf(text," B=%.0fHz ",frq_R39_duty);
LCD_DisplayStringLine(Line4,(uint8_t *)text);
}
}
if(view_data==1)
{
sprintf(text," DATA ");
LCD_DisplayStringLine(Line1,(uint8_t *)text);
if(T_R40>1000.0f)
{
sprintf(text," A=%.2fmS ",T_R40/1000.0f);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
}
if(T_R40<0.0f)
{
sprintf(text," A=NULL ");
LCD_DisplayStringLine(Line3,(uint8_t *)text);
}
if(T_R40<=1000.0f&&T_R40>=0.0f)
{
sprintf(text," A=%.0fuS ",T_R40);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
}
if(T_R39>1000.0f)
{
sprintf(text," B=%.2fmS " ,T_R39/1000.0f);
LCD_DisplayStringLine(Line4,(uint8_t *)text);
}
if(T_R39<0.0f)
{
sprintf(text," B=NULL ");
LCD_DisplayStringLine(Line4,(uint8_t *)text);
}
if(T_R39<=1000.0f&&T_R39>=0.0f)
{
sprintf(text," B=%.0fuS ",T_R39);
LCD_DisplayStringLine(Line4,(uint8_t *)text);
}
}
}
//
if(view==1)
{
sprintf(text," PARA ");
LCD_DisplayStringLine(Line1,(uint8_t *)text);
sprintf(text," PD=%dHz ",PD);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
sprintf(text," PH=%dHz ",PH);
LCD_DisplayStringLine(Line4,(uint8_t *)text);
sprintf(text," PX=%dHz ",PX);
LCD_DisplayStringLine(Line5,(uint8_t *)text);
}
if(view==2)
{
sprintf(text," RECD ");
LCD_DisplayStringLine(Line1,(uint8_t *)text);
sprintf(text," NDA=%d ",NDA);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
sprintf(text," NDB=%d ",NDB);
LCD_DisplayStringLine(Line4,(uint8_t *)text);
sprintf(text," NHA=%d ",NHA);
LCD_DisplayStringLine(Line5,(uint8_t *)text);
sprintf(text," NHB=%d ",NHB);
LCD_DisplayStringLine(Line6,(uint8_t *)text);
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{//频率测量
uint16_t ccr_val2;
uint16_t ccr_val3;
if(htim->Instance==TIM2)
{
ccr_val2=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
__HAL_TIM_SetCounter(htim,0);
frq_R40=1000000.0f/ccr_val2;
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
}
if(htim->Instance==TIM3)
{
ccr_val3=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
__HAL_TIM_SetCounter(htim,0);
frq_R39=1000000.0f/ccr_val3;
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM6)
{key_serv();}
// if(htim->Instance==TIM7)
// {key_long_serv();}
}
界面切换与往年的进行比较也有一点改变,之前就是一个界面一个界面的只需要设一个标志位,这次在大界面里面套取小界面,需要两个标志位
我的主函数部分在频率突变的时候第一次数据不能大于初值,否则会加1,这算一个小bug,就是不知道是怎么进行评分的有没有扣除这个分数,在代码我进行过修改,不过并没有很大作用,其他功能大致实现了
总结
在这次测试中,长按没有写出来有点亏,其他地方我觉得还是比较满意的,感觉蓝桥杯的难度一年比一年高,这次代码都写了300多行了,之前做往年的题目才200多行。感觉之前主要是考模块现在往代码编程了,(都没使用串口,可能是模块都考差不多了吧,没什么考点了)