当前位置: 首页 > news >正文

FOC控制原理7-源码解析2-系统滴答定时器中断

1、基础框图

中断执行逻辑

19. ST FOC MC SDK5.x电机控制软件框架 — [野火]电机应用开发实战指南—基于STM32 文档 (embedfire.com)

中断频率由低到高分别为:霍尔传感器中断->SysTick中断->ADC采样中断

                                            速度捕获->状态机->采样FOC控制

 2、中断代码讲解

(1)滴答定时器中断---(2kHz)电机控制任务(1kHz)时基信号用于HAL库

/*** 函数功能: 系统滴答定时器中断* 输入参数: 无* 返 回 值: 无* 说    明: 2Khz,执行电机控制任务,同时生成1Khz的时基用于HAL库*/
void SysTick_Handler(void)
{static uint8_t SystickDividerCounter = SYSTICK_DIVIDER;if (SystickDividerCounter == SYSTICK_DIVIDER){HAL_IncTick();HAL_SYSTICK_IRQHandler(); // 1Khz(1ms)的时基SystickDividerCounter = 0;}SystickDividerCounter ++;  MC_RunMotorControlTasks(); //2kHz 状态机:电机调度 中频任务
}

这段代码是一个用于处理系统滴答定时器(SysTick)中断的函数 SysTick_Handler。SysTick 是一个24位倒计时定时器,通常用于提供系统的基准时钟信号,广泛应用于嵌入式系统中。这段代码的目的是在每秒2000次(2kHz)的频率下执行电机控制任务,同时生成一个每秒1000次(1kHz)的时基信号用于HAL库。

代码细节解释:

  1. 函数声明:

    void SysTick_Handler(void)
    
    • SysTick_Handler 是 SysTick 定时器中断的服务程序(ISR)。当 SysTick 定时器倒计时到0时,系统会自动调用这个函数。
  2. 静态变量 SystickDividerCounter:

    static uint8_t SystickDividerCounter = SYSTICK_DIVIDER;
    
    • SystickDividerCounter 是一个静态变量,用于分频计数。SYSTICK_DIVIDER 是一个预定义的常量,通常是2,用于将2kHz的时钟信号分频为1kHz。
  3. 分频逻辑:

    if (SystickDividerCounter == SYSTICK_DIVIDER)
    {HAL_IncTick();HAL_SYSTICK_IRQHandler(); // 1Khz(1ms)的时基SystickDividerCounter = 0;
    }
    SystickDividerCounter ++;
    
    • 每次进入 SysTick_Handler 函数时,都会检查 SystickDividerCounter 是否等于 SYSTICK_DIVIDER
    • 如果相等,说明已经经过了足够的时钟周期(2个2kHz周期,即1ms),此时会调用 HAL_IncTick() 和 HAL_SYSTICK_IRQHandler() 来更新 HAL 库的时基,并将 SystickDividerCounter 重置为0。
    • 如果 SystickDividerCounter 不等于 SYSTICK_DIVIDER,则只是简单地将 SystickDividerCounter 加1。
  4. 电机控制任务:

    MC_RunMotorControlTasks(); //2kHz 状态机:电机调度 中频任务
    
    • 在每次进入 SysTick_Handler 函数时,都会调用 MC_RunMotorControlTasks() 函数,执行电机控制任务。这个任务是以2kHz的频率运行的,即每秒2000次。

总结:

  • SysTick_Handler 函数以2kHz的频率被调用。
  • 通过 SystickDividerCounter 变量,每2个2kHz周期(即1ms)生成一个1kHz的时基信号,用于 HAL 库的计时。
  • 每次调用 SysTick_Handler 时,都会执行一次电机控制任务 MC_RunMotorControlTasks(),确保电机控制任务以2kHz的频率运行。

这段代码的核心思想是利用 SysTick 定时器的高频率中断来同时处理高频的电机控制任务和生成低频的时基信号。

HAL 库(Hardware Abstraction Layer,硬件抽象层)是 STM32 微控制器系列中提供的一个软件包,旨在简化对硬件的访问和控制,提供了一种与处理器内核和具体硬件相对独立的编程接口。在 HAL 库中,定时器功能是其重要的一部分,而 HAL_IncTick 和 HAL_SYSTICK_IRQHandler 函数则与系统的时基管理密切相关。

----------------------------------------------------------------------------------------------------------------------------

HAL 库计时的作用

  1. 时间测量

    • 通过 SysTick 定时器生成一个定期中断,每次中断时调用 HAL_IncTick 函数递增一个全局时间变量(通常是 uwTick),从而实现对时间的测量。这可以用于延时函数、时间戳记录等场景。
  2. 延时功能

    • HAL 库提供了一些基于时基的延时函数,如 HAL_Delay,它通过查询 uwTick 变量来实现毫秒级的延时。
  3. 定时功能

    • 在许多应用中,需要定期执行某些任务,如传感器数据采集、状态监控等。通过 SysTick 定时器的中断,可以实现这些定时任务的调度。
  4. 系统功能

    • HAL 库中的一些功能,如 USB、CAN 等通信协议的实现,可能依赖于精确的时基来确保协议的正确执行。
  5. RTOS 支持

    • 如果系统中运行了实时操作系统(如 ARM 的 CMSIS-RTX),SysTick 定时器常被用作操作系统的时间基准,用于任务调度、信号量处理等。

工作原理

  • SysTick 定时器配置

    • SysTick 定时器通常被配置为每1毫秒(1kHz)产生一次中断,这一中断频率是通过系统时钟分频得到的。例如,如果系统时钟为16MHz,可以通过设置 SysTick 定时器的重载值为16000来实现1ms的中断周期。
  • 中断服务程序

    • 在 SysTick 定时器中断服务程序中,调用 HAL_IncTick 函数递增 uwTick 变量,该变量通常是一个32位的无符号整数,表示自系统启动以来经过的毫秒数。
  • 时间相关的函数

    • HAL_Delay 函数通过查询 uwTick 变量,在达到指定延时时间时返回。
    • HAL_GetTick 函数返回当前的 uwTick 值,用于获取时间戳或计算时间差。

示例代码

以下是一个简单的 SysTick_Handler 函数示例,展示了如何使用 SysTick 定时器来生成1kHz的时基:

void SysTick_Handler(void)
{HAL_IncTick();HAL_SYSTICK_IRQHandler();
}uint32_t HAL_GetTick(void)
{return uwTick;
}void HAL_Delay(uint32_t Delay)
{uint32_t tickstart = HAL_GetTick();uint32_t wait = Delay;if ((tickstart + wait) < tickstart) {while ((HAL_GetTick() < (uint32_t)(MAX_DELAY - wait)) || ((HAL_GetTick() >= tickstart) && (HAL_GetTick() < (tickstart + wait))));} else {while ((HAL_GetTick() < (tickstart + wait)));}
}

在这段代码中:

  • HAL_IncTick 用于递增 uwTick 变量。
  • HAL_GetTick 返回当前的 uwTick 值。
  • HAL_Delay 通过循环等待,直到 uwTick 达到预期的延时时间。

总之,HAL 库的计时功能为开发者提供了方便的时间管理工具,使得在嵌入式系统中实现定时和延时操作更加简单和可靠。

(2)电机控制调度

/*** 函数功能: 电机控制调度* 输入参数: 无* 返 回 值: 无* 说    明: 执行中等频率任务,调用该函数频率是2KHz*/
void MC_Scheduler(void)
{if (bMCBootCompleted == 1){    if(hMFTaskCounterM1 > 0u){hMFTaskCounterM1--; // 中频计数器}else{TSK_MediumFrequencyTaskM1();// 执行中等频率的任务hMFTaskCounterM1 = MF_TASK_OCCURENCE_TICKS;// 计数器复位}if(hBootCapDelayCounterM1 > 0u){hBootCapDelayCounterM1--;  // 自举电容充电时间}if(hStopPermanencyCounterM1 > 0u){hStopPermanencyCounterM1--;// 状态机STOP的持续时间}}
}

这段代码是一个电机控制调度函数 MC_Scheduler,用于在中等频率下执行电机控制相关的任务。调用该函数的频率是2kHz(每秒2000次)。下面是对这段代码的详细解释:

代码功能概述

  • 函数功能:电机控制调度,执行中等频率的任务。
  • 调用频率:2kHz,即每秒调用2000次。
  • 主要任务:触发中等频率的任务(TSK_MediumFrequencyTaskM1),并管理一些计数器,用于延时或状态控制。

代码详细解释

  1. 函数声明:

    void MC_Scheduler(void)
    
    • MC_Scheduler 函数是一个无参数、无返回值的函数,主要负责电机控制的调度任务。
  2. 启动完成标志检查:

    if (bMCBootCompleted == 1)
    
    • bMCBootCompleted 是一个布尔类型的标志变量,表示电机控制的启动阶段是否已经完成。
    • 如果 bMCBootCompleted 为1(启动完成),则执行电机控制相关的任务。否则,不执行任何操作。
  3. 中等频率任务调度:

    if(hMFTaskCounterM1 > 0u)
    {hMFTaskCounterM1--; // 中频计数器
    }
    else
    {TSK_MediumFrequencyTaskM1(); // 执行中等频率的任务hMFTaskCounterM1 = MF_TASK_OCCURENCE_TICKS; // 计数器复位
    }
    
    • hMFTaskCounterM1 是一个计数器变量,用于控制中等频率任务的执行间隔。
    • 如果 hMFTaskCounterM1 大于0,说明还未到达执行任务的时间,因此将其减1。
    • 如果 hMFTaskCounterM1 减到0,则调用 TSK_MediumFrequencyTaskM1() 函数,执行中等频率的电机控制任务。
    • 执行完任务后,将 hMFTaskCounterM1 重新设置为 MF_TASK_OCCURENCE_TICKS,即复位计数器,等待下一个周期。
  4. 自举电容充电时间管理:

    if(hBootCapDelayCounterM1 > 0u)
    {hBootCapDelayCounterM1--;  // 自举电容充电时间
    }
    
    • hBootCapDelayCounterM1 是一个计数器,用于控制自举电容充电的时间。
    • 如果 hBootCapDelayCounterM1 大于0,说明自举电容还在充电过程中,因此将其减1。
    • 如果减到0,说明充电完成,后续可能会进入其他状态(例如启动电机等)。
  5. 状态机STOP的持续时间管理:

    if(hStopPermanencyCounterM1 > 0u)
    {hStopPermanencyCounterM1--; // 状态机STOP的持续时间
    }
    
    • hStopPermanencyCounterM1 是一个计数器,用于控制状态机在STOP状态的持续时间。
    • 如果 hStopPermanencyCounterM1 大于0,说明状态机还需要保持在STOP状态,因此将其减1。
    • 如果减到0,说明STOP状态的持续时间已结束,后续可能会进入其他状态(例如启动电机等)。

总结

  • 中等频率任务调度
    • 通过 hMFTaskCounterM1 计数器控制中等频率任务的执行时间,任务的执行频率由 MF_TASK_OCCURENCE_TICKS 决定。
  • 自举电容充电时间管理
    • 通过 hBootCapDelayCounterM1 计数器管理自举电容的充电时间,确保在充电完成后再进行下一步操作。
  • 状态机STOP的持续时间管理
    • 通过 hStopPermanencyCounterM1 计数器管理状态机在STOP状态的持续时间,确保在规定时间内保持STOP状态。

这段代码的核心是通过计数器来实现时间控制,确保电机控制任务在合适的时间点执行,并且能够管理一些延时任务(如自举电容充电和状态机持续时间)。


http://www.mrgr.cn/news/82208.html

相关文章:

  • MySQL使用记录
  • K8s高可用集群之Kubernetes集群管理平台、命令补全工具、资源监控工具部署、常用命令
  • C# 设计模式(创建型模式):建造者模式
  • VS2015中使用boost库函数时报错问题解决error C4996 ‘std::_Copy_impl‘
  • 如何在Windows / Mac / Android上查看 HEIC 图像
  • libaom 源码分析线程结构
  • 使用ebooklib制作符合epub3规范的epub文件
  • C++语言编程————C++数据类型
  • 解决virtualbox克隆ubuntu虚拟机之后IP重复的问题
  • java Redisson 实现限流每秒/分钟/小时限制N个
  • 【复刻】ESG表现对企业价值的影响机制研究(2009-2021年)
  • 一、VxLAN 简介
  • 旷视科技Java面试题及参考答案
  • NRF24L01模块通信实验
  • 日期时间选择(设置禁用状态)
  • linux系统安装搭建chrony(ntp)时间同步服务器
  • git使用指南-实践-搭建git私服
  • 数据仓库中的指标体系模型介绍
  • Frontend - 分页(针对 python / Django )
  • 用Python操作字节流中的Excel工作簿
  • SpringCloud源码分析-Ribbon与LoadBalancer
  • python实现自动登录12306抢票 -- selenium
  • Yolo11改进策略:注意力改进|Neck层改进|SCSA,探索空间与通道注意力之间的协同效应|即插即用
  • 【Rust自学】9.2. Result枚举与可恢复的错误 Pt.1:match、expect和unwrap处理错误
  • 【Rust自学】9.1. 不可恢复的错误以及panic!
  • 【Rust自学】8.6. HashMap Pt.2:更新HashMap