蓝桥杯嵌入式

整体构建流程:先通过CubeMX创建一个只含有时钟的打底工程,在创建一个一个源工程(方便打底工程移植初始化代码)。

一、led模块

在源工程中的cubeMX构建led初始化,八个引脚,一个锁存器引脚,移植到打底工程中,并在打底工程中建立lLed_Disp(char ucLed)函数,此函数通过(ucLed<<8)得到对应的led引脚,通过8位ucLed分别控制。注意:控制顺序是先写led寄存器,在开锁存器,关锁存器

二、lcd模块

没啥注意的,copy历程就好了。

三、key模块

按键消抖需要用到定时器,在移植工程中需注意:需要用到定时器溢出中断功能,开启中断,移植it文件中的IRQhand函数,初始化后记得手动添加HAL_TIM_Base_Start_IT定时器开启函数,此函数中断也会开启,然后在HAL_TIM_PeriodElapsedCallback回调函数中写按键消抖逻辑。

运用状态机,按键功能分为短按键和长按键,状态分别为①检测按下,②消抖状态()③检测松开(定时器设置为10ms中断,如果大于一定时间段为长按,小于则为短按)注意:在长按后得到长按标志位后不能恢复状态为0(状态机的state),此处不用管,只要得到状态就行。(目前不知道为啥,测的这样可以用)

练习代码

#include "stdbool.h"
typedef struct{
    unsigned char Judge_State;
    bool Key_State;
    bool Key_Short_Flag;
    bool Key_Long_Flag;
    int Key_Time;
}KEY;

KEY key[4];
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIM3)    
    {
        key[0].Key_State=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
        key[1].Key_State=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
        key[2].Key_State=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
        key[3].Key_State=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3);
        
        for(int i=0;i<4;i++)
        {
            switch(key[i].Judge_State)
            {
                case 0:
                if(key[i].Key_State==0)//检测按下
                {
                    key[i].Judge_State=1;        
                }
                break;
                case 1:
                if(key[i].Key_State==0)//检测消抖,过了10ms后如果还是按下就消除抖动
                {
                    key[i].Judge_State=2;        
                }
                else//为抖动,返回初状态
                {
                    key[i].Judge_State=0;    
                }                
                break;
                case 2:
                if(key[i].Key_State==1)//检测松开
                {
                    key[i].Judge_State=0;
                    if(key[i].Key_Time<80)
                    {
                        key[i].Key_Short_Flag=1;//短按
                    }
                }
                else//还没松手
                {
                    key[i].Key_Time++;
                    if(key[i].Key_Time>=80)//800ms为一次长按
                    {
                        key[i].Key_Long_Flag=1;//长按
                        //在此处不能把key[i].Judge_State设置为0
                        //如果设置为0现在一直是按下的状态,松开直接会跑到case 2:的短按状态
                    }    
                }
                break;
            }    
        }
    }
}

想明白了:短按中的key[i].Judge_State=0;会随着按键的抖动重新回归初始态,长按时不要管。

四、输入捕获

此处捕获测频率使用的是测周法测频率,设置为上升沿或下降沿进中断都行(一个周期),在中断回调函数中,读取捕获到的值(HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1)),注意:读完记得清零cnt。最后,通过设定的最小周期乘以捕获的个数得到周期,再取倒数。

提示:测周法中用于测量指定周期的最小周期越小(频率越大),误差越小,但不能太小,太小捕获值会变大,指定测量的频率也不要太大(周期小)。

问:定时器生成指定频率时是由两个参数决定,一个是分频系数,一个是重装值。这个频率能和重装值有关系呢?其实这个也是测周法:重装值指定一个周期,以分频后的频率为基准,倒数为一个小周期,小周期乘以重装值为总时间,再取倒数就是频率。

测试时:得出发出频率的定时器要调整重装值,测量的定时器频率月大越好,过大,测的值会比平常多。仅提供调时的一个方向。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值