赞
踩
从图中看出单片机的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 版权所有,并保留所有权利。