1. STM32单片机概述

STM32是意法半导体(STMicroelectronics)推出的基于ARM Cortex-M内核的32位微控制器系列,具有高性能、低功耗、丰富外设等特点,广泛应用于工业控制、消费电子、物联网等领域。本文将详细介绍STM32开发环境搭建、HAL库使用、外设编程以及实际项目开发。

1.1 STM32系列特点

  1. 高性能: ARM Cortex-M内核,主频可达400MHz
  2. 低功耗: 多种低功耗模式,适合电池供电应用
  3. 丰富外设: GPIO、UART、SPI、I2C、ADC、DAC、定时器等
  4. 开发友好: 完善的开发工具链和HAL库支持
  5. 生态丰富: 大量第三方库和开发板支持

1.2 STM32系列分类

按内核分类

  • Cortex-M0: 入门级,成本敏感应用
  • Cortex-M3: 主流应用,平衡性能和成本
  • Cortex-M4: 高性能,支持DSP指令
  • Cortex-M7: 超高性能,支持双精度浮点

按应用分类

  • STM32F系列: 通用型,平衡性能和成本
  • STM32L系列: 低功耗型,电池供电应用
  • STM32H系列: 高性能型,复杂控制应用
  • STM32G系列: 入门级,成本优化

1.3 开发环境

官方开发工具

  • STM32CubeMX: 图形化配置工具
  • STM32CubeIDE: 集成开发环境
  • STM32CubeProgrammer: 编程工具

第三方工具

  • Keil MDK: 专业嵌入式开发环境
  • IAR Embedded Workbench: 高性能编译器
  • PlatformIO: 跨平台开发平台

2. STM32开发环境搭建

2.1 STM32CubeIDE安装配置

1
2
3
4
5
6
7
8
# 下载STM32CubeIDE
# 访问官网: https://www.st.com/en/development-tools/stm32cubeide.html

# 安装步骤
1. 下载对应操作系统的安装包
2. 运行安装程序
3. 选择安装路径和组件
4. 配置工作空间

2.2 STM32CubeMX配置

1
2
3
4
5
6
// STM32CubeMX配置步骤
1. 选择MCU型号
2. 配置系统时钟
3. 配置外设参数
4. 生成初始化代码
5. 导出到IDE项目

2.3 HAL库介绍

HAL(Hardware Abstraction Layer)库是STM32官方提供的硬件抽象层,提供统一的API接口。

1
2
3
4
5
6
7
8
// HAL库主要模块
#include "stm32f4xx_hal.h" // 核心HAL库
#include "stm32f4xx_hal_gpio.h" // GPIO控制
#include "stm32f4xx_hal_uart.h" // UART通信
#include "stm32f4xx_hal_i2c.h" // I2C通信
#include "stm32f4xx_hal_spi.h" // SPI通信
#include "stm32f4xx_hal_adc.h" // ADC采集
#include "stm32f4xx_hal_tim.h" // 定时器控制

3. GPIO控制实战

3.1 GPIO基本配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// GPIO配置结构体
typedef struct {
uint32_t Pin; // 引脚号
uint32_t Mode; // 模式
uint32_t Pull; // 上下拉
uint32_t Speed; // 速度
uint32_t Alternate; // 复用功能
} GPIO_InitTypeDef;

// GPIO模式定义
#define GPIO_MODE_INPUT 0x00000000U
#define GPIO_MODE_OUTPUT_PP 0x00000001U
#define GPIO_MODE_OUTPUT_OD 0x00000011U
#define GPIO_MODE_AF_PP 0x00000002U
#define GPIO_MODE_AF_OD 0x00000012U
#define GPIO_MODE_ANALOG 0x00000003U
#define GPIO_MODE_IT_RISING 0x10110000U
#define GPIO_MODE_IT_FALLING 0x10210000U
#define GPIO_MODE_IT_RISING_FALLING 0x10310000U

3.2 LED控制实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// LED控制代码
#include "main.h"

// LED引脚定义
#define LED_PIN GPIO_PIN_13
#define LED_PORT GPIOC

// LED初始化
void LED_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};

// 使能GPIO时钟
__HAL_RCC_GPIOC_CLK_ENABLE();

// 配置GPIO
GPIO_InitStruct.Pin = LED_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
}

// LED控制函数
void LED_Toggle(void) {
HAL_GPIO_TogglePin(LED_PORT, LED_PIN);
}

void LED_On(void) {
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);
}

void LED_Off(void) {
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
}

