一、底层
根据它的硬件配置可以看出来这套题目使用到了按键、LED、LCD、输入捕获这几个功能
(1)输入捕获功能
首先在CubeMx里面的配置
题目中说到了我们使用的是PA15和PB4(实际在板子上对应的的是R39和R40),所以我们的CubeMx配置,首先我们要打开PA15和PB4的TIM,因此我们开的是TM2_CH1,TIM3_CH1。同时我们还开了内部时钟,选取了输入捕获的直接模式,把预分频系数设置为80-1,把ARR自动重装载值设置为65535(这个很重要)。最后别忘了开中断!!!输入捕获和按键的定时器是需要开中断的,如果是单纯的定时器设置是不需要开中断的。
不要忘了时钟树的配置是24和80
再就是我们的初始化
我们在main.c里面的初始化要开一下输入捕获的中断
cs
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
最后重要的是我们要记得写好底层
只要是开了定时器,那我们就需要写htim->Instance==TIM2
对于输入捕获,我们首先要在5933找到相应的函数
然后我们就要写htim->Instance==TIM2;
里面的框架就是,我们要先开启输入捕获中断的通道
然后我们要接收捕获到的值HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
同时我们要用一个int形的数据去接收它 TA=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
这个时候千万别忘记把计数值清零__HAL_TIM_SetCounter(htim,0);
最后别忘了计算一下频率值:FA=(80000000/80)/TA;
cs
int TA,FA,TB,FB;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(hitim->Instance=TIM2)
{
HAL_TIM_IC_Start_IT(htim,TIM_CHANNEL_1);
TA=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
__HAL_TIM_SetCounter(htim,0);
FA=(80000000/80)/TA;
}
if(htim->Instance==TIM3)
{
HAL_TIM_IC_Start_IT(htim,TIM_CHANNEL_1);
TB=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
__HAL_TIM_SetCounter(htim,0);
FB=(80000000/80-1)/TB;
}
}
(2)按键底层
首先需要在tim.c的5933找到这个函数名字,然后需要写一个找到定时器的函数if(htim->Instance==TIM4)//只要有定时器,就别忘了写选定时器这一步,输入捕获也是同样。然后开始读取GPIO的值,后面就是for循环,注意一定要写for(int i=0;i<4;i++)别写错了,然后再写switch case。里面的步骤就是,首先就是判断按键是否按下,然后就是跳转1,2这个跳转的数据千万不要写错了。在第0步的时候,除了要判断按键是否按下之外,还要把时间计时为0。第一步就是判断案件是否再次按下,如果再次按下就跳转到第2步。首先是判断按下是否松开,如果松开,就跳转到第0步,同时判断是否为短按键,如果是短按键,那么标志位置1,一定要记住这里是标志位置1,后面的按键逻辑就要这样写,不然把标志位的1和0写错的话,后面就实现不了相应的功能。如果没有松开,就一直计时,判断是否为长按键,如果是长按键那么标志位置1。
cs
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM4)
{
key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch (key[i].jungle_sta)
{
case 0:
{
if(key[i].key_sta==0)
{
key[i].jungle_sta=1;
key[i].key_time=0;
}
}
break;
case 1:
{
if(key[i].key_sta==0)
{
key[i].jungle_sta=2;
}
else
{
key[i].jungle_sta=0;
}
}
break;
case 2:
{
if(key[i].key_sta==1)
{
key[i].jungle_sta=0;
if(key[i].key_time<100)
{
key[i].short_flag=1;
}
}
else
{
key[i].key_time++;
if(key[i].key_time>100)
{
key[i].long_flag=1;
}
}
}
break;
}
}
}
}
二、逻辑部分

这里有一个要注意的点就是使用到了浮点型。首先我们的代码要写A=%.2f,后面就需要写A,那么这个A的值A=(float)FA/1000;前面加的(float)就是把FA/1000这个值转化为小数

还有一个很重要的逻辑功能就是,首先你要判断是在哪个界面,在哪个界面实现怎样的逻辑。比如题目中就有在第一个界面下按键B3实现周期和频率的切换。参数选择都是在按键里面写下的逻辑para++。if(para==0)PH=PH+100;这样子来写来实现选择参数并且增加数值
还有就是 看看长按键的时间是多少秒。千万不要把按键的标志位写错了,短按键按下的标志位是1,不按下是0。还可以在切换界面的下面直接写LCD_Clear();这样能够实现清屏的功能。
三、测评
15.2文件已经提交至4T,除了频率超限没有完成,其他都完成了,静候测评成绩。