This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] EK-LM4F120XL:处理相互影响的多个中断

Guru**** 1791630 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/569098/ek-lm4f120xl-handling-multiple-interrupts-affecting-each-other-correctly

器件型号:EK-LM4F120XL

大家好、我有以下设置:连接到 INT_GPIOC 和 INT_GPIOD  (左轮中断 C 和右轮中断 D)的轮编码器和 INT_TIMER2A 中断、自 INIT 起增加计数器的秒数。 目的是每次触发对应于轮编码器的中断时、它都会生成一条消息、其中包含 INIT 以来的时间以及有关轮侧和方向的信息、并通过 UART 转发发送。 问题是,在某些情况下,事件的时间戳似乎顺序错误,这种情况似乎是在定时器_interrupt_fires i.e 每次经过一秒时发生的(请参阅下面的示例序列)。 我怀疑这与相互重叠的中断相关、但我不确定如何解决它? 我还想将 UART 发送例程(serial_write_message)移至远离中断的主循环。 但是、在这种情况下、我应该阻止 GPIOC 和 GPIOD 中断在 serial_write_message_is 完成之前触发、但不要将它们松开、例如下面的内容、但我不确定是否可以在主代码中将中断排队等待执行时间? 如果有任何解决问题的建议、我将不胜感激。

伪代码通过 UART 在主代码中而非中断中发送消息:

while (1){

//flag 指示新消息
if (new_message){
//队列中断例程生成 new_message_string,直到将旧消息写入 UART (但不会释放中断)
BLOCK_GPIO_INTERRUPTS ();
//new_message_string 内容在中断例程中设置
serial_write_message (new_message_string); 
//可以接受来自中断的旧消息写入的新消息 UNBLOAD_GPIO_INTERRUPTS (); new_message = 0; }
损坏事件的示例序列

0 117.908203 0 1
0 117.956008 1 1.
0 117.960891 0 1
0 117.999351 1
0 118.4722 0 1.
0 118.56480 0 1
0 118.59448 1 1.
0 118.102294 0 1.
0 118.103828 1 1.
0 118.156608 0 1.
0 118.163978 1.
0 118.202339 0 1
0 118.206573 1 1.

生成和执行中断的实际代码:

静态空 init_interrupts (){

GPIOPinIntEnable (GPIO_PORTD_base、input1);
GPIOPinIntEnable (GPIO_PORTC_BASE、input2);
IntEnable (INT_GPIOD);
IntEnable (INT_GPIOC);
IntEnable (INT_TIMER2A);
TimerIntEnable (TIMER2_base、TIMER_TINA_TIMEOUT);
IntMasterEnable ();
TimerEnable (TIMER2_base、TIMER_A);

}

void system_time(){
TIMERIntClear (TIMER2_base、TIMER_TINA_TIMEOUT);
second_INIT = seconds_sine_init + 1;
}

void IntGPIOD (void){

if (!GPIOPinRead (GPIO_PORT_TIMEOUT) TIMEOUT = secreturn_HIGH;

}void INPUT



(GPIOD) 1和 INPUT (LOFT)+ INPUT (INTOP0) 1);INPUT (INTOPUR1 & INPUT (INTOP0)高电平) 0:1;
int wheel = 0;
int wheet_dir = 1;
char rower_direction = motor_get_direction ();

if (rower_dir='f'){
wheel_dir =
'b'){
wheel rowe_dir='0';
}else if (rowrowe_dir='l'){
wheel
='rand_dir
='0';}wheel ='randrowel_dir_dir_dir=0'


GPIOPinIntClear (GPIO_PORTD_base、input1);

float realtime = seconds_sine_init +(float)(SysCtlClockGet ()-1 - TimerValueGet (TIMER2_base、timer_A))/((float) SysCtlClockGet ());
char message[80]- TimerValueGet (TIMER2_base、timer_a)/((turel tel))/(%tlef
)/yclockGet (%tlef))、%tlef、%t&tlen、%tlef、%t&t
serial_write_message (message、message_len);
} 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Nippe、
    使中断例程尽可能短:只需记录所需的值、然后标记一个标志供以后处理。
    中断的频率是多少? 如果串行传输总是比下一个中断更快、则无需阻止它们。 如果情况并非如此、那么您会遇到不同的问题-您需要在内部处理某种信息、并仅传输"当前速度"或其他某种处理的数据。
    此外、在该论坛中搜索"PWM 计时器读数"或类似的内容-对于测量中断时间的技术、有两个冗长而富有启发性的讨论。
    此致
    布鲁诺
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、感谢您的回复。 我没有将大多数代码从中断例程移到主代码中(如下所示)。 但是我仍然遇到同样的现象、即每次新的秒开始时、前几个时间戳都不正确。 时间戳也被奇怪地截断,即数字的数量应为6,但在这些情况下,数字的数量为4 (有时为5)。  在大多数情况下,频率大于0.02秒。 我将尝试看看这些"PWM 时间读数"讨论、如果这些讨论可以提供一些解决问题的提示。

    采样时间戳:

    0 124.869972 1
    0 124.882019 1
    0 124.912612 0 1
    0 124.922569 1 1.
    0 124.963287 0 1.
    0 124.979240 1 1.
    0 125.4875 0 1
    0 125.15571 1 1
    0 125.53894 0 1
    0 125.72471 1 1
    0 125.97198 0 1
    0 125.108673 1 1
    0 125.148162 0 1
    0 125.161460 1
    0 125.189491 0 1
    0 125.194854 1
    0 125.241081 0 1
    0 125.252151 1
    0 125.282821 0 1
    0 125.284980 1
    0 125.332481 0 1

    主循环:

    while (1){
    
    if (sensors_encoder_updated ())}{
    float
    
    
    dir = sensors_get_seconds_sine_init ();struct EncoderState = sensors_get_encoder_state ();char message[80];int message_len = eb_sprintf (message、"%d %f %d %d %d\n"、0、realtime_heel、t.state);tWheel
    serial_write_message (message、message_len);
    sensors_clear_encoder_updated();
    }
    

    中断例程:

    void IntGPIOc (void){
    
    char rover_direction = motor_get_direction (void
    
    intheel_dir = 1);
    if (rover_direction ='b'|| rover_direction ='r'){
    tle_dir = 0;
    }
    
    encoder_state.dheel = 1;
    encoder_state.dheel = 1;encode_puttir_dir = tle_state_pidel_gio
    
    
    ;更新后的 GPIO_state.state.state.state1;pintc = pinar pinch
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    问题实际上发生在 EB_sprintf 函数中、与中断无关。 如果函数的输入类似于21.001212、则省略数字开头的零。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您分享问题、Nippe。
    出于多种原因、我避免使用文本进行这些数字值的传递-这就是其中之一。 通常容易出现转换错误、需要在传输前和接收后进行额外处理。 有时它不是一个选项(即、在解码 GPS NMEA 信息时)、然后您需要使用可靠的字符串转数字转换函数!
    谢谢
    布鲁诺