北屋教程网

专注编程知识分享,从入门到精通的编程学习平台

STM32入门:从GPIO到ADC的5个最常用外设配置指南

为什么这5个外设是STM32的"敲门砖"?

STM32微控制器凭借高性能、低成本成为嵌入式开发的首选,但新手往往被复杂的外设配置劝退。其实,GPIO、UART、SPI、I2C、ADC这5个外设是80%项目的核心——从控制LED、读取传感器到串口通信,几乎所有应用都离不开它们。今天我们用"配置步骤+实战案例+代码片段"的方式,带你快速上手,看完就能动手做项目!

一、GPIO:最基础的"数字开关",控制LED只需3步

1. 功能概述

GPIO(通用输入输出)是STM32与外界交互的"手脚":输出高低电平控制LED、继电器,输入模式读取按键、传感器信号。每个引脚可独立配置为输入(上拉/下拉/浮空)输出(推挽/开漏),还能复用为UART、SPI等外设引脚。

2. 配置步骤(以STM32CubeMX为例)

第一步:启用时钟

GPIO挂载在AHB1总线上,需先在"RCC"中开启对应端口时钟(如GPIOA)。

第二步:引脚配置

在"Pinout"界面选择引脚(如PA5),设置模式为GPIO_Output,输出类型推挽(PP),速度高速(50MHz),无上拉下拉。

第三步:生成代码并控制

CubeMX自动生成初始化函数,在main.c中用HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);点亮LED,GPIO_PIN_RESET熄灭。

3. 实战案例:按键控制LED翻转

硬件连接:按键接PA0(上拉输入),LED接PA5(推挽输出)。
核心代码

// 初始化GPIO
void MX_GPIO_Init(void) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  __HAL_RCC_GPIOA_CLK_ENABLE();
  // LED引脚配置
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  // 按键引脚配置(上拉输入)
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 主循环检测按键
while (1) {
  if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { // 按键按下(低电平)
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 翻转LED
    HAL_Delay(200); // 消抖
  }
}

配图:GPIO配置界面与硬件连接


图1:STM32CubeMX中GPIO推挽输出配置界面,红框标注模式与速度设置

二、UART:串口通信"万金油",调试/传数据全靠它

1. 功能概述

UART(通用异步收发器)是设备间通信的"电话线",无需时钟线,通过TX(发送)/RX(接收)两根线即可实现数据传输。常用波特率115200bps,支持中断/DMA模式,适合调试信息输出、传感器数据接收(如GPS、蓝牙模块)。

2. 配置步骤

第一步:选择UART外设

在CubeMX"Connectivity"中选USART1,模式异步(Asynchronous),波特率115200,数据位8位,停止位1位,无校验。

第二步:引脚复用

USART1默认复用PA9(TX)、PA10(RX),在引脚图中确认引脚功能为USART1_TX/RX

第三步:使能中断(可选)

如需接收数据,在"NVIC"中勾选USART1中断,优先级设为1(高于普通任务)。

3. 实战案例:串口发送"Hello STM32"

硬件连接:USB转TTL模块的TX接PA10,RX接PA9,GND共地。
核心代码

// 发送函数
uint8_t tx_data[] = "Hello STM32!\r\n";
HAL_UART_Transmit(&huart1, tx_data, sizeof(tx_data), HAL_MAX_DELAY);

// 中断接收(接收1字节后触发)
uint8_t rx_data;
HAL_UART_Receive_IT(&huart1, &rx_data, 1);

// 接收回调函数(在stm32f1xx_it.c中)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
  if (huart == &huart1) {
    HAL_UART_Transmit(&huart1, &rx_data, 1, HAL_MAX_DELAY); // 原样发送接收到的数据
    HAL_UART_Receive_IT(&huart1, &rx_data, 1); // 重新开启接收
  }
}

配图:UART硬件连接图


图2:STM32与USB转TTL模块的交叉连接方式(TX接RX,RX接TX)

三、SPI:高速同步通信,驱动显示屏/Flash就靠它

1. 功能概述

SPI(串行外设接口)是"高速数据公路",全双工同步通信,速度可达几十Mbps,适合连接LCD显示屏、Flash存储器、AD转换器。通过SCK(时钟)、MOSI(主发从收)、MISO(主收从发)、NSS(片选)四线通信,支持一主多从架构。

2. 关键配置:时钟极性与相位