// 主函数中的使用
int main(void) {
HAL_Init();
SystemClock_Config();
LED_Init();

while (1) {
LED_Toggle();
HAL_Delay(500); // 延时500ms
}
}

3.3 按键检测实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 按键检测代码
#define BUTTON_PIN GPIO_PIN_0
#define BUTTON_PORT GPIOA

// 按键初始化
void Button_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};

__HAL_RCC_GPIOA_CLK_ENABLE();

GPIO_InitStruct.Pin = BUTTON_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);
}

// 按键检测函数
uint8_t Button_Read(void) {
return HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);
}

// 防抖处理
uint8_t Button_Read_Debounce(void) {
static uint32_t last_time = 0;
uint32_t current_time = HAL_GetTick();

if (current_time - last_time > 50) { // 50ms防抖
if (Button_Read() == GPIO_PIN_RESET) {
last_time = current_time;
return 1;
}
}
return 0;
}

4. UART通信实战

4.1 UART配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// UART配置结构体
typedef struct {
USART_TypeDef *Instance; // UART实例
UART_InitTypeDef Init; // 初始化参数
uint8_t *pTxBuffPtr; // 发送缓冲区指针
uint16_t TxXferSize; // 发送数据大小
uint16_t TxXferCount; // 发送计数器
uint8_t *pRxBuffPtr; // 接收缓冲区指针
uint16_t RxXferSize; // 接收数据大小
uint16_t RxXferCount; // 接收计数器
DMA_HandleTypeDef *hdmatx; // DMA发送句柄
DMA_HandleTypeDef *hdmarx; // DMA接收句柄
HAL_LockTypeDef Lock; // 锁定状态
__IO HAL_UART_StateTypeDef gState; // 全局状态
__IO HAL_UART_StateTypeDef RxState; // 接收状态
__IO uint32_t ErrorCode; // 错误代码
} UART_HandleTypeDef;

// UART初始化
UART_HandleTypeDef huart1;

void UART1_Init(void) {
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;

if (HAL_UART_Init(&huart1) != HAL_OK) {
Error_Handler();
}
}

4.2 UART发送接收

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// UART发送函数
void UART_SendString(UART_HandleTypeDef *huart, char *str) {
HAL_UART_Transmit(huart, (uint8_t *)str, strlen(str), HAL_MAX_DELAY);
}

void UART_SendData(UART_HandleTypeDef *huart, uint8_t *data, uint16_t size) {
HAL_UART_Transmit(huart, data, size, HAL_MAX_DELAY);
}

// UART接收函数
void UART_ReceiveData(UART_HandleTypeDef *huart, uint8_t *data, uint16_t size) {
HAL_UART_Receive(huart, data, size, HAL_MAX_DELAY);
}

// 中断接收
void UART_ReceiveIT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) {
HAL_UART_Receive_IT(huart, pData, Size);
}

// 接收完成回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART1) {
// 处理接收到的数据
// 重新启动接收
HAL_UART_Receive_IT(&huart1, rx_buffer, 1);
}
}

4.3 串口调试实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 串口调试代码
char debug_buffer[100];

void Debug_Printf(const char *format, ...) {
va_list args;
va_start(args, format);
vsnprintf(debug_buffer, sizeof(debug_buffer), format, args);
va_end(args);

UART_SendString(&huart1, debug_buffer);
}

// 使用示例
int main(void) {
HAL_Init();
SystemClock_Config();
UART1_Init();

Debug_Printf("STM32 UART Debug Test\r\n");
Debug_Printf("System Clock: %lu Hz\r\n", HAL_RCC_GetSysClockFreq());

while (1) {
Debug_Printf("Tick: %lu\r\n", HAL_GetTick());
HAL_Delay(1000);
}
}

5. I2C通信实战

5.1 I2C配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// I2C配置
I2C_HandleTypeDef hi2c1;

void I2C1_Init(void) {
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000; // 100kHz
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

if (HAL_I2C_Init(&hi2c1) != HAL_OK) {
Error_Handler();
}
}

5.2 I2C读写操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// I2C写操作
HAL_StatusTypeDef I2C_WriteByte(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
return HAL_I2C_Mem_Write(hi2c, DevAddress, MemAddress,
I2C_MEMADD_SIZE_8BIT, pData, Size, HAL_MAX_DELAY);
}

// I2C读操作
HAL_StatusTypeDef I2C_ReadByte(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
return HAL_I2C_Mem_Read(hi2c, DevAddress, MemAddress,
I2C_MEMADD_SIZE_8BIT, pData, Size, HAL_MAX_DELAY);
}

