输入——按键点灯
开发板按键电路如下:
按键未按下接地,按下后为高电平。电容起到消抖作用,软件处理就不需要手动延时消抖了。
编程没啥难度,就是改了一下输入模式。使用 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
外设地址 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。