Timer 使用ARM 32位定时器中断的意外串行通信

Timer 使用ARM 32位定时器中断的意外串行通信,timer,embedded,uart,serial-communication,baud-rate,Timer,Embedded,Uart,Serial Communication,Baud Rate,我的代码是用于串行通信和使用定时器中断的led闪烁,其中led以固定的时间间隔切换,在串行终端上有一些行打印,对于固定时间,我使用定时器 情景: 我在串行终端上以连续方式“while”发送数据,当计时器过期时,中断发生,我的led再次切换到终端上的串行数据“红色led闪烁500毫秒”。理想情况下,只有在计时器过期时才调用此计时器函数,其余时间我的while循环应该执行,while循环数据应该打印在终端上。 但这并没有发生,连载印刷品并不像它应该印刷的那样 让我知道这背后的真正原因是什么 我改变了

我的代码是用于串行通信和使用定时器中断的led闪烁,其中led以固定的时间间隔切换,在串行终端上有一些行打印,对于固定时间,我使用定时器

情景:

我在串行终端上以连续方式“while”发送数据,当计时器过期时,中断发生,我的led再次切换到终端上的串行数据“红色led闪烁500毫秒”。理想情况下,只有在计时器过期时才调用此计时器函数,其余时间我的while循环应该执行,while循环数据应该打印在终端上。 但这并没有发生,连载印刷品并不像它应该印刷的那样

让我知道这背后的真正原因是什么

我改变了波特率(115200到9600),输出非常相似。 但如果你只打印“w”而不是“while”,那么行为也类似,但定时器“红色LED闪烁500毫秒”打印2次。 不清楚计时器在哪里忙着执行此行为

下面是我的代码:

define d9 "while\r\n"

int main(void) {

//Serial Communication Inilization done
//Timer Initialization done

    while (1) 
    {
        // This line prints continuously on the terminal 
        LPUART_DRV_SendDataPolling(INST_LPUART1, (uint8_t *) d9, strlen(d9));
    }
} 
实际产量:

...
while
while
while
wRED LED blinked for 500 ms
hRED LED blinked for 500 ms
iRED LED blinked for 500 ms
lRED LED blinked for 500 ms
eRED LED blinked for 500 ms
while
while
...
预期产出:

...
while
while
while
RED LED blinked for 500 ms
while
while
...

您提供的实际输出显示字符串“红色LED闪烁500毫秒”(=:“ISR字符串”)在“(=:“主循环字符串”)中断该字符串的同时中断该字符串

它使用单调的频率(在两次调用之间留下主循环字符串的单个字符),这与重载计时器和主循环内的单调行为完全匹配

这有力地支持了@markus nm和@Chris Stratton的两条评论的假设(我几乎会说,“它证明了…”),即您存在并发问题

他们的提示是正确的-最简单的解决方案是在访问全局资源之前获得互斥(或简化:禁用中断),在全局资源中合并两个数据源。并发问题产生的资源可能是RAM中的缓冲区,甚至是UART端口寄存器本身。如果您还不熟悉并发编程,请注意,在没有经验或背景知识的情况下,在整个系统的功能周围添加更多的互斥时,不要遇到同步/死锁问题


解决并发问题的一个更强大(但更复杂)的解决方案是使用RTOS,将其他上下文发送到其输入队列的小任务只输出到UART。然后,RTOS负责并发性。但是,此策略的任何细节都超出了您的问题范围。

盲目猜测:您的sendData函数实际上不发送任何数据,而是将其放入缓冲区。当第一个事务尚未完成时,此缓冲区机制不知道它可能被中断,并具有另一个函数输入数据。您可以尝试在写入缓冲区时禁用全局中断来测试这一点。您不能这样做。您需要代码的一部分来“拥有”UART的发送功能,并且需要将所有内容都通过UART传输。无论如何,在ISR中发起和发送多字符消息是个坏主意。很可能您应该做的是在ISR中设置一个volatile标志,然后检查该标志,并在主循环中发送消息,在主循环中消息可以放在其他输出之间。如果您确实有一个ISR管理软件发送缓冲区,它一次只能移动硬件可以接受的数据字节数,而不是代表它自己“说话”。顺便说一句,如果您想调试ISR,通常最好切换GPIO并使用示波器或便宜的sigrok兼容USB的逻辑分析仪观看。让我尝试上述两种方法,非常感谢@markus nm