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.

[参考译文] TM4C123GH6PM:Tivaware 计时器中的中断永不运行

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/691206/tm4c123gh6pm-interrupt-in-tivaware-timer-never-runs

器件型号:TM4C123GH6PM
主题中讨论的其他器件: TM4C123AH6PMTM4C129ENCPDT

大家好。 我目前正在使用 TIvaware 中的 timer.c、并构建了一个代码来将其用于超声波传感器。  我的问题是、我的中断永远不会被呼叫。  我将包含我的部分代码、希望有人能帮我解决问题。  提前感谢。  

信息: 我正在使用 Timer1、因此我使用 PF2和 PF3。 程序不断被占用 while flagB 循环、并且永远不会退出、因为中断 TIMER1BHANDLER 永远不会运行、因此 flagB 不会更新为1。   

#include "timer.h"#include

#include "tm4c123ghp6.h"
#include "interrupt.h"
#include "sysctl.h"

#define Timer1 0x40031000
#define perodo 62.5

#define echo 0x04 //PF2
#define TRIG 0x08 //pF3

uint8_t flagB;

void ConfigGPIO (void){
SYSCTL_RCGCGPIO_R |= 0x20;
while (!(SYSCTL_PRGPIO_R 和0x20));

GPIO_PORTF_DIR_|= TRIG;
GPIO_PORTF_DIR_R &=~μ s (回波);

GPIO_PORTF_AFSEL_R |=(TRIG|ECHO);
GPIO_PORTF_PCTL_R |=(GPIO_PORTF_PCTL_R 和0xFFFFFF")| 0x7700;
GPIO_PORTF_AMSEL_R &=~Ω(ECHO|TRIG);
GPIO_PORTF_DEN_R ||(ECHO|TRIG);

}

void ConfigHCSR04 (void){

SysCtlPeripheralEnable (SYSCTL_Periph_Timer1);
while (!SysCtlPeripheralReady (SYSCTL_Periph_Timer1));

TimerDisable (Timer1、timer_both);

//(T1CCP0连接回波。)
TimerConfigure (Timer1、(TIMER_CFG_SPLIT_PAGE|TIMER_CFG_A_CAP_TIME|TIMER_CFG_B_ONE_SHOT));
TimerControlEvent (Timer1、timer_A、timer_event_both _edge);
TimerControlEvent (Timer1、timer_B、timer_event_NEG_EDGE);

TimerIntEnable (Timer1、(TIMER_CAP_EVENT|TIMER_TIMB_TIMEOUT));
TimerIntRegister (Timer1、timer_A、Timer1AHandler);
TimerIntRegister (Timer1、Timer_B、Timer1BHandler);

IntMasterEnable();
IntEnable (INT_TIMER1B);
IntEnable (INT_TIMER1A);

//TimerA 24位。 TimerB 16位。
TimerPrescaleSet (Timer1、Timer_A、0xFF);
TimerLoadSet (Timer1、timer_A、0xFFFF);
TimerLoadSet (Timer1、timer_B、(10000/周期数));// 10 us 内超时

TimerEnable (Timer1、timer_A);

}

void Timer1BHandler (void){
GPIO_PORTF_DATA_R &=~Ω(TRIG);
TimerIntClear (Timer1、TIMER_TIMB_TIMEOUT);
flagB = 1;
}

void main (void){
ConfigHCSR04();
ConfigGPIO();

while (1){
如果(!(GPIO_PORTF_DATA_R 和 ECHO)){// Si no estoy haciendo medicion entones emito ultrasonido。
GPIO_PORTF_DATA_R |= TRIG;
TimerEnable (Timer1、Timer_B);
while (!flagB);
标志 B = 0;
}
} 

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

    您好 Richard、

    如果您将 DRM 代码和 TivaWare 代码组合在一起、则很难说出可能发生的情况。

    我第一眼看到的一些内容:

    1) 1)我看不到 SysCtlPeripheralEnable 调用或与其类似的东西。

    SysCtlPeripheralEnable (SYSCTL_Periph_Timer1); 

    2) 2)您有 TimerIntEnable、但没有全局中断使能调用

    IntMasterEnable();
    IntEnable (INT_TIMER1B); 

    3) 3)您已经设置了计时器1A 和1B、并且为它们启用了中断、但我只看到一个 ISR。

    4) 4)不清楚您是否已将 ISR 正确添加到 startup_ccs.c 文件中、因此也请确保这样做。

    5) 5)我看不到您的 GPIO 配置代码、因此请确保您也有一个 SysCtlPeripheralEnable 调用。

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

    您好、首先感谢您抽出时间回答我的问题。 我肯定没有包括全局中断使能调用、因为我不知道需要。 这些函数是否都是我需要从 interrupt.c 中包含的函数? 很抱歉、我对中断并不是很熟悉。 无论如何、我现在已经将它们包括在内。

    我按照您的建议将激活时钟到 SysCtlPeripheral 中的 DMR 更改为。 (虽然我认为它们是相同的)。
    在 startup_ccs.c 文件中、我在"由用户添加"一节下声明了两个 ISR (我只在这个线程中的 TimerB 上包含了我的 ISR)和 extern。 之后、我在 DATA_SECTION 的相应段中包含了它们的名称。

    我已通过 DMR 配置 GPIO。 在所有这些之后、我的问题仍然存在:flagB 永远不会变为1。 我还有什么要做的吗? 再次感谢!

    如果我在线程中编辑了我的代码并包含了我的 GPIO 配置、 那么如果您有一些时间、请查看它。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我想提一下 DRM ...

    您的代码包括:#include "tm4c123ghp6.h"

    这是一个在不久的过去对我们来说有点小的错误。 我们的源代码中有类似的 include、一切都很棒、除了我们有适用于多个电路板的相同代码库、包括多个不同的 TM4C 器件、例如 TM4C129ENCPDT、TM4C123AH6PM 等 我们不知道(我们忘记了)、我们在代码中的某个位置包含了"tm4c129encpdt.h"。 当我们为 TM4C123AH6PM 编译该代码库时、使用了 TM4C129ENCPDT 的一些映射、这会导致中断不触发以及其他非常吸引人且非常有害的副作用。

    因此、要么不包含特定于器件的标头、要么如果必须、然后在包含的周围放置 ifdef 防护、以确保仅在定义了符号 PART_TM4C123GH6PM 时才包含该保护。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Richard、

    如果您在调试器中暂停代码、代码位于何处? 我想了解它是否位于用于捕获错误的任何 ISR 中。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你(们)好。 它永远被吸入 while (!flagB)循环。  我会玩它、等待片刻、然后停下来、因为我的旗杆 B 永远不会变为1。

    感谢12点12分的推荐。 如果有必要、我将在未来的项目中考虑标头防护。

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

    " 如果必须、则将 ifdef 防护装置放置在包括的周围。。"

    TI 实际上提供了这样一个文件、该文件是使用 CMSIS 的发行版: github.com/.../CMSIS-framework-for-TM4-devices

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

    您可能不想使用它。 相反、我会依赖器件头文件。

    1)我会检查寄存器以确保1)定时器正在运行;2)中断被启用;3)如果需要、矢量表为您的 ISR 提供了正确的地址-在 driverlib 下、您将需要注册 ISR。

    我还想翻转 ISR 中的一个引脚、使其更加显式。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好。 我再次非常具体地检查了所有内容、并希望分享我知道的内容:

    计时器运行正常。  timerB RIS 也会激活。   中断 NVIC_EN0寄存器显示两个 Timer1定时器均已启用。  (我不知道 NVIC、但检查了数据表以找出与 Timer1计时器相对应的数字。)   当我进入 TimerEnable (Timer1、Timer_B)时。   定时器确实会在 RIS 标志被切换时运行。  但是、它会中等地跳转到 while (!flagB)、并且永远不会转到 Timer1BHandler ISR。  我还看到 NVIC_Pend0中有4个、即 timerB。   我认为这说明 ISR 未正确注册。   每个定时器的中断屏蔽位被正确设置为1。  

    是否可以有人指导我如何正确设置 ISR? 我所做的就是我在 startup_ccs.c 和使用 TimerIntRegister()中所说的那样。  感谢每个人再次帮助我。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请查看我的最后一个回复! 非常感谢。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Richard、

    感谢您清除一些配置并添加额外的初始化代码。

    您是否尝试过在 ISR 中设置断点? 它永远不会在 ISR 内部达到断点吗?

    如果您没有尝试过、那么问题可能在于您在 ISR 中更改的变量未声明为"易失性"变量。

    尝试将其改为'uint8_t flagB;'、使其成为'volatile uint8_t flagB;'
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Richard、

    我只使用 Timer 1B 运行了一个略微清理的代码版本、需要将 flagb 变量设置为易失性才能正确更新、使用 TivaWare 时的初始化是可以的。 请尝试使您的变量具有易失性、并查看问题是否解决。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你(们)好。 非常感谢,现在它已经更新了! 我仍然有一些问题。 我是否需要在 ISR 中为每个变量添加易失性? 是否可以逐步查看 ISR? 只有通过播放标志 B 更新、看起来我不能在 ISR 内进行分步调试。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Richard、

    任何将在 ISR 中更改其值的全局变量都需要 volatile。 如果未将其设置为 volatile、则编译器优化系统可能无法正确识别该值、因为该变量会在 ISR 执行时更改值。 我认为,这就是你的情况发生的情况。

    您可以分步执行 ISR。 虽然 CCS 偶尔会对它能让您准确地放置断点的位置提出挑剔,但我认为这都是基于应用于代码的编译器优化,但我不是 CCS 专家,所以不要把我的词当作福音:)

    您应该查看这篇关于易失性变量的文章、特别是有关在 ISR 中更新全局变量的部分、因为它几乎正是您所处的情况: https://barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    只要多个上下文(ISR、线程、主循环)访问变量、就使用 volatile。 这些上下文相互"异步"、这意味着它们可以在代码中的任意时刻相互中断。 C 中的一行代码可编译为许多处理器指令、因此实际上这意味着代码也可以"在行的中间"中断。

    如果您发现自己必须声明太多变量 volatile、请检查代码设计是否正确。 在同一数据上运行过多的上下文可能会导致难以预测的交互。