当前位置:   article > 正文

小兴教你做平衡小车-stm32程序开发(按键扫描)_程序中按键扫描

程序中按键扫描

1 单片机最小系统板按键原理图介绍

从图中看出单片机的PB12引脚接到了按键上。
在这里插入图片描述
根据按键的原理图,可以分析得到,如果不按下按键的时候,引脚输入的是高电平。按下按键的时候,引脚输入的是低电平。
在这里插入图片描述

2 库函数程序设计

main.c文件。

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include "stdio.h"

int main(void)
{
	RCC->APB2ENR |= (uint32_t)0x00000010;//打开GPIOC时钟
	GPIOC->CRH   &= (uint32_t)0xFF0FFFFF;//使用前清零
	GPIOC->CRH   |= (uint32_t)0x00300000;//配置PC13为推挽输出,最大速度50MHz
	Delay_Init();
	Usart_Init(115200);
	Key_Init();
	printf("hello world!\r\n");
	while(1)
	{
		GPIOC->BSRR  =  (uint32_t)0x00002000;//PC13引脚输出高电平
		Delay_ms(100);                       //延时100ms
		GPIOC->BRR  =   (uint16_t)0x2000;    //PC13引脚输出低电平
		Delay_ms(100);   		             //延时100ms
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0)
		{
			Delay_ms(10);  
			if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0)
				printf("key is pressed!\r\n");
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

key.c文件。

#include "stm32f10x.h"
#include "key.h"	

void Key_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB时钟
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;       //上拉输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;          //PB12
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //频率为50mhz
	GPIO_Init(GPIOB,&GPIO_InitStructure);               //初始化
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

key.h文件。

#ifndef __KEY_H
#define __KEY_H

void Key_Init(void);

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3 寄存器程序设计

因为寄存器操作可以直接在main.c文件中写完,这里只提供给大家main.c文件哈。

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include "stdio.h"

int main(void)
{
	RCC->APB2ENR |= (uint32_t)0x00000010;//打开GPIOC时钟
	GPIOC->CRH   &= (uint32_t)0xFF0FFFFF;//使用前清零
	GPIOC->CRH   |= (uint32_t)0x00300000;//配置PC13为推挽输出,最大速度50MHz
	Delay_Init();
	Usart_Init(115200);
	
	//库函数版本
//	//---------------------------------------------------------//
//	Key_Init();
	//---------------------------------------------------------//
	
	//寄存器版本
	//---------------------------------------------------------//
	RCC->APB2ENR |= (uint32_t)0x00000008;//打开GPIOB时钟
	GPIOB->CRH   &= (uint32_t)0xFFF0FFFF;//使用前清零
	GPIOB->CRH   |= (uint32_t)0x00080000;//配置PB12为上/下拉输入
	GPIOB->BSRR   = (uint32_t)0x00001000;//配置PB12为上拉
	//---------------------------------------------------------//
	
	printf("hello world!\r\n");
	while(1)
	{
		GPIOC->BSRR  =  (uint32_t)0x00002000;//PC13引脚输出高电平
		Delay_ms(100);                       //延时100ms
		GPIOC->BRR  =   (uint16_t)0x2000;    //PC13引脚输出低电平
		Delay_ms(100);   		             //延时100ms
		//库函数版本
		//---------------------------------------------------------//
//		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0)
//		{
//			Delay_ms(10);  
//			if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0)
//				printf("key is pressed!\r\n");
//		}
		//---------------------------------------------------------//
		
		//寄存器版本
		//---------------------------------------------------------//
		if((GPIOB->IDR & (uint16_t)0x1000) == 0)
		{
			Delay_ms(10);
			if((GPIOB->IDR & (uint16_t)0x1000)== 0)
				printf("key is pressed!\r\n");
		}
		//---------------------------------------------------------//
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

4 效果展示

可以看出信息已经打印出来了,但是呢,有时候会出现按下按键后没有打印的情况。因为我们的按键检测是放到主函数中的,再加上之前有小灯闪烁的延时存在,这就导致了检测不是很准的原因。因此,为了更准确的检测按键,可以引入中断。
在这里插入图片描述

5 引脚外部中断

main.c文件。

//按键扫描超准确版本
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include "stdio.h"

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	RCC->APB2ENR |= (uint32_t)0x00000010;//打开GPIOC时钟
	GPIOC->CRH   &= (uint32_t)0xFF0FFFFF;//使用前清零
	GPIOC->CRH   |= (uint32_t)0x00300000;//配置PC13为推挽输出,最大速度50MHz
	Delay_Init();
	Usart_Init(115200);
	Key_Init();
	printf("hello world!\r\n");
	while(1)
	{
		GPIOC->BSRR  =  (uint32_t)0x00002000;//PC13引脚输出高电平
		Delay_ms(500);                       //延时500ms
		GPIOC->BRR  =   (uint16_t)0x2000;    //PC13引脚输出低电平
		Delay_ms(500);   		             //延时500ms
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

key.c文件。

//按键扫描准确版本
#include "stm32f10x.h"
#include "key.h"
#include "delay.h"
#include "usart.h"
#include "stdio.h"

void Key_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);//开启GPIOB时钟并开启复用时钟
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;       //上拉输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;          //PB12
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //频率为50mhz
	GPIO_Init(GPIOB,&GPIO_InitStructure);               //初始化
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource12);   //PB12中断线映射
	EXTI_InitStructure.EXTI_Line = EXTI_Line12; //中断线12
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;   //中断线使能开启
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//外部中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
	EXTI_Init(&EXTI_InitStructure);  //外部中断初始化
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;     //配置外部中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//设置抢占优先级为0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;       //设置子优先级为1
	NVIC_Init(&NVIC_InitStructure);   //中断优先级初始化
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

key.h文件。

#ifndef __KEY_H
#define __KEY_H

void Key_Init(void);

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

stm32f10x_it.c文件。

#include "stm32f10x.h"
#include "delay.h"
#include "stdio.h"

void EXTI15_10_IRQHandler(void)   //按键中断服务函数
{
	if(EXTI_GetITStatus(EXTI_Line12)!=RESET)   //判断是否触发进入中断
	{
		Delay_ms(10);   //按键消抖
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0)
		{
			while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0);//等待松开按键
			printf("key is pressed!\r\n");
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line12);   //清除EXTI_Line12上的中断标志位
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/638943
推荐阅读
相关标签
  

闽ICP备14008679号