一. 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 1 void 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 0 enum { 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_H extern 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) { ; } }