STM32(STM32F103C8T6) 从点灯到深入指南
**STM32F103C8T6入门指南**:从点灯到深入实践。首先准备硬件(最小系统板+ST-Link),安装STM32CubeIDE。入门从LED闪烁开始,通过HAL库控制GPIO。深入阶段:1)学习按键中断,实现消抖处理;2)使用定时器生成精确时序和PWM呼吸灯;3)配置串口重定向printf,方便调试;4)掌握ADC采集模拟信号。综合项目可制作智能呼吸灯(ADC控制PWM频率)或串口命令控制
·
STM32F103C8T6 从点灯到深入指南
第一部分:硬件准备
1.1 所需硬件
- STM32F103C8T6最小系统板(蓝色小板)
- ST-Link V2下载器(或板载ST-Link的Nucleo板)
- USB数据线
- LED和220Ω电阻(如板载LED可省略)
- 杜邦线若干
1.2 引脚对应关系
STM32F103C8T6常用引脚:
LED -> PC13(板载LED,大部分板子都有)
串口1 TX -> PA9
串口1 RX -> PA10
第二部分:环境搭建
2.1 软件安装
- STM32CubeIDE:官网下载
- STM32CubeMX:(已集成在IDE中)
- 驱动:安装ST-Link USB驱动
2.2 第一个工程:LED闪烁
步骤1:使用STM32CubeMX创建工程
1. 打开STM32CubeIDE → New STM32 Project
2. 选择MCU型号:STM32F103C8Tx
3. 配置系统核心:
- SYS → Debug: Serial Wire
- RCC → HSE: Crystal/Ceramic Resonator
4. 配置GPIO:
- PC13 → GPIO_Output(如用板载LED)
5. 时钟配置:设置HCLK为72MHz
6. 生成代码
步骤2:编写LED闪烁代码
// 在main.c的while循环中添加
while (1)
{
// 方法1:使用HAL库函数
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(500); // 500ms延迟
// 方法2:直接寄存器操作(更快)
// GPIOC->ODR ^= GPIO_PIN_13;
// HAL_Delay(500);
}
第三部分:深入外设学习
3.1 GPIO深入 - 按键控制LED
电路连接
按键 → PA0(外部中断)
LED → PC13
代码实现
// 1. CubeMX配置:
// PA0 → GPIO_EXTI0,上升沿触发
// 2. 回调函数实现
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
}
}
// 3. 消抖处理(软件消抖)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
static uint32_t last_time = 0;
uint32_t current_time = HAL_GetTick();
if (current_time - last_time > 50) // 50ms消抖
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
last_time = current_time;
}
}
3.2 定时器 - 精确计时/PWM呼吸灯
定时器中断实现精确闪烁
// 1. CubeMX配置:
// TIM2 → 时钟源Internal Clock
// 预分频:7200-1,自动重载值:5000-1
// 72MHz/7200 = 10kHz,5000/10kHz = 0.5s
// 2. 开启定时器中断
HAL_TIM_Base_Start_IT(&htim2);
// 3. 中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
}
}
PWM呼吸灯
// 1. CubeMX配置:
// TIM3 Channel1 → PA6,PWM Generation CH1
// 预分频:72-1,自动重载值:100-1
// PWM频率 = 72MHz/(72*100) = 10kHz
// 2. 启动PWM
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
// 3. 呼吸灯效果
uint8_t brightness = 0;
int8_t direction = 1;
while (1)
{
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, brightness);
brightness += direction;
if (brightness == 0 || brightness == 100)
direction = -direction;
HAL_Delay(10);
}
3.3 串口通信 - 调试信息输出
串口配置
// 1. CubeMX配置:
// USART1 → Asynchronous
// Baud Rate: 115200
// Word Length: 8bit
// PA9: USART1_TX, PA10: USART1_RX
// 2. 重定向printf(在main.c中添加)
#include <stdio.h>
#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;
}
// 3. 使用printf调试
printf("System Start!\r\n");
printf("LED State: %d\r\n", HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13));
3.4 ADC - 电位器读取
ADC单次转换
// 1. CubeMX配置:
// ADC1 → IN0 (PA0)
// Resolution: 12bit
// Scan Conversion Mode: Disabled
// Continuous Conversion Mode: Disabled
// 2. 读取ADC值
uint32_t adc_value = 0;
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
{
adc_value = HAL_ADC_GetValue(&hadc1);
}
HAL_ADC_Stop(&hadc1);
// 3. 转换为电压值
float voltage = (adc_value * 3.3) / 4095.0;
printf("ADC Value: %ld, Voltage: %.2fV\r\n", adc_value, voltage);
第四部分:综合项目
项目1:智能呼吸灯
// 功能:ADC控制PWM呼吸频率
while (1)
{
// 读取电位器值控制呼吸速度
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
uint32_t adc_val = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
// ADC值映射到延时时间(10-100ms)
uint32_t delay_time = 10 + (adc_val * 90) / 4095;
// 呼吸灯效果
for(int i=0; i<100; i++)
{
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, i);
HAL_Delay(delay_time);
}
for(int i=100; i>0; i--)
{
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, i);
HAL_Delay(delay_time);
}
}
项目2:串口命令控制LED
// 串口接收回调
char rx_buffer[32];
uint8_t rx_index = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (rx_buffer[0] == '1')
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
printf("LED ON\r\n");
}
else if (rx_buffer[0] == '0')
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
printf("LED OFF\r\n");
}
else if (rx_buffer[0] == 't')
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
printf("LED Toggled\r\n");
}
// 继续接收
HAL_UART_Receive_IT(&huart1, (uint8_t*)rx_buffer, 1);
}
// 在主函数初始化中开启接收中断
HAL_UART_Receive_IT(&huart1, (uint8_t*)rx_buffer, 1);
第五部分:调试技巧
5.1 常用调试方法
- LED指示:不同状态用不同闪烁模式
- 串口打印:printf输出变量值
- 逻辑分析仪:观察GPIO波形
- 调试器:单步执行、断点、查看变量
5.2 故障排除
// 检查时钟是否配置正确
SystemCoreClockUpdate();
printf("System Clock: %ld Hz\r\n", SystemCoreClock);
// 检查外设时钟是否使能
if (__HAL_RCC_GPIOA_IS_CLK_ENABLED())
printf("GPIOA Clock Enabled\r\n");
// 检查引脚配置
GPIO_InitTypeDef GPIO_InitStruct = {0};
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
第六部分:进阶学习路径
下一步建议
- 学习DMA:实现ADC+UART的数据传输
- I2C/SPI:连接OLED、传感器
- FreeRTOS:多任务管理系统
- USB:实现USB虚拟串口
- CAN总线:工业通信
实用工具
- STM32CubeMonitor:实时数据可视化
- Wireshark:分析串口/USB数据
- VOFA+:串口波形显示工具
快速参考命令
# 常见问题:
1. 程序不运行? → 检查BOOT0/BOOT1引脚
2. 无法下载? → 检查ST-Link连接
3. 串口无输出? → 检查波特率、TX/RX接线
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐



所有评论(0)