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.

[参考译文] TM4C1231H6PGE:永远不会触发 PWM 中断

Guru**** 2609285 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/756019/tm4c1231h6pge-pwm-interrupt-never-fires

器件型号:TM4C1231H6PGE

您好!

我的目标是从我的 PWM 外设生成中断。

我按照以下文章中的说明操作:  

并附带以下代码:

int main (void)
{
SysCtlPWMClockSet (SYSCTL_PWMDIV_64);
SysCtlPeripheralEnable (SYSCTL_Periph_PWM1);
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);

GPIOPinTypePWM (GPIO_PORTD_base、GPIO_PIN_1);
GPIOPinConfigure (GPIO_PD0_M1PWM0);
GPIOPinConfigure (GPIO_PD1_M1PWM1);

volatile uint32_t ui32PWMClock = SysCtlClockGet ()/ 64;

volatile uint32_t ui32Load =( ui32PWMClock/PWM_FREQUENCY )- 1;

PWMGenConfigure (PWM1_base、PWM_GEN_0、PWM_GEN_MODE_DOWN);
PWMGenPeriodSet (PWM1_base、PWM_GEN_0、ui32Load);

PWMPulseWidthSet (PWM1_base、PWM_OUT_1、IDLE_FLOT_SPIN);
PWMOutputState (PWM1_base、PWM_OUT_1_BIT、true);

PWMGenEnable (PWM1_base、PWM_GEN_0);

