野火霸天虎 STM32F407 学习笔记_5 按键输入;位带操作介绍

输入——按键点灯

开发板按键电路如下:

image-20231109191525189

按键未按下接地,按下后为高电平。电容起到消抖作用,软件处理就不需要手动延时消抖了。

编程没啥难度,就是改了一下输入模式。使用 ReadInputDataBits 读取。

//bsp_button.c
#include "bsp_button.h"

void Button_GPIO_Config(void){
    
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    {
    
    
        GPIO_InitTypeDef GPIOInitStruct;
        GPIOInitStruct.GPIO_Mode=GPIO_Mode_IN;
        GPIOInitStruct.GPIO_Pin=GPIO_Pin_0;
        GPIOInitStruct.GPIO_OType=GPIO_OType_PP;
        GPIOInitStruct.GPIO_Speed=GPIO_Speed_50MHz;
        GPIOInitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;
        
        GPIO_Init(GPIOA,&GPIOInitStruct);
    }
}

//main.c
#include "stm32f4xx.h"

#include "bsp_led.h"
#include "bsp_button.h"

int main()
{
    
    
    //RCC
    LED_GPIO_Config();
    Button_GPIO_Config();
    while (1)
    {
    
    
        if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))GPIO_SetBits(GPIOF, GPIO_Pin_6);
        else GPIO_ResetBits(GPIOF, GPIO_Pin_6);
    }
}

实现按键按下后翻转:

int main()
{
    
    
    //RCC
    LED_GPIO_Config();
    Button_GPIO_Config();
    while (1)
    {
    
    
        if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==Bit_SET){
    
    
            while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==Bit_SET);
            GPIO_ToggleBits(GPIOF, GPIO_Pin_6);
        }
    }
}

要等到按键松开的时候再翻转,轮询直到松开。

位带操作

之前51单片机常见位定义。比如 PA 引脚有8个 IO 口,我们可以定义 sbit LED1=PA^0 这样单独操作某一位。

stm32 里没有直接的位定义方式。一种解决办法是我们利用与或操作不影响其他位的同时操作特定位;另一种就是位带操作。

stm32 里有一部分别名区域,用于映射外设、SRAM 中特定的位带区,我们操作这一部分别名区域时就可以实现对外设、SRAM 位带区与的位操作。

片上外设位带区:0X4000 0000~0X400F 0000,别名区:0X4200 0000~0X43FF FFFF,包含 APB12,AHB1 外设。

SRAM 位带区:0X2000 0000~0X200F 0000,别名区:0X2200 0000~0X23FF FFFF

扫描二维码关注公众号,回复: 17161866 查看本文章

image-20231109220918350

外设地址 A 别名地址为:AliasAddr= =0x42000000+ (A-0x40000000)84 +n*4 (n是位序号)

SRAM 地址 A 别名地址为:AliasAddr= =0x22000000+ (A-0x20000000)84 +n*4

扩大了32倍,可以对32位寄存器中的每一位进行操作。

统一公式:\#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x000FFFFF)<<5)+(bitnum<<2))

使用:比如我们操作一个 GPIO 的位操作。

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x000FFFFF)<<5)+(bitnum<<2))
// 把一个地址转换成一个指针
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
// 把位带别名区地址转换成指针
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))

// GPIO ODR 和 IDR 寄存器地址映射
#define GPIOF_ODR_Addr (GPIOF_BASE+20)
#define GPIOF_IDR_Addr (GPIOF_BASE+16)

// 单独操作 GPIO 的某一个 IO 口,n(0,1,2...15),
// n 表示具体是哪一个 IO 口
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入

//使用示例
PFout(6)= 0;

这个概念学学就好,好像实际应用没啥意义。我们微处理器考试也考过hh。

猜你喜欢

转载自blog.csdn.net/jtwqwq/article/details/134322171