STM32μC:SysTick延迟在中断处理程序中不起作用

Mar*_*cel 1 c microcontroller stm32 stm32f1

所以我STM32F103C8T6用C语言编写了一个微控制器程序,使用RTC(实时时钟)和显示模块.

RTC和显示都工作正常,但是当我尝试从RTC中断处理程序内部更新显示时,它不起作用.

当我从内部向显示器写东西时main(),它工作得很好.

中断处理程序也可以工作,所以我认为问题在写入显示的函数中.

此功能使用小延迟来与显示控制器进行通信.

我以前使用SysTick过来生成这样的延迟:

void delay(uint32_t n){
    uint32_t start =  systick_count;
    while (systick_count - start < n);
    return;
}
Run Code Online (Sandbox Code Playgroud)

但不知何故,在RTC的中断处理程序中,它不起作用.所以我用这个替换了我的延迟函数,而不是使用SysTick:

for (; i>0; i--) {
    for (int j = 0; j < 72; ++j) {
        __asm__ __volatile__("nop\n\t":::"memory");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在一切正常.

我试图理解,为什么SysTick显然在RTC中断处理程序内不起作用.

我想这可能是由中断优先级引起的,但根据数据表,默认情况下,SysTick Interrupt优先级高于RTC中断优先级.

也许有人可以解释,为什么会这样?

编辑1:好的,所以我已经阅读了更多关于中断优先级的内容,似乎我需要正确配置NVIC_IRQChannelPreemptionPriority.我会尽快尝试这个...

关于中断内部的延迟,我知道这不是正确的方法,但我仍然想了解程序的行为

EDIT2:我刚刚尝试通过以下方式更改中断优先级:

// set RTC interrupt priority to 15 (lowest)
NVIC_SetPriority(RTC_IRQn, 15);
// set interrupt priority of SysTick to 0 (highest)
NVIC_SetPriority(SysTick_IRQn, 0);
Run Code Online (Sandbox Code Playgroud)

现在SysTick延迟在RTC中断处理程序中工作.

Jac*_*mok 5

使用SysTick实现延迟的方法与HAL_Delay来自ST的HAL库相同.它的工作方式是SysTick不断增加(通常以1ms为间隔)一个变量 - systick_count在你的情况下 - 在你的情况下与延迟函数内的局部变量进行比较start.

这里有两点需要注意:

  1. systick_count需要变得不稳定,以便在每次比较之前强制重新读取其值.它被中断修改而不是在该函数内部.您的编译器可能会选择优化此部分代码.

  2. 调用延迟功能时,SysTick中断需要"运行".如果它不是因为你处于更高优先级(数值更低)的中断,那么你处于死锁状态并且延迟功能永远不会完成,因为计数器永远不会被从未发生的SysTick增加.关于这一点 - 不要假设事情,只依赖于数据表.继续实际验证它是否在延迟时运行.在调用延迟函数时检查NVIC寄存器值,或者只是在处于RTC中断时在SysTick中设置断点 - 它应该在您处于延迟功能时触发该断点.如果不是 - 您可能需要调整中断优先级.

关于延迟中断的整个想法 - 通常被认为是不好的做法.中断应该用于非常快速地完成非常小的工作,例如设置一个标志,表明需要在主程序代码中完成某些操作,或者将接收到的字节放入队列中以便以后处理.虽然在一个只有一个中断的简单程序中可能看起来不太明显(如果你计算Systick就会有两个中断),一旦你添加更多中断就会很快出现问题,并且会遇到诸如丢失信息之类的问题,因为你的中断会阻塞每个中断另外,他们没有得到足够快的调用.