赞
踩
STM32F407ZG有8个16引脚的GPIO端口。还有一个12引脚的PI端口。
GPIO端口都连接在AHB1总线上,自高时钟频率168MHz。
GPIO引脚能承受5V电压.
每个GPIO端口有4个32位寄存器,用于配置GPIO引脚的工作模式;1个32位输入数据寄存器和1个32位输出数据寄存器,还有复用功能选择寄存器等。
输入浮空(input floating):作为GPIO输入引脚,不使用上拉或下拉电阻。
输入上拉(input pull-up),作为GPIO输入引脚,使用内部上拉电阻。当没有外部输入时,引脚输入电平为高电平。
输入下拉(input pull-down):作为GPIO输入引脚,使用内部下拉电阻。当没有外部输入时,引脚输入电平为低电平。
模拟(analog):作为GPIO模拟引脚,用于ADC输入引脚或DAC输出引脚。
具有上拉或下拉的开漏输出(output open-drain):如果不使用上拉或下拉电阻,开漏输出1时引脚为高阻态,输出0时引脚是低电平。这种模式可用于共用总线的信号。
具有上拉或下拉的推挽输出(output push-pull):如果不使用上拉或下拉电阻,推挽输出1时引脚是高电平,输出0时引脚为低电平。若需要增强引脚输出驱动能力,就可以使用上拉。例如需要GPIO引脚输出高电平点亮LED时。
具有上拉或下拉的复用功能推挽(afternate function push-pull)。
具有上拉或下拉的复用功能开漏(afternate function open-drain)。
HAL_GPIO_Init() GPIO引脚初始化
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx,GPIO_InitTypeDef *GPIO_Init);
参数1 GPIO_TypeDef *GPIOx,定义了各个端口的各个寄存器的偏移地址,实际调用HAL_GPIO_Init()时使用端口的基地址作为参数GPIOx的值。在stm32f407xx.h中定义了各个端口的基地址。
- #define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
- #define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
- #define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
- #define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
- #define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
- #define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
- #define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
- #define GPIOH ((GPIO_TypeDef *) GPIOH_BASE)
- #define GPIOI ((GPIO_TypeDef *) GPIOI_BASE)
参数2GPIO_InitTypeDef *GPIO_Init,定义了GPIO引脚的属性。
- //定义GPIO属性的结构体
- typedef struct
- {
- uint32_t Pin;
- uint32_t Mode;
- uint32_t Pull;
- uint32_t Speed;
- uint32_t Alternate;
- }GPIO_InitTypeDef;
- //Pin定义GPIO的引脚
- #define GPIO_PIN_0 ((uint16_t)0x0001)
- #define GPIO_PIN_1 ((uint16_t)0x0002)
- #define GPIO_PIN_2 ((uint16_t)0x0004)
- #define GPIO_PIN_3 ((uint16_t)0x0008)
- #define GPIO_PIN_4 ((uint16_t)0x0010)
- #define GPIO_PIN_5 ((uint16_t)0x0020)
- #define GPIO_PIN_6 ((uint16_t)0x0040)
- #define GPIO_PIN_7 ((uint16_t)0x0080)
- #define GPIO_PIN_8 ((uint16_t)0x0100)
- #define GPIO_PIN_9 ((uint16_t)0x0200)
- #define GPIO_PIN_10 ((uint16_t)0x0400)
- #define GPIO_PIN_11 ((uint16_t)0x0800)
- #define GPIO_PIN_12 ((uint16_t)0x1000)
- #define GPIO_PIN_13 ((uint16_t)0x2000)
- #define GPIO_PIN_14 ((uint16_t)0x4000)
- #define GPIO_PIN_15 ((uint16_t)0x8000)
- #define GPIO_PIN_All ((uint16_t)0xFFFF)
-
- #define GPIO_PIN_MASK 0x0000FFFFU
- //Mode定义引脚功能模式设置
- #define GPIO_MODE_INPUT MODE_INPUT
- /*!<输入浮空模式*/
- #define GPIO_MODE_OUTPUT_PP (MODE_OUTPUT | OUTPUT_PP)
- /*!<推挽输出模式*/
- #define GPIO_MODE_OUTPUT_OD (MODE_OUTPUT | OUTPUT_OD)
- /*!<开漏输出模式*/
- #define GPIO_MODE_AF_PP (MODE_AF | OUTPUT_PP)
- /*!<复用功能推挽模式*/
- #define GPIO_MODE_AF_OD (MODE_AF | OUTPUT_OD)
- /*!<复用功能开漏模式*/
- #define GPIO_MODE_ANALOG MODE_ANALOG
- /*!<带上升沿触发检测的外部中断模式*/
- #define GPIO_MODE_IT_RISING 0x10110000U
- /*!<带上升沿触发检测的外部中断模式*/
- #define GPIO_MODE_IT_FALLING 0x10210000U
- /*!<带下降沿触发检测的外部中断模式*/
- #define GPIO_MODE_IT_RISING_FALLING 0x10310000U
- /*!<带上升沿/下降沿触发检测的外部中断模式*/
-
- #define GPIO_MODE_EVT_RISING 0x10120000u
- /*!<具有上升沿触发器检测的外部事件模式*/
- #define GPIO_MODE_EVT_FALLING 0x10220000u
- /*!< 具有下降沿触发器检测的外部事件模式*/
- #define GPIO_MODE_EVT_RISING_FALLING 0x10320000u
- /*!< 具有下降沿/下降沿触发器检测的外部事件模式*/
-
- //pull定义是否使用内部上拉或下拉电阻
- #define GPIO_NOPULL 0x00000000U /*!< 无上拉或下拉*/
- #define GPIO_PULLUP 0x00000001U /*!< 上拉*/
- #define GPIO_PULLDOWN 0x00000002U /*!< 下拉*/
- //Speed定义输出模式引脚的最高输出频率
- #define GPIO_SPEED_FREQ_LOW 0x00000000U //2MHz
- #define GPIO_SPEED_FREQ_MEDIUM 0x00000001U //12.5-50MHz
- #define GPIO_SPEED_FREQ_HIGH 0x00000002U //25-100MHz
- #define GPIO_SPEED_FREQ_VERY_HIGH 0x00000003U //50-200MHz
- //Alternate定义引脚复用功能
- #define GPIO_AF1_TIM1 ((uint8_t)0x01)
- #define GPIO_AF1_TIM2 ((uint8_t)0x01)
- #define GPIO_AF4_I2C1 ((uint8_t)0x04)
- #define GPIO_AF4_I2C2 ((uint8_t)0x04)
- #define GPIO_AF4_I2C3 ((uint8_t)0x04)
- #define GPIO_AF5_SPI1 ((uint8_t)0x05)
- #define GPIO_AF5_SPI2 ((uint8_t)0x05)
- #define GPIO_AF5_SPI3 ((uint8_t)0x05)
- #define GPIO_AF7_USART1 ((uint8_t)0x07)
- #define GPIO_AF7_USART2 ((uint8_t)0x07)
- #define GPIO_AF7_USART3 ((uint8_t)0x07)
HAL_GPIO_DeInit() GPIO引脚反初始化,恢复为复位后的状态。
HAL_GPIO_WritePin() 使引脚输出0或1
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin,GPIO_PinState PinState);
PinState是引脚输出电平,是枚举类型GPIO_PinState,.
- typedef enum
- {
- GPIO_PIN_RESET = 0,
- GPIO_PIN_SET
- }GPIO_PinState;
例如,要使PF9和PF10输出低电平,使用下面代码:
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9|GPIO_PIN_10,GPIO_PIN_RESET);
如果要输出高电平,使用下面代码:
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9|GPIO_PIN_10,GPIO_PIN_SET);
HAL_GPIO_ReadPin() 读取引脚输入电平
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx,uint16_t GPIO_PIN);
HAL_GPIO_TogglePin() 反转引脚的输出
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx,uint16_t,GPIO_PIN);
HAL_GPIO_LockPin() 锁定引脚配置,而不是锁定引脚的输入或输出状态
资源:
2个LED灯:由+3.3V电源驱动,当GPIO引脚输出为0时,LED点亮。当GPIO引脚输出为1时,LED熄灭。与LED连接的引脚PF9和PF10要设置为推挽输出。
4个按键:KeyUp键,外端接+3.3V,在按键按下时,输入PA0的是高电平,所以引脚PA0应该被设置为输入下拉。在按键未按下时,输入0;
另外3个按键,连接在PE2/PE3/PE4上,外端接地。按键按下时,输入低电平,所以使用输入上拉。
1个有源蜂鸣器:控制端在PF8,应设置为推挽输出。当PF8输出0时,蜂鸣器响,输出为1时,蜂鸣器不响。
原理图:
按下KeyLeft键时,使LED1的输出翻转。
按下KeyRight键时,使LED2的输出翻转。
按下KeyUp键时,使LED1和LED2的输出都翻转。
按下KeyDown键时,使蜂鸣器的输出翻转。
SYS组件中,设置Debug接口为Serial Wire。
RCC组件中,设置HSE为Crystal/Ceramic Resonator。
在时钟树上,设置HSE频率8MHz,实际开发板就是8MHz,主锁相环选择HSE作为时钟源,设置HCLK频率168MHz,软件自动配置时钟树。
根据3.3.2配置GPIO引脚。
用户标签 | 引脚名称 | 引脚功能 | GPIO模式 | 上拉或下拉 |
---|---|---|---|---|
LED1 | PF9 | GPIO_Output | 推挽输出 | 无 |
LED2 | PF10 | GPIO_Output | 推挽输出 | 无 |
KeyRight | PE2 | GPIO_Input | 输入 | 上拉 |
KeyDown | PE3 | GPIO_Input | 输入 | 上拉 |
KeyLeft4 | PE4 | GPIO_Input | 输入 | 上拉 |
KeyUp | PA0 | GPIO_Input | 输入 | 下拉 |
buzzer | PF8 | GPIO_Output | 推挽输出 | 无 |
- void MX_GPIO_Init(void)
- {
-
- GPIO_InitTypeDef GPIO_InitStruct = {0};
-
- /* GPIO Ports Clock Enable */
- __HAL_RCC_GPIOE_CLK_ENABLE();
- __HAL_RCC_GPIOF_CLK_ENABLE();
- __HAL_RCC_GPIOH_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
-
- /*Configure GPIO pin Output Level */
- HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_SET);
-
- /*Configure GPIO pin Output Level */
- HAL_GPIO_WritePin(GPIOF, LED1_Pin|LED2_Pin, GPIO_PIN_RESET);
-
- /*Configure GPIO pins : PEPin PEPin PEPin */
- GPIO_InitStruct.Pin = KeyRight_Pin|KeyDown_Pin|KeyLeft_Pin;
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
-
- /*Configure GPIO pins : PFPin PFPin PFPin */
- GPIO_InitStruct.Pin = Buzzer_Pin|LED1_Pin|LED2_Pin;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
-
- /*Configure GPIO pin : PtPin */
- GPIO_InitStruct.Pin = KeyUp_Pin;
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull = GPIO_PULLDOWN;
- HAL_GPIO_Init(KeyUp_GPIO_Port, &GPIO_InitStruct);
-
- }
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
-
- /** Configure the main internal regulator output voltage
- */
- __HAL_RCC_PWR_CLK_ENABLE();
- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
-
- /** Initializes the RCC Oscillators according to the specified parameters
- * in the RCC_OscInitTypeDef structure.
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
- RCC_OscInitStruct.PLL.PLLM = 8;
- RCC_OscInitStruct.PLL.PLLN = 168;
- RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
- RCC_OscInitStruct.PLL.PLLQ = 4;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
-
- /** Initializes the CPU, AHB and APB buses clocks
- */
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
-
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
- {
- Error_Handler();
- }
- }
- typedef enum{
- Key_NONE = 0, //没有那件按键被按下
- Key_LEFT, //KeyLeft
- Key_RIGHT, //KeyRight
- Key_UP, //KeyUp
- Key_DOWN //KeyDown
- }KEYS;
-
- KEYS ScanPressedKey(uint32_t timeout)
- {
- KEYS key = Key_NONE;
- uint32_t tickstart = HAL_GetTick(); //当前技术值
- const uint32_t btnDelay = 20; //按下按键的抖动,延时在采样时间
- GPIO_PinState keyState; //引脚输入状态
- while(1)
- {
- keyState = HAL_GPIO_ReadPin(KeyLeft_GPIO_Port,KeyLeft_Pin);
- if(keyState == GPIO_PIN_RESET)
- {
- HAL_Delay(btnDelay); //延时跳过前抖动期
- keyState = HAL_GPIO_ReadPin(KeyLeft_GPIO_Port,KeyLeft_Pin); //再采样
- if(keyState == GPIO_PIN_RESET)
- return Key_LEFT;
- }
-
- keyState = HAL_GPIO_ReadPin(KeyRight_GPIO_Port,KeyRight_Pin);
- if(keyState == GPIO_PIN_RESET)
- {
- HAL_Delay(btnDelay); //延时跳过前抖动期
- keyState = HAL_GPIO_ReadPin(KeyRight_GPIO_Port,KeyRight_Pin); //再采样
- if(keyState == GPIO_PIN_RESET)
- return Key_RIGHT;
- }
-
- keyState = HAL_GPIO_ReadPin(KeyDown_GPIO_Port,KeyDown_Pin);
- if(keyState == GPIO_PIN_RESET)
- {
- HAL_Delay(btnDelay); //延时跳过前抖动期
- keyState = HAL_GPIO_ReadPin(KeyDown_GPIO_Port,KeyDown_Pin); //再采样
- if(keyState == GPIO_PIN_RESET)
- return Key_DOWN;
- }
-
- keyState = HAL_GPIO_ReadPin(KeyUp_GPIO_Port,KeyUp_Pin);
- if(keyState == GPIO_PIN_SET)
- {
- HAL_Delay(btnDelay); //延时跳过前抖动期
- keyState = HAL_GPIO_ReadPin(KeyUp_GPIO_Port,KeyUp_Pin); //再采样
- if(keyState == GPIO_PIN_SET)
- return Key_UP;
- }
-
- if(timeout != KEY_WAIT_ALWAYS)
- {
- if((HAL_GetTick() == tickstart) > timeout)
- break;
- }
- }
- return key;
- }
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。