STM32 GPIO之二——按键例程 学习总结

来源:互联网 发布:美工需要练打字吗 编辑:程序博客网 时间:2024/05/29 03:16

一. GPIO的8种工作模式

1.4种输入模式:

(1)上拉输入模式(GPIO_Mode_IPU):在默认状态下(GPIO引脚无输入),读取得的GPIO引脚数据为1,高电平。

(2)下拉输入模式(GPIO_Mode_IPD):在默认状态下(GPIO引脚无输入),读取得的GPIO引脚数据为0,低电平。

(3)浮空输入模式(GPIO_Mode_IN_FLOATING):一般把这种模式用于标准的通信协议如I²C、USART的接收端。

(4)模拟输入模式(GPIO_Mode_AIN):使用ADC外设时,必须设置为模拟输入模式。

2.4种输出模式:

(1)推挽输出模式(GPIO_Mode_OUT_PP):一般应用在输出电平为0到3.3伏的场合。

(2)开漏输出模式(GPIO_Mode_OUT_OD):一般应用在电平不匹配的场合。

(3)复用推挽输出模式:如GPIO的引脚用作串口的输出。

(4)复用开漏输出模式:如在IC、SMBUS这些需要线与功能的复用场合。

二、开发板原理图如下:


三、测试代码:

实现功能:LED1亮,按下按键时LED1灭,再按下按键时LED1亮,如此循环。



/*led.c*/#include "led.h"/*配置LED用到的I/O口*/void LED_GPIO_Config(void){/*定义一个GPIO_InitTypeDef类型的结构体*/   GPIO_InitTypeDef GPIO_InitStructure;/*开启GPIOC的外设时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);/*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_5;/*设置引脚模式为通用推挽输出*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;/*设置引脚速率为50MHz*/ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/*调用库函数,初始化GPIOB、GPIOD*/ GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_Init(GPIOD,&GPIO_InitStructure);/*关闭所有LED灯*/ GPIO_SetBits(GPIOB,GPIO_Pin_5);//3、6、5引脚输出高电平,关闭三盏LED灯 GPIO_SetBits(GPIOD,GPIO_Pin_3|GPIO_Pin_6);                                                       }

/*led.h*/#ifndef __LED_H#define __LED_H#include "stm32f10x.h"#define ON  0#define OFF 1#define LED1(a) if(a) \                 GPIO_SetBits(GPIOD,GPIO_Pin_3);\ else   \ GPIO_ResetBits(GPIOD,GPIO_Pin_3) #define LED2(a) if(a) \                 GPIO_SetBits(GPIOD,GPIO_Pin_6);\ else   \ GPIO_ResetBits(GPIOD,GPIO_Pin_6) #define LED3(a) if(a) \                 GPIO_SetBits(GPIOB,GPIO_Pin_5);\ else   \ GPIO_ResetBits(GPIOB,GPIO_Pin_5)void LED_GPIO_Config(void);#endif /*__LED_H*/ 

/*key.c*/#include "key.h"void Delay(u16 time){       u16 i=0;     while(time--)   {      i=10;  //自己定义      while(i--) ;       }}/**函数名:Key_GPIO_Config*描述  :配置按键用到的I/O口*输入  :无*输出  :无*/void Key_GPIO_Config(void){    GPIO_InitTypeDef GPIO_InitStructure;  /*开启按键端口(PE5)的时钟*/  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_MHZ;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  GPIO_Init(GPIOC,&GPIO_InitStructure);}/**函数名:Key_Scan(GPIO_TypeDef* GPIOx,u16 GPIO_Pin)*描述  :检测是否有按键按下*输入  :GPIOx:x 可以是A,B,C,D或者E*        GPIO_Pin:待读取的端口位*输出  :KEY_OFF(没按下按键)、KEY_ON(按下按键)*/u8 Key_Scan(GPIO_TypeDef* GPIOx,u16 GPIO_Pin){  /*检测是否有键按下*/if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON ){     /*延时消抖*/ Delay(10000);    if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON ){             /*等待按键释放*/while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON);          return KEY_ON;        }else      return KEY_OFF;  } else      return KEY_OFF;}
/*key.h*/#ifndef __KEY_H#define __KEY_H#include "stm32f10x.h"#define KEY_ON  0#define KEY_OFF 1void Key_GPIO_Config(void);u8 Key_Scan(GPIO_TypeDef* GPIOx,u16 GPIO_Pin);void Delay(u16 time);#endif /*__LED_H*/

/*main.c*/#include "stm32f10x.h"#include "led.h"#include "key.h" int main (void){ LED_GPIO_Config(); LED1( ON ); Key_GPIO_Config();   while(1){      if( Key_Scan(GPIOC,GPIO_Pin_5) == KEY_ON ){/*LED反转*/        GPIO_WriteBit(GPIOB, GPIO_Pin_5,(BitAction)((1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5))));      }  }} 


四、范例