// EEPROM读写示例
#define EEPROM_ADDRESS 0xA0

HAL_StatusTypeDef EEPROM_Write(uint16_t address, uint8_t *data, uint16_t size) {
return I2C_WriteByte(&hi2c1, EEPROM_ADDRESS, address, data, size);
}

HAL_StatusTypeDef EEPROM_Read(uint16_t address, uint8_t *data, uint16_t size) {
return I2C_ReadByte(&hi2c1, EEPROM_ADDRESS, address, data, size);
}

6. SPI通信实战

6.1 SPI配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// SPI配置
SPI_HandleTypeDef hspi1;

void SPI1_Init(void) {
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;

if (HAL_SPI_Init(&hspi1) != HAL_OK) {
Error_Handler();
}
}

6.2 SPI读写操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// SPI发送接收
HAL_StatusTypeDef SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData,
uint8_t *pRxData, uint16_t Size) {
return HAL_SPI_TransmitReceive(hspi, pTxData, pRxData, Size, HAL_MAX_DELAY);
}

// SPI发送
HAL_StatusTypeDef SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) {
return HAL_SPI_Transmit(hspi, pData, Size, HAL_MAX_DELAY);
}

// SPI接收
HAL_StatusTypeDef SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) {
return HAL_SPI_Receive(hspi, pData, Size, HAL_MAX_DELAY);
}

// SPI Flash操作示例
#define FLASH_CS_PIN GPIO_PIN_4
#define FLASH_CS_PORT GPIOA

void Flash_CS_Low(void) {
HAL_GPIO_WritePin(FLASH_CS_PORT, FLASH_CS_PIN, GPIO_PIN_RESET);
}

void Flash_CS_High(void) {
HAL_GPIO_WritePin(FLASH_CS_PORT, FLASH_CS_PIN, GPIO_PIN_SET);
}

uint8_t Flash_ReadID(void) {
uint8_t cmd = 0x9F;
uint8_t id[3];

Flash_CS_Low();
SPI_Transmit(&hspi1, &cmd, 1);
SPI_Receive(&hspi1, id, 3);
Flash_CS_High();

return id[0];
}

7. ADC采集实战

7.1 ADC配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ADC配置
ADC_HandleTypeDef hadc1;

void ADC1_Init(void) {
ADC_ChannelConfTypeDef sConfig = {0};

hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

if (HAL_ADC_Init(&hadc1) != HAL_OK) {
Error_Handler();
}

// 配置ADC通道
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
Error_Handler();
}
}

7.2 ADC采集实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// ADC采集函数
uint32_t ADC_ReadValue(ADC_HandleTypeDef *hadc) {
HAL_ADC_Start(hadc);
HAL_ADC_PollForConversion(hadc, HAL_MAX_DELAY);
uint32_t value = HAL_ADC_GetValue(hadc);
HAL_ADC_Stop(hadc);
return value;
}

// 电压转换
float ADC_ToVoltage(uint32_t adc_value) {
return (float)adc_value * 3.3f / 4095.0f;
}

// 多通道ADC采集
uint32_t ADC_ReadChannel(ADC_HandleTypeDef *hadc, uint32_t channel) {
ADC_ChannelConfTypeDef sConfig = {0};

sConfig.Channel = channel;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

HAL_ADC_ConfigChannel(hadc, &sConfig);
return ADC_ReadValue(hadc);
}

// ADC采集示例
int main(void) {
HAL_Init();
SystemClock_Config();
ADC1_Init();

while (1) {
uint32_t adc_value = ADC_ReadValue(&hadc1);
float voltage = ADC_ToVoltage(adc_value);

Debug_Printf("ADC Value: %lu, Voltage: %.2fV\r\n", adc_value, voltage);
HAL_Delay(1000);
}
}

8. PWM输出实战

8.1 定时器PWM配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 定时器PWM配置
TIM_HandleTypeDef htim2;

void TIM2_PWM_Init(void) {
TIM_OC_InitTypeDef sConfigOC = {0};

htim2.Instance = TIM2;
htim2.Init.Prescaler = 84 - 1; // 84MHz / 84 = 1MHz
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000 - 1; // 1MHz / 1000 = 1kHz
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) {
Error_Handler();
}

// 配置PWM通道
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
Error_Handler();
}

HAL_TIM_MspPostInit(&htim2);
}

