RobinHou 发表于 2025-4-15 21:43:45

FreeRTOS结构下测量方波信号的问题

采用32G12K128 测量方波信号的频率,
裸奔的情况下,使用定时器和管脚中断就可以完成。
但在FreeRTOS的框架下面如果再突兀的使用这两个中断,
我设计的程序,FreeRTOS的任务调度会受到干扰。
程序会跑飞。请问有什么好的方案吗?

国芯人工智能 发表于 2025-4-15 21:48:00

在FreeRTOS框架下测量方波信号的频率时,确实需要特别注意中断与任务调度之间的协调,以避免系统不稳定或任务调度受到干扰。以下是一些建议和方案,帮助您在FreeRTOS环境下实现方波信号的频率测量。

1. 使用FreeRTOS的中断服务例程(ISR)机制
FreeRTOS提供了专门的中断服务例程(ISR)机制,允许在中断上下文中进行任务通知或信号量的操作,从而避免直接操作任务调度器。您可以在管脚中断服务例程中使用xTaskNotifyFromISR或xSemaphoreGiveFromISR来通知任务进行处理。

示例代码:
c
// 定义任务句柄和信号量
TaskHandlet xFrequencyTaskHandle;
SemaphoreHandlet xSemaphore;

// 管脚中断服务例程
void GPIOISR(void) {
    BaseTypet xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
    portYIELDFROMISR(xHigherPriorityTaskWoken);
}

// 频率测量任务
void vFrequencyTask(void pvParameters) {
    while (1) {
      if (xSemaphoreTake(xSemaphore, portMAXDELAY) == pdTRUE) {
            // 处理方波信号,计算频率
      }
    }
}

// 初始化函数
void vInit(void) {
    xSemaphore = xSemaphoreCreateBinary();
    xTaskCreate(vFrequencyTask, "FrequencyTask", configMINIMALSTACKSIZE, NULL, 1, &xFrequencyTaskHandle);
    // 配置管脚中断
}

2. 使用定时器中断与任务同步
在FreeRTOS中,定时器中断也可以与任务同步。您可以在定时器中断服务例程中通知任务进行处理,而不是直接在中断中处理复杂的逻辑。

示例代码:
c
// 定义任务句柄和信号量
TaskHandlet xTimerTaskHandle;
SemaphoreHandlet xTimerSemaphore;

// 定时器中断服务例程
void TIMERISR(void) {
    BaseTypet xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR(xTimerSemaphore, &xHigherPriorityTaskWoken);
    portYIELDFROMISR(xHigherPriorityTaskWoken);
}

// 定时器任务
void vTimerTask(void pvParameters) {
    while (1) {
      if (xSemaphoreTake(xTimerSemaphore, portMAXDELAY) == pdTRUE) {
            // 处理定时器中断,计算频率
      }
    }
}

// 初始化函数
void vInit(void) {
    xTimerSemaphore = xSemaphoreCreateBinary();
    xTaskCreate(vTimerTask, "TimerTask", configMINIMALSTACKSIZE, NULL, 1, &xTimerTaskHandle);
    // 配置定时器中断
}

3. 使用FreeRTOS的软件定时器
FreeRTOS提供了软件定时器功能,可以在任务上下文中处理定时事件,而不需要直接使用硬件定时器中断。您可以使用软件定时器来定期检查方波信号的状态,并计算频率。

示例代码:
c
// 定义软件定时器句柄
TimerHandlet xFrequencyTimer;

// 软件定时器回调函数
void vFrequencyTimerCallback(TimerHandlet xTimer) {
    // 检查方波信号状态,计算频率
}

// 初始化函数
void vInit(void) {
    xFrequencyTimer = xTimerCreate("FrequencyTimer", pdMSTOTICKS(100), pdTRUE, NULL, vFrequencyTimerCallback);
    xTimerStart(xFrequencyTimer, 0);
}

4. 优化中断优先级
在FreeRTOS中,中断优先级的管理非常重要。确保您的管脚中断和定时器中断的优先级设置合理,避免中断优先级过高导致任务调度器无法正常运行。通常,建议将中断优先级设置为低于或等于configMAXSYSCALLINTERRUPTPRIORITY,以确保FreeRTOS的API可以在中断中安全调用。

5. 使用任务通知代替信号量
任务通知是FreeRTOS提供的一种轻量级同步机制,比信号量更高效。您可以在中断服务例程中使用xTaskNotifyFromISR来通知任务进行处理。

示例代码:
c
// 定义任务句柄
TaskHandlet xFrequencyTaskHandle;

// 管脚中断服务例程
void GPIOISR(void) {
    BaseTypet xHigherPriorityTaskWoken = pdFALSE;
    xTaskNotifyFromISR(xFrequencyTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
    portYIELDFROMISR(xHigherPriorityTaskWoken);
}

// 频率测量任务
void vFrequencyTask(void pvParameters) {
    while (1) {
      ulTaskNotifyTake(pdTRUE, portMAXDELAY);
      // 处理方波信号,计算频率
    }
}

// 初始化函数
void vInit(void) {
    xTaskCreate(vFrequencyTask, "FrequencyTask", configMINIMALSTACKSIZE, NULL, 1, &xFrequencyTaskHandle);
    // 配置管脚中断
}

总结
在FreeRTOS框架下测量方波信号的频率时,应尽量避免在中断服务例程中直接处理复杂逻辑,而是通过任务通知、信号量或软件定时器等机制与任务进行同步。合理设置中断优先级,确保任务调度器能够正常运行。通过以上方法,可以有效避免程序跑飞或任务调度受到干扰的问题。

[本文内容由国芯人工智能辅助生成,仅供参考]

RobinHou 发表于 2025-4-16 20:51:27

国芯人工智能 发表于 2025-4-15 21:48
在FreeRTOS框架下测量方波信号的频率时,确实需要特别注意中断与任务调度之间的协调,以避免系统不稳定或任 ...

目前论坛上STC32G12K128的FreeRTOS 软件定时器和信号量的功能好像还没有移植好,我强行把软件定时器功能打开,运行出错。请问有没有具体的例程。
页: [1]
查看完整版本: FreeRTOS结构下测量方波信号的问题