/*stm32v5_led.c*/#include "stm32v5_led.h"static led_gpio_t   leds_gpio[MAX_LED] ={{LED1, GPIOB, GPIO_Pin_5}, /* LED1 用的GPB5 */{LED2, GPIOD, GPIO_Pin_6}, /* LED2 用的GPD6 */{LED3, GPIOD, GPIO_Pin_3}, /* LED3 用的GPD3 */};void init_led_gpio(void){int                i;GPIO_InitTypeDef   GPIO_InitStructure;/* 使能PB和PD组 GPIO的时钟 */  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD , ENABLE);/*设置 PB5(LED1), PD6(LED2), PD3(LED3)为 GPIO 输出推免模式,口线翻转速度为50MHz */for(i=0; i<MAX_LED; i++){/*设置 PB5(LED1)为 GPIO 输出推免模式,口线翻转速度为50MHz */GPIO_InitStructure.GPIO_Pin = leds_gpio[i].pin;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(leds_gpio[i].group, &GPIO_InitStructure);  }}void turn_led(int which, int cmd){   if(which<0 || which> MAX_LED ) return;  if(OFF == cmd) GPIO_ResetBits(leds_gpio[which].group, leds_gpio[which].pin); else GPIO_SetBits(leds_gpio[which].group, leds_gpio[which].pin);}

/*stm32v5_led.h*/#ifndef __STM32V5_LED_H#define __STM32V5_LED_H#include"stm32f10x.h"#define ON           1#define OFF          0enum {  LED1 = 0,LED2,LED3,MAX_LED,};typedef struct led_gpio_s{int                 num;    /* LED编号 */GPIO_TypeDef        *group; /* LED使用的GPIO在哪一组: GPIOB or GPIOD */  uint16_t            pin;    /* LED使用的GPIO组中的那一个pin: GPIO_Pin_x */} led_gpio_t;extern void init_led_gpio(void);extern void turn_led(int which, int cmd);#endif

/*stm32v5_key.c*/#include "stm32f10x.h"#include "stm32f10x_exti.h"#include "stm32f10x_rcc.h"#include "misc.h"#include "stm32v5_led.h"#include "stm32v5_key.h"#define DEFINE_PIN_EXTI(group, pin, IRQn, SubPriority) \void init_P##group##pin##_as_EXTI(void) \{ \GPIO_InitTypeDef GPIO_InitStructure; \EXTI_InitTypeDef EXTI_InitStructure; \NVIC_InitTypeDef NVIC_InitStructure; \\RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO##group|RCC_APB2Periph_AFIO, ENABLE); \\  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_##pin;\  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; \  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; \  GPIO_Init(GPIO##group, &GPIO_InitStructure); \\GPIO_EXTILineConfig(GPIO_PortSourceGPIO##group, GPIO_PinSource##pin); \  EXTI_InitStructure.EXTI_Line = EXTI_Line##pin; \  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; \  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; \  EXTI_InitStructure.EXTI_LineCmd = ENABLE; \  EXTI_Init(&EXTI_InitStructure);\\NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); \  NVIC_InitStructure.NVIC_IRQChannel = IRQn;\  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; \  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; \  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;\  NVIC_Init(&NVIC_InitStructure); \} /* Key1(PC5) configured as EXTI5, SubPriority as 1 */DEFINE_PIN_EXTI(C, 5, EXTI9_5_IRQn, 1)/* Key2(PC2) configured as EXTI2, SubPriority as 2 */DEFINE_PIN_EXTI(C, 2, EXTI2_IRQn, 2)/* Key3(PC3) configured as EXTI3, SubPriority as 3 */DEFINE_PIN_EXTI(C, 3, EXTI3_IRQn, 3)/* PC5 Key1 interrupt handler */void EXTI9_5_IRQHandler(void){static uint8_t        led1_status = OFF;if(EXTI_GetITStatus(EXTI_Line5) != RESET){led1_status ^= 1;turn_led(LED1, led1_status);//EXTI_ClearITPendingBit(EXTI_Line5);  }}/* PC2 Key2 interrupt handler */void EXTI2_IRQHandler(void){static uint8_t        led2_status = OFF;if(EXTI_GetITStatus(EXTI_Line2) != RESET){led2_status ^= 1;turn_led(LED2, led2_status);EXTI_ClearITPendingBit(EXTI_Line2);  }}/* PC3 Key3 interrupt handler */void EXTI3_IRQHandler(void){static uint8_t        led3_status = OFF;if(EXTI_GetITStatus(EXTI_Line3) != RESET){led3_status ^= 1;turn_led(LED3, led3_status);EXTI_ClearITPendingBit(EXTI_Line3);  }}void init_keys_interrupt(void){init_PC5_as_EXTI();init_PC2_as_EXTI();init_PC3_as_EXTI();}

/*stm32v5_key.h*/#ifndef __STM32V5_KEY_H#define __STM32V5_KEY_Hextern void init_keys_interrupt(void);#endif

/*main.c*/#include "stm32f10x.h"#include "stm32v5_led.h"#include "stm32v5_key.h"int main(void){init_led_gpio();init_keys_interrupt();  while(1)  {;  }}


原创粉丝点击