SPI有4种工作模式,核心是CPOL(时钟极性)CPHA(时钟相位)

  • CPOL=0:空闲时SCK低电平;CPOL=1:空闲时SCK高电平。
  • CPHA=0:第一个时钟沿采样数据;CPHA=1:第二个时钟沿采样数据。
    常用模式0(CPOL=0,CPHA=0)和模式3(CPOL=1,CPHA=1),需与外设手册一致(如W25Q64 Flash用模式0)。

3. 实战案例:SPI驱动1.8寸TFT显示屏

硬件连接:SCK=PA5,MOSI=PA7,NSS=PA4(软件控制片选),DC=PA2(数据/命令切换)。
核心代码

// SPI发送命令
void LCD_WriteCmd(uint8_t cmd) {
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); // DC=0(命令)
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // NSS=0(选中)
  HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // NSS=1(取消选中)
}

// 初始化SPI
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; // CPOL=0
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; // CPHA=0
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // 36MHz(APB2=72MHz/2)

配图:SPI通信时序图


图3:SPI模式0时序(CPOL=0,上升沿采样数据,下降沿更新数据)

四、I2C:双线控制多设备,传感器通信首选

1. 功能概述

I2C(集成电路间总线)是"极简通信协议",仅用SCL(时钟)、SDA(数据)两根线,即可连接多个从设备(如OLED屏、温湿度传感器、EEPROM),通过7位地址区分设备(如SSD1306 OLED地址0x3C)。速度分标准模式(100kHz)和快速模式(400kHz),适合低速率、多设备场景。

2. 配置步骤

第一步:使能I2C外设

在CubeMX"Connectivity"中选I2C1,模式I2C,时钟频率400kHz,地址模式7位。

第二步:引脚配置

I2C1默认复用PB6(SCL)、PB7(SDA),需外接上拉电阻(4.7kΩ,部分模块内置)。

3. 实战案例:I2C驱动OLED显示文字

硬件连接:OLED的SCL接PB6,SDA接PB7,VCC=3.3V,GND共地。
核心代码

// 初始化OLED
SSD1306_Init();
// 显示字符
SSD1306_GotoXY(10, 10); // 坐标(x=10,y=10)
SSD1306_Puts("Hello I2C!", &Font_7x10, 1); // 字体7x10,显示
SSD1306_UpdateScreen(); // 刷新屏幕

配图:I2C OLED接线图


图4:OLED模块引脚定义(GND=地,VCC=3.3V,SCL=时钟,SDA=数据)

五、ADC:模拟信号转数字,读取传感器的"翻译官"

1. 功能概述

ADC(模数转换器)将03.3V模拟电压转为12位数字值(04095),用于读取光敏电阻、温度传感器(如LM35)、电位器等模拟信号。STM32F103有3个ADC,支持单通道/多通道扫描,最高转换速率1MHz(1μs/次)。

2. 配置步骤

第一步:选择ADC通道

在CubeMX"Analog"中选ADC1,通道0(PA0),模式单次转换,扫描模式关闭。

第二步:校准ADC

ADC上电后需校准,调用
HAL_ADCEx_Calibration_Start(&hadc1);

第三步:读取转换值

启动ADC转换,等待完成后读取结果,公式:电压=ADC值×3.3V/4096

3. 实战案例:电位器控制LED亮度

硬件连接:电位器中间引脚接PA0,两端接3.3V和GND,LED接PB5(PWM控制)。
核心代码

// 读取ADC值
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
uint16_t adc_val = HAL_ADC_GetValue(&hadc1);
float voltage = adc_val * 3.3f / 4096.0f;

// PWM占空比 = ADC值/4096(0~100%)
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, adc_val/4); // TIM3_CH2=PB5

配图:ADC电压采集电路


图5:ADC采集电路(电位器分压后输入PA0,电容C1滤波减少噪声)

从"配置"到"项目"的3个建议

  1. 先图形化配置,再深入寄存器:新手用STM32CubeMX快速上手,熟悉后看HAL库源码,理解寄存器操作(如GPIOx_ODR控制输出)。
  2. 用"最小系统"验证:每个外设先搭最小电路(如GPIO+LED),确保基础功能正常,再添加复杂模块。
  3. 结合示波器调试:SPI/I2C通信异常时,用示波器看SCK/SDA波形,对比时序图找问题(如CPOL/CPHA配置错误)。

互动话题:你第一次用STM32时,被哪个外设难住了?欢迎在评论区分享你的踩坑经历,点赞最高的送《STM32外设配置速查表》!

(文章配图来源:CSDN博客、ST官方文档,案例代码经实测验证)

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言