第196集STM32单片机开发与嵌入式系统实战
|字数总计:3.3k|阅读时长:16分钟|阅读量:
1. STM32单片机概述
STM32是意法半导体(STMicroelectronics)推出的基于ARM Cortex-M内核的32位微控制器系列,具有高性能、低功耗、丰富外设等特点,广泛应用于工业控制、消费电子、物联网等领域。本文将详细介绍STM32开发环境搭建、HAL库使用、外设编程以及实际项目开发。
1.1 STM32系列特点
- 高性能: ARM Cortex-M内核,主频可达400MHz
- 低功耗: 多种低功耗模式,适合电池供电应用
- 丰富外设: GPIO、UART、SPI、I2C、ADC、DAC、定时器等
- 开发友好: 完善的开发工具链和HAL库支持
- 生态丰富: 大量第三方库和开发板支持
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
|
1. 下载对应操作系统的安装包 2. 运行安装程序 3. 选择安装路径和组件 4. 配置工作空间
|
2.2 STM32CubeMX配置
1 2 3 4 5 6
| 1. 选择MCU型号 2. 配置系统时钟 3. 配置外设参数 4. 生成初始化代码 5. 导出到IDE项目
|
2.3 HAL库介绍
HAL(Hardware Abstraction Layer)库是STM32官方提供的硬件抽象层,提供统一的API接口。
1 2 3 4 5 6 7 8
| #include "stm32f4xx_hal.h" #include "stm32f4xx_hal_gpio.h" #include "stm32f4xx_hal_uart.h" #include "stm32f4xx_hal_i2c.h" #include "stm32f4xx_hal_spi.h" #include "stm32f4xx_hal_adc.h" #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
| typedef struct { uint32_t Pin; uint32_t Mode; uint32_t Pull; uint32_t Speed; uint32_t Alternate; } GPIO_InitTypeDef;
#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
| #include "main.h"
#define LED_PIN GPIO_PIN_13 #define LED_PORT GPIOC
void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOC_CLK_ENABLE(); 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); }
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); } }
|
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) { 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
| typedef struct { USART_TypeDef *Instance; 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_HandleTypeDef *hdmarx; HAL_LockTypeDef Lock; __IO HAL_UART_StateTypeDef gState; __IO HAL_UART_StateTypeDef RxState; __IO uint32_t ErrorCode; } UART_HandleTypeDef;
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
| 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); }
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_HandleTypeDef hi2c1;
void I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; 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
| 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); }
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); }
#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_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
| 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); }
HAL_StatusTypeDef SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) { return HAL_SPI_Transmit(hspi, pData, Size, HAL_MAX_DELAY); }
HAL_StatusTypeDef SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) { return HAL_SPI_Receive(hspi, pData, Size, HAL_MAX_DELAY); }
#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_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(); } 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
| 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; }
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); }
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
| TIM_HandleTypeDef htim2;
void TIM2_PWM_Init(void) { TIM_OC_InitTypeDef sConfigOC = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 84 - 1; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 1000 - 1; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) { Error_Handler(); } 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
| 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); }
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); }
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}; __HAL_RCC_GPIOA_CLK_ENABLE(); 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; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 10000 - 1; 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
| 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); }
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
| 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]; 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
| 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)); } }
|
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 核心技术要点
- 开发环境: STM32CubeIDE + STM32CubeMX
- HAL库: 统一的硬件抽象层API
- 外设编程: GPIO、UART、I2C、SPI、ADC、PWM等
- 中断处理: 外部中断、定时器中断
- 实时系统: FreeRTOS任务调度和通信
- 调试优化: 性能测试和内存管理
13.2 最佳实践
- 模块化设计: 将功能分解为独立的模块
- 错误处理: 完善的错误检测和处理机制
- 资源管理: 合理使用内存和CPU资源
- 代码规范: 统一的编码风格和注释规范
- 测试验证: 充分的单元测试和集成测试
13.3 进阶方向
- 低功耗设计: 电源管理和睡眠模式
- 实时性优化: 中断优先级和任务调度
- 通信协议: 自定义协议栈开发
- 安全机制: 加密算法和安全启动
- 云端集成: 物联网平台对接
通过本文的学习,您应该已经掌握了STM32单片机开发的核心技术,能够独立完成嵌入式项目的开发和调试。在实际项目中,建议根据具体需求选择合适的STM32系列和开发方案,并注重代码的可维护性和可扩展性。