一 按键检测实验
-
使能 GPIO 端口时钟;
-
初始化 GPIO 目标引脚为输入模式(浮空输入);
-
编写简单测试程序,检测按键的状态,实现按键控制 LED 灯
#ifndef __KEY_H #define __KEY_H #include "stm32f10x.h" #define KEY0_GPIO_PIN GPIO_Pin_4 #define KEY0_GPIO_PORT GPIOE #define KEY0_GPIO_CLK RCC_APB2Periph_GPIOE #define key0_down 0 #define key0_up 1 uint8_t Key_Scan( GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin); void KEY0_GPIO_Config(void); void delay(uint32_t count); #endif
#include "key.h" void KEY0_GPIO_Config(void){ GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = KEY0_GPIO_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; RCC_APB2PeriphClockCmd(KEY0_GPIO_CLK, ENABLE ); GPIO_Init(KEY0_GPIO_PORT,&GPIO_InitStruct); } void delay(uint32_t count){ for(;count!=0;count--); } uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin){ if (GPIO_ReadInputDataBit(GPIOx, GPIO_Pin)==key0_down){ delay(0xfff);//等待低电平稳定 while (GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == key0_down);//等待按键释放 return key0_down; } else return key0_up; }
#include "stm32f10x.h" #include "led.h" #include "key.h" //按键检测:Key0按下一次 Led0的状态就反转一次 //存在问题:按键抖动导致cpu检测到短时间电平状态忽高忽低 //此时LED0来回反转,最终以低电平检测结束,一直等待按键释放 //这时候灯反转。 int main(void) { LED0_GPIO_Config(); KEY0_GPIO_Config(); while (1){ if (Key_Scan(KEY0_GPIO_PORT,KEY0_GPIO_PIN)== key0_down) LED0_TOGGLE; } }
二.GPIO—位带操作
位操作就是可以单独的对一个比特位读和写,这个在 51 单片机中非常常见。51 单片机中通过关键字 sbit 来实现位定义,STM32 没有这样的关键字,而是通过访问位带别名区来实现.
在 STM32 中,有两个地方实现了位带,一个是 SRAM 区的最低 1MB 空间,另外一个是外设区最低 1MB 空间。
外设外带区的地址为:0X40000000~0X40100000,大小为 1MB,这 1MB 的大小在 103系列大/中/小容量型号的单片机中包含了片上外设的全部寄存器,这些寄存器的地址为:0X40000000~0X40029FFF 。 外 设 位 带 区 经 过 膨 胀 后 的 位 带 别 名 区 地 址 为 :0X42000000~0X43FFFFFF
这里仅仅演示下 GPIO 中 ODR 和 IDR 这两个寄存器的位操作
#include "stm32f10x.h" #include "led.h" #include "key.h" //位带操作LED0闪烁;位带操作检测IO输入电平高低 #define GPIOB_ODR_ADDR (GPIOB_BASE+0x0c) #define PBout(n) *(unsigned int*)((GPIOB_ODR_ADDR&0xF0000000)+0x02000000+((GPIOB_ODR_ADDR&0x00FFFFFF)<<5)+(n<<2)) #define GPIOE_IDR_ADDR (GPIOE_BASE+0x08) #define PEin(n) *(unsigned int*)((GPIOE_IDR_ADDR&0xF0000000)+0x02000000+((GPIOE_IDR_ADDR&0x00FFFFFF)<<5)+(n<<2)) void delay(uint32_t count){ for(;count!=0;count--); } int main(void) { LED0_GPIO_Config(); KEY0_GPIO_Config(); #if 0 while (1){ //GPIO_SetBits(LED0_GPIO_PORT, LED0_GPIO_PIN5); //LED0(ON); PBout(5) = 1; delay(0xfffff); //GPIO_ResetBits(LED0_GPIO_PORT, LED0_GPIO_PIN5); //LED0(OFF); PBout(5) = 0; } #else while (1){ if (PEin(4)== key0_down){ while(PEin(4)== key0_down); LED0_TOGGLE; } } #endif }
启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作:
1、初始化堆栈指针 SP=_initial_sp
2、初始化 PC 指针=Reset_Handler
3、初始化中断向量表
4、配置系统时钟
5、调用 C 库函数_main 初始化用户堆栈,从而最终调用 main 函数去到 C 的世界