stm32cubmx创建freertos工程 超神波测距任务 oled显示任务 ,读取编码器任务
时间: 2025-06-29 07:13:32 浏览: 9
### 创建带有 FreeRTOS 的 STM32CubeMX 工程
为了创建一个包含超声波测距任务、OLED 显示任务和读取编码器任务的 STM32CubeMX FreeRTOS 工程,以下是详细的指导:
#### 1. 初始化项目并配置硬件资源
启动 STM32CubeMX 并选择目标 MCU 型号。按照向导提示输入项目名称和其他必要信息。
#### 2. 配置时钟树与时基
确保正确设置了系统时钟频率,并启用 SysTick 作为 systick 时基[^1]。
#### 3. 添加外设支持
##### 超声波传感器 (HC-SR04)
- **GPIO**: 设置触发脉冲输出引脚(TRIG)以及回响信号输入捕获引脚(ECHO)。通常 TRIG 是 GPIO 输出模式而 ECHO 则应被设定成外部中断或定时器通道用于捕捉上升沿下降沿事件。
- **TIMx 外部时钟模式** 或者 **EXTI 中断**
- 如果采用 TIMx,则需指定该定时器工作于输入捕获方式来测量高电平持续时间;如果选用 EXTI 方式则只需关注边沿触发条件下的回调处理函数实现。
##### OLED 屏幕
- **SPI/IIC 接口**: 根据所使用的 OLED 类型决定通信协议的选择。对于 IIC 设备而言,仅需定义 SDA 和 SCL 对应管脚即可;
- **软件组件库**: 寻找合适的图形界面库如 SSD1306 来简化编程复杂度。
##### 编码器接口
- **TIMx Encoder Interface Mode**
定义一对 GPIO 引脚连接至增量式旋转编码器 A/B 相位输出端子上,并将其关联给某个具备此特性的高级定时器实例,比如 TIM1, TIM8 等等。这允许直接利用内置硬件特性解码位置变化量。
```c
// 示例代码片段:初始化编码器模式
void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535; // 可根据需求调整周期值大小
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0;
if (HAL_TIM_Encoder_Init(&htim1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
```
#### 4. 启用 RTOS 支持
在中间件选项卡内勾选 "FreeRTOS" ,接着会弹出对话框询问是否自动添加必要的文件夹结构和服务例程——确认同意操作。
#### 5. 创建任务
针对上述三个主要功能分别建立独立的任务单元:
- `ultrasonic_task`: 执行距离探测流程并通过共享变量传递结果给其他部分使用。
- `display_task` : 更新显示屏上的数据显示内容。
- `encoder_read_task`: 实现对机械转动部件当前位置信息采集的功能逻辑。
```c
/* Task function prototypes */
static void UltrasonicTask(void *argument);
static void DisplayTask(void *argument);
static void EncoderReadTask(void *argument);
int main(void)
{
...
osThreadDef(UltraSonic_Task, UltrasonicTask, osPriorityNormal, 0, configMINIMAL_STACK_SIZE*2);
UltraSonicHandle = osThreadCreate(osThread(UltraSonic_Task), NULL);
osThreadDef(Display_Task, DisplayTask, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE);
DisplayHandle = osThreadCreate(osThread(Display_Task), NULL);
osThreadDef(Encoder_Read_Task, EncoderReadTask, osPriorityAboveNormal, 0, configMINIMAL_STACK_SIZE);
EncoderReadHandle = osThreadCreate(osThread(Encoder_Read_Task), NULL);
osKernelStart();
while (1){
;
}
}
/**
* @brief Periodically measures distance using ultrasonic sensor.
* @param argument: Not used
* @retval None
*/
static void UltrasonicTask(void const * argument)
{
for (;; )
{
// Implement measurement routine here...
vTaskDelay(pdMS_TO_TICKS(10)); // Adjust delay as needed
}
}
/**
* @brief Updates display with current data from other tasks.
* @param argument: Not used
* @retval None
*/
static void DisplayTask(void const * argument)
{
for (;; )
{
// Update the screen content based on shared variables...
vTaskDelay(pdMS_TO_TICKS(100));
}
}
/**
* @brief Reads encoder position and updates global variable.
* @param argument: Not used
* @retval None
*/
static void EncoderReadTask(void const * argument)
{
int32_t lastCountValue;
for (;; )
{
lastCountValue = __HAL_TIM_GET_COUNT(&htim1); // Assuming TIM1 is configured in encoder mode
// Process count value to determine direction/speed etc.
vTaskDelay(pdMS_TO_TICKS(1)); // Shorter period due to real-time nature of this task
}
}
```
阅读全文