SysCtlDelay (2 * SysCtlClockGet ();

PWMGenIntTrigEnable (PWM1_base、PWM_GEN_0、PWM_INT_CNT_ZERO);

while (1)
{
如果(PWM_INTERRUPT)
{
//执行某些操作
}
}

"PWM_INTERRUPT"是一个变量、其值在 ISR 例程中设置如下:

//
//
//// startup_ccs.c -与 TI 的 Code Composer Studio 一起使用的启动代码。
//
//版权所有(c) 2013 Texas Instruments Incorporated。 保留所有权利。
//软件许可协议
//
//德州仪器(TI)提供此软件仅供
和//仅供 TI 的微控制器产品使用。 软件归
// TI 和/或其供应商所有,并受适用的版权
//法律保护。 您不能将此软件与"病毒"开源
//软件组合在一起以形成更大的程序。
//
//此软件按“原样”提供,且存在所有故障。
//对于

本软件,不作任何明示、暗示或法定的保证,包括但不限于对适销性和适用性的暗示保证//特定用途。 在任何
//情况下、TI 不对任何
原因造成的特殊、意外或必然//损害负责。
//
//这是 EK-TM4C123GXL 固件包修订版1.0的一部分。
////
*****************

#include 
#include "inc/hw_NVIC.h"
#include "inc/hw_types.h"

//*********
//
//转发默认故障处理程序的声明。
////
*****************
void ResetISR (void);
static void NmiSR (void);
static void FaultISR (void);
static void IntDefaultHandler (void);

//*********
//
//
启动//处理器时要调用的复位处理程序的外部声明
//
*********
extern void _c_int00 (void);

//*********
//
//标记栈顶的链接器变量。
////
*****************
extern uint32_t __stack_top;

//*********
//
//应用程序使用的中断处理程序的外部声明。
////
*****************
//extern void IntGPIOe (void);
extern void ISL29023I2CIntHandler (void);
void PWM1_GEN0_ISR (void);
//extern void SysTickIntHandler (void);
//extern void UARTStdioIntHandler


(****);//extern void RGBBlinkHandler (void)
//
//矢量表。 请注意、必须在这个上放置适当的结构、
以//确保它在物理地址0x0000.0000处结束、或者
在//程序的开头(如果位于0以外的起始地址)结束。
////
*****************
#pragma DATA_SECTION (g_pfnVectors、".intvecs")
void (* const g_pfnVectors [])(void)=
{
(void (*)(void)((uint32_t)&_stack_top)、
//初始堆栈指针
ResetISR、 //重置处理程序
NmiSR、 // NMI 处理程序
FaultISR、 //硬故障处理程序
IntDefaultHandler、 // MPU 故障处理程序
IntDefaultHandler、 //总线故障处理程序
IntDefaultHandler、 //用法故障处理程序
0、 //保留
0、 //保留
0、 //保留
0、 //保留
IntDefaultHandler、 // SVCall 处理程序
IntDefaultHandler、 //调试监视器处理程序
0、 //保留
IntDefaultHandler、 // PendSV 处理程序
IntDefaultHandler、 // SysTick 处理程序
IntDefaultHandler、 // GPIO 端口 A
IntDefaultHandler、 // GPIO 端口 B
IntDefaultHandler、 // GPIO 端口 C
IntDefaultHandler、 // GPIO 端口 D
IntDefaultHandler、 // GPIO 端口 E
IntDefaultHandler、 // UART0 Rx 和 Tx
IntDefaultHandler、 // UART1 Rx 和 Tx
IntDefaultHandler、 // SSI0 Rx 和 Tx
IntDefaultHandler、 // I2C0主机和从机
IntDefaultHandler、 // PWM 故障
IntDefaultHandler、 // PWM 发生器0
IntDefaultHandler、 // PWM 发生器1
IntDefaultHandler、 // PWM 发生器2.
IntDefaultHandler、 //正交编码器0
IntDefaultHandler、 // ADC 序列0
IntDefaultHandler、 // ADC 序列1
IntDefaultHandler、 // ADC 序列2.
IntDefaultHandler、 // ADC 序列3.
IntDefaultHandler、 //看门狗计时器
IntDefaultHandler、 // Timer 0子计时器 A
IntDefaultHandler、 // Timer 0子计时器 B
IntDefaultHandler、 //计时器1子计时器 A
IntDefaultHandler、 //计时器1子计时器 B
IntDefaultHandler、 //计时器2子计时器 A
IntDefaultHandler、 //计时器2子计时器 B
IntDefaultHandler、 //模拟比较器0
IntDefaultHandler、 //模拟比较器1
IntDefaultHandler、 //模拟比较器2.
IntDefaultHandler、 //系统控制(PLL、OSC、BO)
IntDefaultHandler、 //闪存控制
IntDefaultHandler、 // GPIO 端口 F
IntDefaultHandler、 // GPIO 端口 G
IntDefaultHandler、 // GPIO 端口 H
IntDefaultHandler、 // UART2 Rx 和 Tx
IntDefaultHandler、 // SSI1 Rx 和 Tx
IntDefaultHandler、 //计时器3子计时器 A
IntDefaultHandler、 //计时器3子计时器 B
IntDefaultHandler、 // I2C1主设备和从设备
IntDefaultHandler、 //正交编码器1
IntDefaultHandler、 // CAN0
IntDefaultHandler、 // CAN1
IntDefaultHandler、 // CAN2
0、 //保留
IntDefaultHandler、 //休眠
IntDefaultHandler、 // USB0
IntDefaultHandler、 // PWM 发生器3.
IntDefaultHandler、 // uDMA 软件传输
IntDefaultHandler、 // uDMA 错误
IntDefaultHandler、 // ADC1序列0
IntDefaultHandler、 // ADC1序列1
IntDefaultHandler、 // ADC1序列2.
IntDefaultHandler、 // ADC1序列3.
0、 //保留
0、 //保留
IntDefaultHandler、 // GPIO 端口 J
IntDefaultHandler、 // GPIO 端口 K
IntDefaultHandler、 // GPIO 端口 L
IntDefaultHandler、 // SSI2 Rx 和 Tx
IntDefaultHandler、 // SSI3 Rx 和 Tx
IntDefaultHandler、 // UART3 Rx 和 Tx
IntDefaultHandler、 // UART4 Rx 和 Tx
IntDefaultHandler、 // UART5 Rx 和 Tx
IntDefaultHandler、 // UART6 Rx 和 Tx
IntDefaultHandler、 // UART7 Rx 和 Tx
0、 //保留
0、 //保留
0、 //保留
0、 //保留
ISL29023I2CIntHandler、 // I2C2主设备和从设备
IntDefaultHandler、 // I2C3主设备和从设备
IntDefaultHandler、 //计时器4子计时器 A
IntDefaultHandler、 //计时器4子计时器 B
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
0、 //保留
IntDefaultHandler、 //计时器5子计时器 A
IntDefaultHandler、 //计时器5子计时器 B
IntDefaultHandler、 //宽定时器0子定时器 A
IntDefaultHandler、 //宽定时器0子定时器 B
IntDefaultHandler、 //宽定时器1子定时器 A
IntDefaultHandler、 //宽定时器1子定时器 B
IntDefaultHandler、 //宽定时器2子定时器 A
IntDefaultHandler、 //宽定时器2子定时器 B
IntDefaultHandler、 //宽定时器3子定时器 A
IntDefaultHandler、 //宽定时器3子定时器 B
IntDefaultHandler、 //宽定时器4子定时器 A
IntDefaultHandler、 //宽定时器4子定时器 B
IntDefaultHandler、 //宽定时器5子定时器 A
IntDefaultHandler、 //宽定时器5子定时器 B
IntDefaultHandler、 // FPU
0、 //保留
0、 //保留
IntDefaultHandler、 // I2C4主设备和从设备
IntDefaultHandler、 // I2C5主设备和从设备
IntDefaultHandler、 // GPIO 端口 M
IntDefaultHandler、 // GPIO 端口 N
IntDefaultHandler、 //正交编码器2
0、 //保留
0、 //保留
IntDefaultHandler、 // GPIO 端口 P (摘要或 P0)
IntDefaultHandler、 // GPIO 端口 P1
IntDefaultHandler、 // GPIO 端口 P2
IntDefaultHandler、 // GPIO 端口 P3
IntDefaultHandler、 // GPIO 端口 P4
IntDefaultHandler、 // GPIO 端口 P5
IntDefaultHandler、 // GPIO 端口 P6
IntDefaultHandler、 // GPIO 端口 P7
IntDefaultHandler、 // GPIO 端口 Q (摘要或 Q0)
IntDefaultHandler、 // GPIO 端口 Q1
IntDefaultHandler、 // GPIO 端口 Q2
IntDefaultHandler、 // GPIO 端口 Q3
IntDefaultHandler、 // GPIO 端口 Q4
IntDefaultHandler、 // GPIO 端口 Q5
IntDefaultHandler、 // GPIO 端口 Q6
IntDefaultHandler、 // GPIO 端口 Q7
IntDefaultHandler、 // GPIO 端口 R
IntDefaultHandler、 // GPIO 端口 S
PWM1_GEN0_ISR、 // PWM 1发生器0
IntDefaultHandler、 // PWM 1发生器1
IntDefaultHandler、 // PWM 1发生器2
IntDefaultHandler、 // PWM 1发生器3
IntDefaultHandler // PWM 1故障
};

//*********
//
//这是在处理器首次开始执行
时调用的代码//在复位事件之后。 只执行绝对必要的设置,
//之后调用应用程序提供的 entry()例程。 任何花式
//操作(例如根据复位原因寄存

器做出决策、和//复位该寄存器中的位)都只能由//应用程序控制。
////
*****************
void
ResetISR (void)
{
//
//跳转到 CCS C 初始化例程。 这将启用
//浮点单元,因此不需要在此处执行此操作。
//
_asm (".global _c_int00\n"
" _c_int00");
}

//*********
//
//这是当处理器接收到 NMI 时被调用的代码。 这个
//只需进入一个无限循环,保留系统状态供
调试器检查//。
////
*****************
静态空
NmiSR (void)
{
//
//输入无限循环。
//
while (1)
{
}
}

//*********
//
//这是处理器收到故障
//中断时调用的代码。 这只是进入一个无限循环、保持系统状态
//供调试器检查。
////
*****************
静态空
FaultISR (空)
{
//
//输入无限循环。
//
while (1)
{
}
}

//*********
//
//这是当处理器收到意外
的//中断时调用的代码。 这只是进入一个无限循环、保持系统状态
//供调试器检查。
////
*****************
静态空
IntDefaultHandler (void)
{
//
//进入无限循环。
//
while (1)
{
}
}

ISR:

void PWM1_GEN0_ISR (void)
{
PWMGenIntClear (PWM1_base、PWM_GEN_0、PWM_INT_CNT_ZERO);
PWM_INTERRUPT = true;
} 

PWM 信号已成功生成、但未调用中断(从未达到断点)。

我出了什么问题?

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

    您需要添加调用来启用 VIM 中的 PWM 中断和主中断使能、方法是添加以下行:

    IntEnable (INT_PWM1_0);
    IntMasterEnable(); 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我添加了这些行、现在它起作用了。
    但我在互联网上看到了其他示例、这些示例也称为:
    PWMIntEnable (PWM1_base、PWM_INT_GEN_0);
    它与 IntEnable (INT_PWM1_0)有何区别?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您实际上在三个级别启用中断。 PWMIntEnable()函数选择哪个条件产生 PWM 模块的中断。 IntEnable()函数启用 VIM (矢量中断模块)中的中断线。 IntMasterEnable()函数启用 Cortex M4 CPU 中的中断。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    PWMIntEnable()函数选择哪个条件产生 PWM 模块的中断。
    是否确定您不是指 PWMGenIntTrigEnable (PWM1_base、PWM_GEN_0、PWM_INT_CNT_ZERO)、您是否这样做?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    PWMGenIntTrigEnable()实际上调用指定 PWM 发生器的 IntRegister()和 IntEnable()。 在代码中,您静态初始化 PWMGEN0矢量,因此对 PWMGenIntTrigEnable()中的 IntRegister()的调用是多余的。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您说:

    PWMGenIntTrigEnable()实际调用 IntRegister()和 IntEnable()

    从这个结论中,如果我使用 PWMGenIntTrigEnable(),我不需要同时使用 IntRegister()和 IntEnable()。

    我的理解是否正确?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    没错。 此外,使用调用 IntRegister()的 PWMGenIntTrigEnable()时,您无需在 statup_ccs.c 中编辑矢量
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您说 PWMGenIntTrigEnable 调用 IntRegister -我查看 了 PWMGenIntTrigEnable 的实现、但我看不到什么...

    PWMGenIntTrigEnable (uint32_t ui32Base、uint32_t ui32Gen、
    uint32_t ui32IntTrig)
    {
    //
    //检查参数。
    //
    assert (((ui32Base == PWM0_BASE)||(ui32Base == PWM1_base));
    assert (_PWMGenValid (ui32Gen));
    Assert (((ui32IntTrig &~)(PWM_INT_CNT_ZERO | PWM_INT_CNT_LOAD |
    PWM_INT_CNT_AU | PWM_INT_CNT_AD | PWM_INT_CNT_BU |
    PWM_INT_CNT_BD | PWM_TR_CNT_ZERO |
    PWM_TR_CNT_LOAD | PWM_TR_CNT_AU | PWM_TR_CNT_AD |
    PWM_TR_CNT_BU | PWM_TR_CNT_BD)= 0);
    
    //
    //启用指定的中断/触发器。
    //
    HWREG (PWM_GEN_BADDR (ui32Base、ui32Gen)+ PWM_O_X_INTEN)|= ui32IntTrig;
    } 
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    抱歉,我说了“错误”,函数 PWMGenIntRegister()调用 IntRegisterIO 和 IntEnable。