赞
踩
从图中看出单片机的PB12引脚接到了按键上。
根据按键的原理图,可以分析得到,如果不按下按键的时候,引脚输入的是高电平。按下按键的时候,引脚输入的是低电平。
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"); } } }
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); //初始化
}
key.h文件。
#ifndef __KEY_H
#define __KEY_H
void Key_Init(void);
#endif
因为寄存器操作可以直接在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"); } //---------------------------------------------------------// } }
可以看出信息已经打印出来了,但是呢,有时候会出现按下按键后没有打印的情况。因为我们的按键检测是放到主函数中的,再加上之前有小灯闪烁的延时存在,这就导致了检测不是很准的原因。因此,为了更准确的检测按键,可以引入中断。
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 } }
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); //中断优先级初始化 }
key.h
文件。
#ifndef __KEY_H
#define __KEY_H
void Key_Init(void);
#endif
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上的中断标志位 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。