这一部分呢,主要是关于按键控制的GPIO操作。也就是主要集中于GPIO的读取功能,废话不多说,直接上图。
从原理图上可以清楚看到3个按键连接的分别是GPIOA0,GPIOE3和GPIOE4。因为KEY0和KEY1连接是一样的,所以只讲PE3和PA0
简单的逻辑推理可以知道,当KEY_UP按下时。PA0被下拉到地,输入为0。所以在KEY_UP还没有被按下的时候应该是高电平,这样才会在按下按键时电平产生变化。所以PA0因为设置为下拉输入,PE3与PA0完全相反,不在重复叙述,PE3设置为上拉输入。
#include "stm32f10x.h"
#include "Delay.h"
void Key_Init(void)
{
//开启GPIOA和GPIOE的时钟
RCC->APB2ENR |= (1<<2);
RCC->APB2ENR |= (1<<6);
//将PA0设置为下拉输入
GPIOA->CRL &= 0xFFFFFFF8;
GPIOA->CRL |= 0x0000008;
GPIOA->BSRR |= (1<<16);
//将PE3设置为上拉输入
GPIOE->CRL &= 0xFFFF0FFF;
GPIOE->CRL |= 0x00008000;
GPIOE->BSRR |= (1<<3);
}
uint8_t Key_num(void)
{
uint8_t num = 0;
if((GPIOE->IDR &= 0x0008) == 0)
{
Delay_ms(10);
while((GPIOE->IDR &= 0x0008) == 0);
Delay_ms(10);
num = 1;
}
if((GPIOA->IDR &= 0x0001) != 0)
{
Delay_ms(10);
while((GPIOE->IDR &= 0x0001) != 0);
Delay_ms(10);
num = 2;
}
在过去的一章里已经介绍了时钟的开启。看到CRL寄存器的设置,可以看到分别在GPIOA_CRL的第0位和GPIOE_CRL的第3位设置为1000。
MODE的00意味选择输入模式,CNF的10选择上拉/下拉模式。诶?可能就要问了,为什么上拉和下拉设置在一起啦,如果不加上其他操作的话,单片机怎么知道我想设置为上拉还是下拉呢?没错,我们需要加上后续操作来将分辨处两者的差别。注意到后面对BSRR寄存器的操作,BSRR寄存器是对IO口输出的设置,在这里我们区分上拉还是下拉的区别就是两者电平。也就是说,将PA0的电平设置为0就是将PA0下拉,将PE3的电平设置为1就是将PE3上拉。这样就将GPIO口初始化完毕了。
再看之后的Key_num函数,这里主要实现了对IDR寄存器的读取,和结果的输出。这里还用到了软件消抖,因为该系列只简单扼要地介绍寄存器的操作方法,所以只会主要介绍if中的判断条件,对消抖需要了解的朋友网上的资料非常丰富,可以自行搜索。
回归正题,在GPIO篇1中介绍过IDR寄存器是专门用来读取IO口电平的。怎么读取呢,很简单,我们想要读取哪位就将哪位与上1,因为任何位(1和0)& 1都不会改变,而&0都会变成0,所以用来获取需要的位。(上篇中直接使用了进制计算,也没有做详细说明。对寄存器的操作是无法离开位操作的,这是基本操作,可以花时间好好了解一下,在之后的篇章中也不会在提及位操作,默认大家是了解的,不太清楚的用笔写一写也能很快明白。)
PE3是上拉,高电平。如果在判断中检测到IDR3为0,等价于PE3电平发生了变化,等于检测到到按钮被按下。同理也可以理解PA0的判断是如何构成的了。
OK!到这里可以说GPIO的简单的输出与输入都已经介绍完毕了,再之后的文章中就不会给大家展示初始化代码,而是直接带过。大家也可以接触一些简单的模块来熟悉GPIO的操作,比如基础的蜂鸣器(要分清楚有源和无源的区别)等。
之后更新中断,这位就是重量级了!!