建设行业门户网站需要什么条件,网站建设和,网站建设进度表 免费下载,东莞网络推广培训班在第一讲中曾经提到#xff0c;GPIO有输入输出两种模式。在点亮LED时#xff0c;我们已经使用了GPIO输出模式#xff0c;在按键识别中#xff0c;我们将要使用GPIO输入模式。首先来看看按键的电路原理图#xff08;下图在选手资源数据包——CT117E-M4产品手册中#xff0…在第一讲中曾经提到GPIO有输入输出两种模式。在点亮LED时我们已经使用了GPIO输出模式在按键识别中我们将要使用GPIO输入模式。首先来看看按键的电路原理图下图在选手资源数据包——CT117E-M4产品手册中 其中B1~B4为4个不同的按键它们通过PB0、PB1、PB2、PA0四个端口以上拉电阻的方式连接到单片机中。当按键松开时PB0等端口处于高电平状态当按键按下后端口处于低电平状态。因此我们可以把这些端口设置为GPIO输入上拉电阻pull-up模式通过读取其电平的高低状态来判断按键是否被按下。所谓上下拉电阻其实决定的就是GPIO输入端口断路时的初始电平状态有关介绍可以自行搜索
例如需要判断B1是否被按下时我们只需要判断PB0的电平状态
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) GPIO_PIN_RESET)//读取PB0的电平状态判断是否为低电平
{/* 执行任务 */
}
在主循环中利用按键扫描我们就可以通过不同的按键操作来执行不一样的任务例如
while (1)
{//B1按下点亮LD1和LD2if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) GPIO_PIN_RESET){LED_On(LD1|LD2);}//B2按下点亮LD3和LD4if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) GPIO_PIN_RESET){LED_On(LD3|LD4);}//B3按下点亮LD5和LD6if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) GPIO_PIN_RESET){LED_On(LD5|LD6);}//B4按下点亮LD7和LD8if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) GPIO_PIN_RESET){LED_On(LD7|LD8);}
}
不仅是按键GPIO输入模式与输出模式一样均广泛应用于各种需要读取外部电路电平的场景。有关GPIO输入的函数如下
/*** brief Read the specified input port pin.* param GPIOx where x can be (A..G) to select the GPIO peripheral for STM32G4xx family* param GPIO_Pin specifies the port bit to read.* This parameter can be any combination of GPIO_PIN_x where x can be (0..15).* retval The input port pin value.*/
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
然而这种方法在实际中并不常用。可以想象除了判断按键是否按下以外一个嵌入式系统一定还有其他的许多任务需要执行。倘若在主循环中一直判断按键是否被按下则会占用CPU效率低下同时也可能因为在执行其他任务响应不及时。因此我们更常用的是采用中断的方式来判断按键是否被按下。
先来普及一下什么是中断。我们知道CPU是按照顺序依次执行主函数中的指令的。中断是指打断CPU当前正在执行的指令跳到中断程序中执行随后跳会主函数原来的位置继续执行原指令。例如在生活中我们的主程序是写代码这时电话铃响我们不得不停下手中的工作进入中断——接电话接完电话后又继续回到写代码的工作中。正如打断我们的有可能是电话铃声有可能是门铃声也有可能是短信铃声等等打断CPU的中断方式也是多种多样的如GPIO外部中断、定时器中断、定时器捕获中断等等……
考虑到比赛中对按键的判断涉及到长短按我们在考虑程序执行效率而采用中断的同时要考虑判断长短按的方法这就涉及到按键按下的时间问题。在单片机中与时间有关的问题都是通过定时器来实现的。因此下面我们来介绍定时器中断。
先来介绍一下与定时器有关的概念。在单片机中有一个晶振石英晶体振荡器它通常决定了单片机的时钟频率。通过对时钟的分频可以得到许许多多的时钟源。不同的硬件通过采用不同的时钟源再对其进行分频就得到了独属于这个硬件自己的时钟频率定时器亦是如此。
参照官方例程LCD的例程我们按如下步骤配置时钟树
1开启外部高速时钟 2勾选HSE将时钟频率设置为80MHz后按回车 3所得到的定时器频率即可以在上图右侧圆圈处查看
这样我们就得到了时钟频率为80MHz的定时器。
下面我们来开启定时器中断。我们设置TIM4如下 其中定时器频率按照如下公式计算具体原理请自行搜索 f0为时钟频率80MHzPrescaler为预分频系数Counter Period为计数周期。这样我们就把TIM4定时器的频率设置为了100Hz即周期为0.01s。最后只需要打开中断开关就完成了定时器中断的配置。 在Cube中设置好后想要使用定时器中断还要在主函数初始化时开启定时器中断在此处是开启TIM4的定时器中断
HAL_TIM_Base_Start_IT(htim4); //开启TIM4的基本(Base)功能定时中断(IT(InTerrupt))
然后编写定时器中断函数注意函数名和形参均是固定的不能修改可参照下图寻找 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //定时(Period)中断(Elapsed)回调(Callback)函数回调即从主程序中调到中断程序中
{if (htim-Instance TIM4) //如果是TIM4定时器触发的中断{//B1按下点亮LD1和LD2if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) GPIO_PIN_RESET){LED_On(LD1|LD2);}//B2按下点亮LD3和LD4if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) GPIO_PIN_RESET){LED_On(LD3|LD4);}//B3按下点亮LD5和LD6if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) GPIO_PIN_RESET){LED_On(LD5|LD6);}//B4按下点亮LD7和LD8if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) GPIO_PIN_RESET){LED_On(LD7|LD8);}}
}
这样每当时间过去了0.01sCPU就会进入定时中断回调函数中运行我们预先写好的中断程序在此处是读取按键端口的电平随后执行相应任务即定时按键扫描而不是一直循环扫描按键是否按下这样就为CPU节省下了大量的时间大大提高了程序的运行效率。