从“点灯”到“通信”:STM32F103C8T6引脚复用实战指南
第一次拿到STM32开发板时,很多人会被密密麻麻的引脚吓到——PA0、PB5、USART1_TX、I2C2_SCL...这些标识到底意味着什么?本文将带你从最基础的LED控制开始,逐步解锁STM32F103C8T6的引脚复用功能,最终实现串口通信、ADC采样和OLED显示等实用功能。通过四个渐进式项目,你将彻底理解如何将芯片手册中的引脚功能表转化为实际可运行的代码。
1. 硬件准备与开发环境搭建
在开始编程前,我们需要准备以下硬件:
- STM32F103C8T6最小系统板(俗称"蓝板")
- USB转TTL串口模块(如CH340G)
- 0.96寸I2C接口OLED屏幕
- 10KΩ电位器
- LED及220Ω限流电阻
- 面包板和杜邦线若干
开发环境推荐使用:
- Keil MDK-ARM:经典STM32开发IDE
- STM32CubeMX:图形化引脚配置工具
- 串口调试助手:如Putty或SecureCRT
安装STM32F1的HAL库支持包:
# 在CubeMX中安装F1系列支持包 STM32Cube → Help → Manage embedded software packages → STM32F1提示:初学者常犯的错误是未正确安装芯片支持包,导致编译时出现"Device not found"错误。
2. 点亮第一个LED:GPIO基础配置
我们从最简单的GPIO控制开始。假设我们要用PA0引脚控制LED:
- 在CubeMX中配置PA0为GPIO_Output
- 设置初始输出电平为Low(LED共阳极)或High(共阴极)
- 生成代码框架
关键代码片段:
// 在main.c的while循环中添加 HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0); HAL_Delay(500); // 500ms间隔引脚模式对照表:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| GPIO_MODE_INPUT | 输入模式 | 读取按键状态 |
| GPIO_MODE_OUTPUT_PP | 推挽输出 | LED控制 |
| GPIO_MODE_OUTPUT_OD | 开漏输出 | I2C通信 |
| GPIO_MODE_AF_PP | 复用推挽 | USART_TX |
| GPIO_MODE_AF_OD | 复用开漏 | I2C_SCL |
常见问题排查:
- LED不亮:检查电路连接,确认共阳/共阴极接法正确
- 闪烁频率异常:检查系统时钟配置是否正确(默认应为72MHz)
3. 串口通信:USART引脚复用实战
STM32F103C8T6有3个USART接口,我们以USART1为例:
- 在CubeMX中启用USART1
- 配置PA9为USART1_TX,PA10为USART1_RX
- 设置波特率为115200,8位数据,无校验
- 生成代码并添加打印功能
关键初始化代码:
// 在main.c中添加串口重定向 #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY); return ch; }测试代码:
printf("USART1测试成功\r\n");注意:使用printf前需在Project Options中勾选"Use MicroLIB"
常见调试技巧:
- 如果收不到数据,先用短路帽连接TX和RX,测试自发自收
- 测量PA9/PA10电压,空闲时应为高电平(3.3V)
4. 模拟信号采集:ADC引脚配置技巧
STM32的ADC精度为12位,我们以PA1(ADC1_IN1)为例读取电位器电压:
- 配置PA1为ADC1_IN1
- 设置ADC为12位分辨率,连续转换模式
- 启用DMA传输以提高效率
关键代码:
// 启动ADC HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adc_value, 1); // 获取电压值(单位:mV) uint16_t get_voltage() { return adc_value * 3300 / 4095; }ADC通道与引脚对应表:
| 通道 | 引脚 | 备注 |
|---|---|---|
| ADC12_IN0 | PA0 | 带Wakeup功能 |
| ADC12_IN1 | PA1 | |
| ADC12_IN2 | PA2 | 与USART2_TX复用 |
| ADC12_IN3 | PA3 | 与USART2_RX复用 |
| ADC12_IN4 | PA4 | |
| ADC12_IN5 | PA5 |
校准技巧:
- 上电后先执行HAL_ADCEx_Calibration_Start()
- 避免长导线引入干扰,必要时加0.1uF滤波电容
5. 显示驱动:I2C引脚复用详解
使用PB10(I2C2_SCL)和PB11(I2C2_SDA)驱动OLED:
- 配置I2C2为标准模式(100kHz)
- 设置PB10为复用开漏输出,PB11同理
- 启用I2C中断
OLED初始化序列示例:
void OLED_Init() { uint8_t init_cmd[] = {0xAE,0xD5,0x80,0xA8,0x3F,...}; HAL_I2C_Mem_Write(&hi2c2, OLED_ADDR, 0x00, 1, init_cmd, sizeof(init_cmd), 100); }I2C通信关键点:
- 上拉电阻:通常4.7kΩ(开发板一般已集成)
- 时序调试:可用逻辑分析仪抓取SCL/SDA波形
- 地址确认:0.96寸OLED通常为0x78或0x7A
实际项目中,我曾遇到I2C通信失败的情况,最终发现是PB10和PB11被意外配置为了普通GPIO模式。通过CubeMX重新生成代码后问题解决——这提醒我们,复用功能配置后一定要验证生成的初始化代码是否符合预期。