8.2 PWM控制函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// PWM控制函数
void PWM_SetDutyCycle(TIM_HandleTypeDef *htim, uint32_t Channel, uint16_t duty) {
uint32_t pulse = (htim->Init.Period + 1) * duty / 100;
__HAL_TIM_SET_COMPARE(htim, Channel, pulse);
}

void PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel) {
HAL_TIM_PWM_Start(htim, Channel);
}

void PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) {
HAL_TIM_PWM_Stop(htim, Channel);
}

// PWM呼吸灯效果
void PWM_BreathingLED(void) {
static int16_t direction = 1;
static uint16_t duty = 0;

duty += direction;
if (duty >= 100) {
duty = 100;
direction = -1;
} else if (duty <= 0) {
duty = 0;
direction = 1;
}

PWM_SetDutyCycle(&htim2, TIM_CHANNEL_1, duty);
}

// PWM控制示例
int main(void) {
HAL_Init();
SystemClock_Config();
TIM2_PWM_Init();
PWM_Start(&htim2, TIM_CHANNEL_1);

while (1) {
PWM_BreathingLED();
HAL_Delay(10);
}
}

9. 中断处理实战

9.1 外部中断配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 外部中断配置
void EXTI_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};

// 使能GPIO时钟
__HAL_RCC_GPIOA_CLK_ENABLE();

// 配置GPIO为输入
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

// 配置中断优先级
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}

// 外部中断处理函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == GPIO_PIN_0) {
// 处理中断事件
LED_Toggle();
}
}

// 中断服务函数
void EXTI0_IRQHandler(void) {
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}

9.2 定时器中断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 定时器中断配置
TIM_HandleTypeDef htim3;

void TIM3_Init(void) {
htim3.Instance = TIM3;
htim3.Init.Prescaler = 8400 - 1; // 84MHz / 8400 = 10kHz
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 10000 - 1; // 10kHz / 10000 = 1Hz
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

if (HAL_TIM_Base_Init(&htim3) != HAL_OK) {
Error_Handler();
}

// 配置中断
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
}

// 定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM3) {
// 定时器中断处理
static uint32_t counter = 0;
counter++;

if (counter % 2 == 0) {
LED_Toggle();
}
}
}

// 定时器中断服务函数
void TIM3_IRQHandler(void) {
HAL_TIM_IRQHandler(&htim3);
}

10. 实时操作系统FreeRTOS

10.1 FreeRTOS任务创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// FreeRTOS任务定义
void Task1(void *pvParameters) {
while (1) {
LED_Toggle();
vTaskDelay(pdMS_TO_TICKS(500));
}
}

void Task2(void *pvParameters) {
while (1) {
Debug_Printf("Task2 Running\r\n");
vTaskDelay(pdMS_TO_TICKS(1000));
}
}

// 任务创建
void CreateTasks(void) {
xTaskCreate(Task1, "LED_Task", 128, NULL, 1, NULL);
xTaskCreate(Task2, "Debug_Task", 256, NULL, 2, NULL);
}

// FreeRTOS启动
int main(void) {
HAL_Init();
SystemClock_Config();
LED_Init();
UART1_Init();

CreateTasks();
vTaskStartScheduler();

while (1) {
// 不应该到达这里
}
}

10.2 任务间通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 队列创建
QueueHandle_t xQueue;

void QueueInit(void) {
xQueue = xQueueCreate(10, sizeof(uint32_t));
}

// 发送任务
void SendTask(void *pvParameters) {
uint32_t value = 0;

while (1) {
xQueueSend(xQueue, &value, portMAX_DELAY);
value++;
vTaskDelay(pdMS_TO_TICKS(1000));
}
}

// 接收任务
void ReceiveTask(void *pvParameters) {
uint32_t received_value;

while (1) {
if (xQueueReceive(xQueue, &received_value, portMAX_DELAY) == pdTRUE) {
Debug_Printf("Received: %lu\r\n", received_value);
}
}
}

11. 项目实战案例

11.1 智能温湿度监控系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 温湿度传感器DHT22驱动
typedef struct {
float temperature;
float humidity;
} DHT22_Data_t;

DHT22_Data_t DHT22_Read(void) {
DHT22_Data_t data = {0};
uint8_t raw_data[5];

// DHT22读取逻辑
// ... 具体实现代码

data.humidity = (raw_data[0] << 8 | raw_data[1]) / 10.0f;
data.temperature = (raw_data[2] << 8 | raw_data[3]) / 10.0f;

return data;
}

