众所周知,虽然STM32F1系列属于中低端的32位ARM控制器,但其功能也是极为强大。在继承了STM32F0的基础上,将核心频率、FLASH、RAM、ADC的性能与容量做出了极大的改进,并且增加了DAC模块和IIS、USB、CAN,SDIO总线通信功能,是目前最为常用的32位位控制器入门学习器件,其中I/O接口的扩展使用更是几乎所有工程中都需要用到的功能。使用外设按键开关通过32对一些对象进行控制更是工程中最为常用的几种I/O扩展之一。
首先,我们先以单个触点式开关按键为例,第一步了解按键的特性:
微机键盘通常使用机械触点式按键开关,其主要功能式把机械上的通断转换为电气上的逻辑关系。也就是说,它能提供标准的TTL逻辑电平,以便于通用数字系统的逻辑电平相容。机械式按键再按下或释放时,由于机械弹性作用的影响,通常伴随有一定的时间触点机械抖动,然后其触点才稳定下来。其抖动过程如下图1所示,抖动时间的长短与开关的机械特性有关,一般为5-10ms。在触点抖动期间检测按键的通与断,可能导致判断出错,即按键一次按下或释放错误的被认为是多次操作,这种情况是不允许出现的。为了克服你、按键触点机械抖动所致的检测误判,必须采取消抖措施。按键较少时,可采用硬件消抖;按键较多式,采用软件消抖。当按键未按下时12、34之间属于开通状态,按键按下时,12、34之间导通,13、24引脚长通。那么如何使按键可以给控制器发出信号从而达到控制的效果呢?
如图当开关断开时由于上拉电阻的作用,此时该脚电压为3.3v也就是信号1,当开关闭合时,该脚电压为0V,也就是信号0,由此法达到信号的输
入
接下来是信号在STM32的内部进行运算的过程,该步骤我们需要借助STM32Cube以及keil5来编程实现。
1.我们先使用STM32Cube对32进行我们期望的配置,这里我设定A7为开关信号的输入以及B12为所控制的灯所接的引脚。
2.用STM32Cube打开keil5,因为在该工程中,我只改写了main.c的代码,所以不在此张贴其他相关文件的代码。
以下是main.c的代码
#include "main.h"
#include "stm32f1xx_hal.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
int main(void)
{
uint8_t KeyStates;//定义一个无符号整形变量:KeyStates,'_t'即为typedef的缩写(个人理解)
uint8_t LEDStates;//同上
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
KeyStates=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7);//将从A7引脚读取的值赋给KeyStates
if (KeyStates == GPIO_PIN_RESET)//检测到按键按下
{
HAL_Delay(30);
KeyStates = (HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7));//延时消抖
if (KeyStates == GPIO_PIN_RESET)
{
if(LEDStates == GPIO_PIN_RESET)
LEDStates = 1;
else
LEDStates = 0;//将LED的状态反转
while (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7) );//打个监测到按键复位时跳出循环,可以防止按键按下时间过长造成的不稳定
}
if(LEDStates == 0)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);//设定B12脚为输出信号脚,当LEDStates为0时B12输出低电平
}
else if(LEDStates == 1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);//当LEDStates为1时B12输出高电平
}
}
}
}
//以下为Cube所配置的程序
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET);
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void _Error_Handler(char *file, int line)
{
while(1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
}
运行结果:使得当按键按下时LED灯亮,再按下时,LED灯灭。
应用:可将LED替换为继电器,从而使用按键驱动大功率器件的启动与关闭。
完