目录
一、基础知识
(一)基本特性
-
数字和模拟信号
-
数字信号
基本概念:两种逻辑状态:逻辑高(1,接近VDD)和逻辑低(0,接近GND)。
处理机制:GPIO操作、通信接口、中断驱动
-
模拟信号
处理机制:ADC、DAC、Op-Amps
-
-
IO端口基本结构
- 端口
- 引脚:包括GPIO(通用输入/输出)和其他引脚。
- 寄存器
(二)引脚配置
-
多路复用——基于stm32f103
-
// 以配置USART1为例 __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟 __HAL_RCC_USART1_CLK_ENABLE(); // 使能USART1时钟
//使用HAL库的GPIO初始化函数,设置GPIO引脚的模式、输出类型以及复用功能。 GPIO_InitTypeDef GPIO_InitStruct = {0}; // 配置PA9为USART1_TX GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 设置为复用推挽输出 GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上拉或下拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 设置为高速 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置PA10为USART1_RX,如果需要 GPIO_InitStruct.Pin = GPIO_PIN_10; // 其余配置与USART1_TX相同 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
对STM32F1系列来说,复用功能由特定的引脚与外设映射定义,因此选择特定复用功能的步骤主要通过正确选择引脚和外设关联来实现,并不需要像STM32F4系列那样设置AFR寄存器。
-
-
引脚电气特性
-
引脚输出类型
- 推挽(Push-Pull):可主动输出高/低电平,适合大多数输出场景。
- 开漏(Open-Drain):只能输出低电平,高电平依赖外部上拉,适用于总线通信。
-
驱动能力与速度
- 低功耗:低电流驱动,适合功耗敏感应用。
- 中速:平衡电流和速度,适用于通用目的。
- 高速:高电流驱动,适用于高速信号或大负载。
-
上拉/下拉配置
- 上拉(Pull-up):高电平稳定,避免悬空。
- 下拉(Pull-down):低电平稳定,避免悬空。
-
模拟模式
-
ADC/DAC转换,减少数字噪音干扰。
-
-
二、工作原理
(一)逻辑状态
-
低电平(逻辑0)
-
高电平(逻辑1)
-
中断触发(ISR)
(二)输入模式与输出模式的区别
-
方向性
-
电阻状态
-
应用目的
(三)基于中断的GPIO输入
-
使能GPIO端口时钟:确保GPIO端口的时钟使能,以供后续配置。
-
配置GPIO引脚为输入模式:通过GPIO初始化结构体设置引脚为输入模式,并定义上拉、下拉等电气特性。
-
配置中断触发条件:根据需要选择适当的触发条件,如上升沿、下降沿或双边沿触发。
-
使能中断和设置优先级:在NVIC(Nested Vectored Interrupt Controller)中使能GPIO中断,并设置其优先级。
-
实现中断服务程序(ISR):编写ISR以处理当中断发生时需要执行的任务,例如读取传感器数据、更改系统状态等。
三、控制方法
(一) 硬件端口的配置
-
寄存器配置(8种工作模式)
-
端口初始化
- 启用外设时钟
-
__HAL_RCC_GPIOA_CLK_ENABLE(); // 启用GPIOA时钟 __HAL_RCC_TIM1_CLK_ENABLE(); // 启用定时器1时钟
-
- 配置GPIO引脚
-
GPIO_InitTypeDef gpioInitStruct = {0}; gpioInitStruct.Pin = GPIO_PIN_0; // 选择引脚PA0 gpioInitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式 gpioInitStruct.Pull = GPIO_NOPULL; // 无上下拉 gpioInitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速 HAL_GPIO_Init(GPIOA, &gpioInitStruct); // 初始化GPIO
-
- 配置定时器和PWM
-
TIM_HandleTypeDef htim1; void MX_TIM1_Init(void) { TIM_OC_InitTypeDef ocInitStruct = {0}; htim1.Instance = TIM1; // 选择定时器1 htim1.Init.Prescaler = 84 - 1; // 设置预分频器 htim1.Init.Period = 100 - 1; // 设置PWM周期 htim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 向上计数 htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim1); // 初始化定时器 // 配置PWM参数 ocInitStruct.OCMode = TIM_OCMODE_PWM1; ocInitStruct.Pulse = 0; // 初始占空比为0 ocInitStruct.OCPolarity = TIM_OCPOLARITY_HIGH; ocInitStruct.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim1, &ocInitStruct, TIM_CHANNEL_1); // 配置PWM通道 }
-
- 启用外设时钟
(二)使用编程语言控制GPIO
-
C语言基础操作
-
使用库函数(HAL库)
-
启用GPIO时钟
__HAL_RCC_GPIOC_CLK_ENABLE(); // 启用GPIOC时钟
-
配置GPIOC引脚
GPIO_InitTypeDef gpioInitStruct = {0}; gpioInitStruct.Pin = GPIO_PIN_0; // 选择引脚PC0 gpioInitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式 gpioInitStruct.Pull = GPIO_NOPULL; // 无上下拉 gpioInitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速 HAL_GPIO_Init(GPIOC, &gpioInitStruct); // 初始化PC0
-
设置引脚状态
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // 将PC0设置为高 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // 将PC0设置为低
-
读取引脚状态
GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0); // 读取PC0状态
-
(三)示例代码讲解
-
点亮LED
-
//Arduino #define LED_PIN 13 // LED引脚 void setup() { pinMode(LED_PIN, OUTPUT); // 设置引脚为输出 } void loop() { digitalWrite(LED_PIN, HIGH); // 点亮LED delay(1000); // 延时1秒 digitalWrite(LED_PIN, LOW); // 熄灭LED delay(1000); // 延时1秒 }
-
四、应用实例(PWM)——基于stm32f407
(一)LED闪烁
-
#include "main.h" // 定义LED引脚 const uint16_t ledPin = GPIO_PIN_0; // 选择PA0作为LED引脚 void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while (1) { HAL_GPIO_WritePin(GPIOA, ledPin, GPIO_PIN_SET); // 点亮LED HAL_Delay(500); // 延时500毫秒 HAL_GPIO_WritePin(GPIOA, ledPin, GPIO_PIN_RESET); // 熄灭LED HAL_Delay(500); // 延时500毫秒 } } static void MX_GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef gpioInitStruct = {0}; gpioInitStruct.Pin = ledPin; // 设置引脚 gpioInitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式 gpioInitStruct.Pull = GPIO_NOPULL; // 不使用上拉或下拉 gpioInitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速 HAL_GPIO_Init(GPIOA, &gpioInitStruct); // 初始化GPIO引脚 }
(二)LED流水灯
-
#include "main.h" // 定义LED引脚数组 const uint16_t ledPins[] = { GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3 }; const uint8_t ledCount = sizeof(ledPins) / sizeof(ledPins[0]); void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while (1) { for (uint8_t i = 0; i < ledCount; i++) { HAL_GPIO_WritePin(GPIOA, ledPins[i], GPIO_PIN_SET); // 点亮LED HAL_Delay(250); // 延时 HAL_GPIO_WritePin(GPIOA, ledPins[i], GPIO_PIN_RESET); // 熄灭LED } } } static void MX_GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef gpioInitStruct = {0}; gpioInitStruct.Mode = GPIO_MODE_OUTPUT_PP; gpioInitStruct.Pull = GPIO_NOPULL; gpioInitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 为所有LED引脚初始化 for (uint8_t i = 0; i < ledCount; i++) { gpioInitStruct.Pin = ledPins[i]; HAL_GPIO_Init(GPIOA, &gpioInitStruct); } }
(三)控制电机和蜂鸣器
-
//PWM初始化与配置 static void MX_TIM_Init(void) { __HAL_RCC_TIM1_CLK_ENABLE(); // 启用定时器1时钟 TIM_OC_InitTypeDef ocInitStruct = {0}; htim1.Instance = TIM1; // 选择定时器1 htim1.Init.Prescaler = 84 - 1; // 设置预分频器(假设时钟频率为84MHz,分频到1MHz) htim1.Init.Period = 100 - 1; // 设置PWM周期(100us) htim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 向上计数 htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim1); // 初始化定时器 // 设置PWM参数 ocInitStruct.OCMode = TIM_OCMODE_PWM1; ocInitStruct.Pulse = 0; // 初始占空比为0 ocInitStruct.OCPolarity = TIM_OCPOLARITY_HIGH; ocInitStruct.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim1, &ocInitStruct, TIM_CHANNEL_1); // 配置PWM通道 }
//控制电机和蜂鸣器 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // 启动PWM // 控制电机转动 for (uint32_t dutyCycle = 0; dutyCycle <= 100; dutyCycle += 10) { __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, dutyCycle); // 设置PWM占空比 HAL_Delay(500); // 延时500毫秒 } // 控制蜂鸣器发声 for (uint32_t freq = 500; freq <= 2000; freq += 500) { __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 50); // 设置占空比 HAL_TIM_Base_Start(&htim1); // 启动定时器 HAL_Delay(500); // 延时500毫秒 __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0); // 关闭蜂鸣器 HAL_Delay(500); // 延时500毫秒 }
五、调试与故障排除
- USB Type-C接口自身并不直接支持传统的硬件级串口通信