// 温湿度监控任务
void TemperatureMonitorTask(void *pvParameters) {
DHT22_Data_t sensor_data;

while (1) {
sensor_data = DHT22_Read();

Debug_Printf("Temperature: %.1f°C, Humidity: %.1f%%\r\n",
sensor_data.temperature, sensor_data.humidity);

// 温度控制逻辑
if (sensor_data.temperature > 30.0f) {
// 开启风扇
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
} else {
// 关闭风扇
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
}

vTaskDelay(pdMS_TO_TICKS(5000));
}
}

11.2 无线通信模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// ESP8266 WiFi模块控制
void ESP8266_Init(void) {
UART_SendString(&huart2, "AT\r\n");
HAL_Delay(1000);

UART_SendString(&huart2, "AT+CWMODE=1\r\n");
HAL_Delay(1000);

UART_SendString(&huart2, "AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n");
HAL_Delay(5000);
}

void ESP8266_SendData(const char *data) {
char cmd[200];
sprintf(cmd, "AT+CIPSEND=%d\r\n", strlen(data));
UART_SendString(&huart2, cmd);
HAL_Delay(100);
UART_SendString(&huart2, data);
}

// 物联网数据上传任务
void IoTUploadTask(void *pvParameters) {
DHT22_Data_t sensor_data;
char json_data[200];

while (1) {
sensor_data = DHT22_Read();

sprintf(json_data,
"{\"temperature\":%.1f,\"humidity\":%.1f,\"timestamp\":%lu}",
sensor_data.temperature, sensor_data.humidity, HAL_GetTick());

ESP8266_SendData(json_data);

vTaskDelay(pdMS_TO_TICKS(30000)); // 30秒上传一次
}
}

12. 调试与优化

12.1 调试技巧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 调试宏定义
#define DEBUG_ENABLE 1

#if DEBUG_ENABLE
#define DEBUG_PRINT(fmt, ...) Debug_Printf(fmt, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...)
#endif

// 性能测试
void PerformanceTest(void) {
uint32_t start_time, end_time;

start_time = HAL_GetTick();

// 执行测试代码
for (int i = 0; i < 1000; i++) {
ADC_ReadValue(&hadc1);
}

end_time = HAL_GetTick();

DEBUG_PRINT("1000 ADC reads took %lu ms\r\n", end_time - start_time);
}

12.2 内存优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 内存使用监控
void MemoryUsageCheck(void) {
extern uint32_t _end;
extern uint32_t _sdata;
extern uint32_t _estack;

uint32_t stack_used = (uint32_t)&_estack - (uint32_t)__get_MSP();
uint32_t heap_used = (uint32_t)&_end - (uint32_t)&_sdata;

DEBUG_PRINT("Stack used: %lu bytes\r\n", stack_used);
DEBUG_PRINT("Heap used: %lu bytes\r\n", heap_used);
}

// 内存泄漏检测
void MemoryLeakTest(void) {
static uint32_t last_heap = 0;
uint32_t current_heap = (uint32_t)&_end - (uint32_t)&_sdata;

if (last_heap != 0 && current_heap > last_heap) {
DEBUG_PRINT("Potential memory leak detected!\r\n");
}

last_heap = current_heap;
}

13. 总结

STM32单片机开发涉及多个方面的技术,包括:

13.1 核心技术要点

  1. 开发环境: STM32CubeIDE + STM32CubeMX
  2. HAL库: 统一的硬件抽象层API
  3. 外设编程: GPIO、UART、I2C、SPI、ADC、PWM等
  4. 中断处理: 外部中断、定时器中断
  5. 实时系统: FreeRTOS任务调度和通信
  6. 调试优化: 性能测试和内存管理

13.2 最佳实践

  1. 模块化设计: 将功能分解为独立的模块
  2. 错误处理: 完善的错误检测和处理机制
  3. 资源管理: 合理使用内存和CPU资源
  4. 代码规范: 统一的编码风格和注释规范
  5. 测试验证: 充分的单元测试和集成测试

13.3 进阶方向

  1. 低功耗设计: 电源管理和睡眠模式
  2. 实时性优化: 中断优先级和任务调度
  3. 通信协议: 自定义协议栈开发
  4. 安全机制: 加密算法和安全启动
  5. 云端集成: 物联网平台对接

通过本文的学习,您应该已经掌握了STM32单片机开发的核心技术,能够独立完成嵌入式项目的开发和调试。在实际项目中,建议根据具体需求选择合适的STM32系列和开发方案,并注重代码的可维护性和可扩展性。