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.

[参考译文] RTOS/MSP432P401R:为什么我的中断无法足够快地触发 ISR?

Guru**** 2524350 points
Other Parts Discussed in Thread: ENERGIA

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/596583/rtos-msp432p401r-why-are-my-interrupts-not-able-to-fire-the-isr-fast-enough

器件型号:MSP432P401R
主题中讨论的其他器件:Energia

工具/软件:TI-RTOS

大家好、

我有一个不带 TI-RTOS 的 driverlib 项目、该项目能够正常工作、以8KHz 由 TimerA0启动的多通道 ADC14测量。  但是、当我尝试将该项目集成到 Energia (基于 TI-RTOS)中时、中断只会以1000Hz 的频率触发。  起初、我以为 Energia 对时钟速度设置了额外的8分频、但我在 CS 或 TimerA 部分找不到它。  如果我设置 CCR1以减少计数、那么我根本不会获得中断。  我有四个要转换的通道、请注意、如果我将中断更改为在第一次转换之后触发、而不是在最后一次转换之后触发、中断的触发速度是中断的四倍、因此转换过程就像花费了很长的时间(1/4000秒)一样。  我正在寻找有关如何进行调试的提示:

  1. 是否有测量 SMCLK 速度的好方法?
  2. 是否有方法测量 MCLK?
  3. 是否有办法找出是什么使中断无法触发?  也许还有另一个具有更高优先级的中断。
  4. 什么会导致 ADC14如此缓慢?

我有三个文件:.ino、.c 和.h: 它们在下面提供:

//.ino 文件。
extern "C"{
#include 
};


//大多数 launchpad 都有一个红色 LED
#define LED RED_LED

//有关更多 LED 定义,请参阅 pins_energia.h
//#define LED GREEND_LED

//按下 RESET:
void setup(){
Serial.begin(115200);
//将数字引脚初始化为输出时,设置例程运行一次。
//pinMode (LED、输出);
adc14_();
//delay (500);
//map_ADC14_enableConversion ();
startSampling();
}//

循环例程不停地运行:
void loop(){
静态 int i=0;
serial.print (i++);
serial.println ("Hello!");
//digitalWrite (LED、HIGH);//打开 LED (HIGH 是电压电平)
//delay (1000); //等待第二
次 digitalWrite (LED、low);//通过使电压低
延迟(1000)关闭 LED; //等待一秒钟
}

和头文件:

/*
* adc14_.h
*
*创建日期:2017年5月12日
* 作者:Frohro
*/

#ifndef COPY2_ADC14_H_
#define COPY2_ADC14_H_

/* DriverLib 包括*/
#include 
#include 

/*标准包括*/
#include 

#include 
#define SMCLK_FREQ 24000000
#define SAMPLE_FREQ 8000
// Timer_A 连续模式配置参数
const Timer_A_UpModeConfig upModeConfig =//这可以正常
工作{
Timer_A_CLOCKSOURCE_SMCLK、 // SM 时钟源
Timer_A_CLOCKSOURCE_divider _1、 // SMCLK/1 = 24MHz
(SMCLK_FREQ/SAMPLE_FREQ)、
Timer_A_TAIE_INTERRUPT_DISABLE、 //禁用计时器 ISR
Timer_A_CCIE_CCR0_INTERRUPT_DISABLE、//禁用 CCR0
Timer_A_do 清除 //清除计数
器};

// Timer_A 比较配置参数*/
const Timer_A_CompareModeConfig compareConfig =
{
Timer_A_CAPTURECOMPARE 寄存器_1、 //使用 CCR1
Timer_A_CAPTURECMOLE_INTERRUPT_DISABLE、//禁用 CCR 中断
Timer_A_OUTPUTMODE_SET_RESET、 //切换输出但是
(SMCLK_FREQ/SAMPLE_FREQ) //应为8kHz 采样率
};

//静态
易失性 uint_fast16_t resultsBuffer[uint8_MAX];
静态易失性 uint8_t resPos;

int adc14_(void);
void ADC14_IRQHandler (void);
void startSampling (void);




#endif /*_ADC14_(void)* ADC14_

最后是 C 文件:

/*
--------------------------------
* MSP432 DriverLib - v4_00_00_11
*----------------------
*
*-版权所有-、BSD、BSD
*版权所有(c) 2017、德州仪器(TI)公司
*保留所有权利。
*
*
只要
符合以下条件*、允许以源代码和二进制形式重新分发和使用:
*
*源代码的重新分发必须保留上述版权
声明*、此条件列表和以下免责声明。
*
***二进制形式的再发行必须在

*随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。
*
***未经

事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。
*
*本软件由版权所有者和贡献者"按原样"提供
*、

不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或
*贡献者都不对任何直接、间接、偶然、特殊、
*模范、 或相应的损害(包括但不限于
*采购替代产品或服务;丧失使用、数据或利润;
*或业务中断)、但出于任何责任理论
、*无论是在合同中、严格责任还是由于
使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他)
、*即使已获悉可能会发生此类损坏。
*--/copyrights-*/*
MSP432 ADC14 -不重复的多通道采样
*
说明:在此代码示例中,
用户 A DriverLib API 演示了能够扫描多个* ADC 通道的功能。 转换
*内存寄存器 ADC_MEM0 - ADC_MEM3被配置为分别读取
A6、A12、A10、A8的转换*结果。 转换被启用、然后使用
一个软件切换来*切换采样。 重复模式未启用、仅采样
*发生一次(用户应暂停调试器以观察
*结果)。 在采集完最终样本后、
* ADC_MEM3的中断被触发、结果存储在 resultsBuffer 缓冲区中。
*
* MSP432P401
* ----------
* /|\| |
* || |
* -|RST P4.7 |<-- A6 (模拟输入、测量值、实际值)
* | P4.1 |<-- A12 (模拟输入、测量值、虚数)
* | P4.3 |<-- A10 (模拟输入、基准实数)
* | P4.5 |<-- A8 (模拟输入、基准虚数)
* | |
* | |
*
4.1、4.3、4.5、4.7是最终所需的引脚。
*
*作者:Timothy Logan
*这是 Rob Frohne 修改的、以在8kHz 采样率下执行多个 ADC。
秘书长的报告 /#include

#define NUMBER_TIMER_CAPTURES 20
#define SAMPLE_LENGTH 128

/*
静态易失性 uint_fast16_t timerAcaptureValues[NUMBER_TIMER_CAPTURES];
静态易失性 uint32_t timerAcapturePointer = 0;
*/

uint16_t refRe[SAMPLE_LENG];
uint16_t refIim[SAMPLE_LENGTH];
uint16_t
measure];uint16_t measure]
extern volatile bodyool ADC;
bool sendMeasurement = false;
int numberFrquenciestoMeasure、frequencyIndex;
float refSum、measSum;
volatile botonool ADC = false;
//void TA0_N_IRQHandler (void);

int adc14_(void)
{
/*停止 WDT */
WDT_A_HOLDTimer();
Hwi_Params 参数;

//寄存器中断
Hwi_Params_init (params);
Hwi_create (INT_ADC14、ADC14_IRQHandler、&params、0);
//Hwi_create (INT_TA0_N、TA0_N_IRQHandler、&params、0);
//Interrupt_enableSlepOnIsrExit();
RESPos = 0;
//设置为 Vcore1
PCM_setCoreVoltageLevel (PCM_VCORE1);

//设置为使用 DCDC
//PCM_setPowerState (PCM_AM_DCDC_VCORE1);

//初始化时钟系统
/*由于我们需要 Energia 时钟设置、这些注释被注释掉。 。
*相应调整计时器的数据结构。 时间
*转换之间的时间可能是这些转换的四倍
*参数、但这似乎是实现一切的最简单方法
*立即一起玩。 *
//FlashCtl_setWaitState (FLASH_BANK0、2);
//FlashCtl_setWaitState (FLASH_BANK1、2);
PCM_setPowerState (PCM_AM_DCDC_VCORE1);
cs_setDCOCenteredFrequency (CS_DCO_FREQUENCY);
cs_setDCOFrequency (24000000);
CS_initClockSignal (CS_MCLK、CS_DCOCLK_SELECT、CS_Clock_divider);
CS_initClockSignal (CS_SMCLK、CS_DCOCLK_SELECT、CS_Clock_divider _1);


/*初始化 ADC (MCLK/1/1)*/
ADC14_enableModule();
ADC14_initModule (ADC_CLOCKSOURCE_MCLK、ADC_PREDIVIDER_1、ADC_DIVIDER_1、
0);

//配置调试引脚作为调试输出...
GPIO_setAsOutputPin (GPIO_PORT_P5、GPIO_PIN5);
GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0);

//Configuring GPIO for Analog In
GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P4、
GPIO_PIN1 | GPIO_PIN3 | GPIO_PIN5 | GPIO_PIN7、GPIO_TICE_MODULE_FUNCTION);

//配置 ADC 存储器(ADC_MEM0 - ADC_MEM3 (A6、A12、A10、A8)、不重复)
//具有内部2.5V 基准
ADC14_configureMultiSequenceMode (ADC_MEM0、ADC_MEM3、TRUE);//无重复模式。
ADC14_configureConversionMemory (ADC_MEM0、
ADC_VREFPOS_INTBUF_VREFNEG_VSS、
ADC_INPUT_A6、ADC_NONDIFFERENTIAL_INPUTES);
ADC14_configureConversionMemory (ADC_MEM1、
ADC_VREFPOS_INTBUF_VREFNEG_VSS、
ADC_INPUT_A12、ADC_NONDIFFERENTIAL 输入);
ADC14_configureConversionMemory (ADC_MEM2、
ADC_VREFPOS_INTBUF_VREFNEG_VSS、
ADC_INPUT_A10、ADC_NONDIFFERENTIAL 输入);
ADC14_configureConversionMemory (ADC_MEM3、
ADC_VREFPOS_INTBUF_VREFNEG_VSS、
ADC_INPUT_A8、ADC_NONDIFFERENTIAL 输入);

/*配置 Timer_A*/
Timer_A_configureUpMode (timer_A0_BASE、&upModeConfig);

/*在 CCR1中配置 Timer_A0 */
Timer_A_initCompare (timer_A0_BASE、&compareConfig);

/*将样本触发器配置为来自 Timer_A0并进行设置
*在触发后自动迭代*/
ADC14_setSampleHoldTrigger (ADC_TRIGGER_SOURCE1、false);

/*当通道3上的转换完成时启用中断*/
ADC14_enableInterrupt (ADC_INT3);
//ADC14_enableConversion();//不需要,因为我们在.ino 中启用它。

/*启用中断*/
INTERRUPT_enableInterrupt (INT_ADC14);
interrupt_enableMaster();

/*启动计时器*/
Timer_A_startCounter (timer_A0_BASE、timer_A_up_mode);

/*正在休眠*/*
while (1)
{
PCM_gotoLPM0 ();
}*/
返回1;
}


void ADC14_IRQHandler (void)
{
uint64_t status;
静态 int i = 0;
//GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN0);
status = ADC14_getEnabableInterruptStatus();
ADC14_clearInterruptFlag (status);
GPIO_toggleOutputOnPin (GPIO_PORT_P5、GPIO_PIN5);
ADC14_disableConversion();

if (status & ADC_INT3)
{
//ADC14_disableConversion();
印度尼西亚 ADC = false;
ADC14_getMultiSequenceResult (resultsBuffer);
measRe[i]= resultsBuffer[0];
measIM[i]= resultsBuffer[1];
refRe[i]= resultsBuffer[2];
refIm [i]= resultsBuffer[3];
//i=(i+1)%SAMPLE_LENGTH;

如果(i!=sample_length)
{
i++;
//ADC14_enableConversion();
}
其他
{
I=0;
印度尼西亚 ADC = true;
//ADC14_enableConversion();
}
}
ADC14_enableConversion();
}/*void

TA0_N_IRQHandler (void)
{
uint32_t jj;

Timer_A_clearCaptureCompareInterrupt (timer_A0_BASE、
Timer_A_CAPTURECOMPARE 寄存器1);

timerAcaptureValues[timerAcapturePointer++]=
Timer_A_getCaptureCompareCount (timer_A0_BASE、
Timer_A_CAPTURECOMPARE 寄存器1);

if (timerAcapturePointer >= number_timer_captures)
{
while (1)
{
GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN0);
for (jj=0;jjj<10000;jjj++);
}
}
}*/

void startSampling(void){

ADC14_enableConversion();//我需要这么做是一个谜
//而不是仅仅调用 ADC14_enableConversion()
//从.ino 文件!
}

感谢您的提示!

Rob

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

    感谢您在论坛上发帖! 我们正在调查此事、并努力将您的请求发送给合适的团队。 我们会及时回复您。

    此致、

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

    谢谢 David、
    我仔细看了一下、TI-RTOS (Energia)似乎正在改变我在.ino 中所做的设置。 此时、我不确定何时。 我正在尝试弄清楚如何实现它、以便 Energia 不会初始化我不需要的东西、例如 ADC。 我可能需要修改 Energia wiring_analog.c 以及 Energia/EMT/src/ti/runtime/wire/msp432/或一些其他 Energia 源代码中的其他内容、或者放弃使用 Energia 的想法、但我不会很快放弃。

    谢谢!

    Rob

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

    Rob、


    您能否帮助我们了解您在本例中使用 Energia 的目的是什么? 在这种情况下、为什么不使用 CCS? 很好奇!

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

    您好 Evan、

    实际上、我将 Code Composer Studio 与 Energia 配合使用、总的来说、它运行得很好。  当我使用 Energia 这个词时、我指的是运行时代码、而不是 IDE。 我不使用 driverlib 单线程裸机代码。  下面是我对这两种选择的想法的一些解释。

    我的工程电子学学生正在为 MSP432 Launchpad 设计矢量网络分析器 Booster Pack。  分析仪与主机 PC 进行串行通信、并包含可编程(通过 I2C)振荡器、同时还需要 ADC 和 GPIO。  课程不是关于软件、而是设计硬件、因此我为他们准备了软件。  当然、他们必须处理软件问题、但我想尽可能简化。  去年、我们执行了一个有点类似的项目、我发现软件设计中最困难的部分是通过一个运行时没有错误的奇特的 Versaclock 振荡器实现 I2C 通信、 有些学生使用了不同的振荡器(TI 振荡器)、因此他们必须在软件方面努力工作。  由于我们将这些振荡器用作扫描信号发生器、两个输出的相位差为90度、因此需要大量的振荡器设置。 大多数使用这些类型振荡器的人只需使用制造商提供的 PC 软件对它们进行一次编程、然后就可以使用它完成编程。  今年、所有学生都决定使用 Si5351可编程振荡器、而不是 Versaclock 或其他 TI 振荡器、我找到了一个出色的 Arduino 库、其中包含了 Si5351所需的所有功能。  起初、我打算像去年一样使用库作为示例代码来开发我自己的 driverlib 裸机软件、但后来我意识到 Energia 已经存在、所以我尝试了它、 它与我为 Si5351找到的 I2C 库一起工作非常好、与主机 PC 的串行通信也是如此。  我决定尝试将我之前开发的裸机 ADC14代码锚固到 Energia。  我希望、由于我唯一不采用 Energia 方法的是 ADC14、因此干扰很小。  通常、能够使用大多数 Energia 库似乎也是一件非常好的事情、并且只有在 Energia 未提供所需性能的情况下、您才需要使用一些 driverlib 代码。  我一直在读取 Energia 的核心运行时代码、但仍然认为这会很好。  但是,我现在知道,有些事情可能使我不能走这条路。  它们是:

    • 您只能使用多线程(MT)项目。  尽管 Code Composer Studio 中有一个按钮使其看起来可以禁用多线程、但在 MSP432上却无法禁用。  (如果 Code Composer Studio 按钮也灰显、而不是刚刚被选中、那会更好、因为这不会误导我。)  这可能是一个问题、因为我在 MT Energia 代码中读取了许多为确保线程安全而禁用中断的位置。
    • 这些计时器似乎在 Energia 代码中得到了大量使用。  我想使用一些计时器、但对于 ADC14的八个不同的计时器触发器、我想我可以找到一个可以使用的计时器、我需要完成对此的探索、因为这仍然是一种可能性。
    • 我还没有找到其他人做过这种事情。  如果其他人率先提出了这个想法、但至少在那里提供了 MT Energia 的源代码、那会更容易。

    此时、我还没有准备好抛弃裸机解决方案、因为它对我来说仍然是可行的。  如果我可以这样做、那么通过对 ADC14代码进行锚固而禁用的唯一功能就是 Energia 的 AnalogXXX()函数、它会使软件对我的学生更友好。  除了使用 AnalogXXX()函数之外,他们还可以通过 Arduino 方式执行任何操作。  不是很好!

    感谢所有的帮助!

    Rob

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

    大家好、

    下面是我今天通过测试能够提供的更多信息。  

    • 我已经尝试过 TimerA0、TimerA1、TimerA2和 TimerA3。  我无法让它与任何一个客户一起工作。
    • 我注意到、TAxR 停止在看起来是随机的时间递增、在12MHz 时通常少于500次计数。
    • 我在随机时间停止了程序、一旦在 Timer.c 中结束、TI-RTOS 似乎会根据需要使用所有计时器。  我想知道如何将 Timer_numTimerDevices 设置为比它小1、并尝试使用 TimerA3来触发我的 ADC14 ISR。
    • 我有一个间歇性工作的简单计时器示例。  这似乎比我在上面发布的 ADC14例程的时间更长、因此除了计时器之外、可能还有其他问题。  发布如下:
    /*
    链接
    基本 Energia 示例。
    将 LED 亮起一秒钟、然后反复熄灭一秒钟。
    更改 LED 定义以使其他 LED 闪烁。
    
    所需硬件:
    *带 LED 的 LaunchPad
    
    此示例代码位于公共域中。
    //
    extern "C"{
    #include "ta_up.h"
    };
    //大多数 launchpad 都有一个红色 LED
    #define LED red_LED
    
    //有关更多 LED 定义,请参阅 pins_energia.h
    //#define LED green_LED
    
    //当您按 reset 时,设置例程运行一次:
    void setup(){
    //将数字引脚初始化为输出。
    PinMode (LED、OUTPUT);
    TA_UP_MAIN ();
    }
    
    //循环例程会不停地运行:
    void loop (){
    //digitalWrite (LED、HIGH);//打开 LED (HIGH 表示电压电平)
    延迟(1000); //等待第二
    次 digitalWrite (LED、low);//通过使电压低
    延迟(1000)关闭 LED; //等待一秒钟
    }
    

    和头文件:

    /*
    * ta_up.h
    *
    *创建日期:2017年5月3日
    * 作者:Frohro
    */
    
    #ifndef TA_UP_H_
    #define TA_UP_H_
    
    #include 
    int ta_up_main (void);
    
    #endif // ta_up_h_*
    

    最后是 C 文件:

    /*
    ta_up.c
    *
    *创建日期:2017年5月3日
    * 作者:Frohro
    *//*
    
    
    ------------------------
    * MSP432 DriverLib - v4_00_00_11
    *----------------------
    *
    *-版权所有-、BSD、BSD
    *版权所有(c) 2017、德州仪器(TI)公司
    *保留所有权利。
    *
    *
    只要
    符合以下条件*、允许以源代码和二进制形式重新分发和使用:
    *
    *源代码的重新分发必须保留上述版权
    声明*、此条件列表和以下免责声明。
    *
    ***二进制形式的再发行必须在
    
    *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。
    *
    ***未经
    
    事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。
    *
    *本软件由版权所有者和贡献者"按原样"提供
    *、
    
    不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或
    *贡献者都不对任何直接、间接、偶然、特殊、
    *模范、 或相应的损害(包括但不限于
    *采购替代产品或服务;丧失使用、数据或利润;
    *或业务中断)、但出于任何责任理论
    、*无论是在合同中、严格责任还是由于
    使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他)
    、*即使已获悉可能会发生此类损坏。
    *--/版权--*/
    
    * MSP432 PWM TA1.1-2、上数/下数模式、DCO SMCLK
    *
    说明:使用软件和 TA_0 ISR 切换 P1.0。 Timer0_A
    被*配置为向上计数模式、因此当 TAR 计数
    *到 CCR0时、定时器溢出。 在本示例中、CCR0加载了0x2DC6、这使得 LED
    *每半秒切换一次。
    * ACLK = n/a、MCLK = SMCLK =默认 DCO ~1MHz
    * TACLK = SMCLK/64
    *
    MSP432P401
    * ----------
    */|\| |
    *|| |
    *-|RST |
    * | |
    * | P1.0|->LED
    * | |
    *
    作者:Timothy Logan
    /*
    DriverLib 包括*/
    #include 
    
    #include "TA_UP.h"
    
    void TA1_0_IRQHandler (void)
    {
    GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN0);
    GPIO_toggleOutputOnPin (GPIO_PORT_P5、GPIO_PIN5);
    Timer_A_clearCaptureCompareInterrupt (timer_A1_base、
    Timer_A_CAPTURECOMPARE 寄存器_0);
    }
    
    
    //应用定义*
    #define TIMER_PERIOD 0x2DC6
    
    //* Timer_A 向上模式配置参数*/
    const Timer_A_UpModeConfig upConfig =
    {
    Timer_A_CLOCKSOURCE_SMCLK、 // SMCLK 时钟源
    Timer_A_CLOCKSOURCE_DELAG_64、 // SMCLK/1 = 3MHz
    Timer_Period、 // 5000个周期
    Timer_A_TAIE_INTERRUPT_DISABLE、 //禁用计时器中断
    Timer_A_CCIE_CCR0_INTERRUPT_ENABLE,//启用 CCR0中断
    Timer_A_do 清除 //清除值
    };
    
    int ta_up_main (void)
    {
    Hwi_Params 参数;
    
    /*停止 WDT */
    WDT_A_HOLDTimer();
    
    //寄存器中断
    Hwi_Params_init (params);
    Hwi_create (INT_TA1_0、TA1_0_IRQHandler、&params、0);
    
    /*将 P1.0配置为输出*/
    GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0);
    GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN0);
    GPIO_setAsOutputPin (GPIO_PORT_P5、GPIO_PIN5);
    GPIO_setOutputLowOnPin (GPIO_PORT_P5、GPIO_PIN5);
    
    
    /*将 Timer_A1配置为向上计数模式*/
    Timer_A_configureUpMode (timer_A1_base、upConfig);
    
    /*启用中断并启动计时器*/
    interrupt_enableSlepOnIsrExit();
    INTERRUPT_enableInterrupt (INT_TA1_0);
    Timer_A_startCounter (timer_A1_base、timer_A_up_mode);
    
    /*启用主中断*/
    interrupt_enableMaster();
    
    /*不使用时睡眠*/
    // while (1)
    {
    //PCM_gotoLPM0 ();
    }
    返回1;
    } 

    下面是 TI-RTOS 的 Timer.h、供您参考:

    //
    *版权所有(c) 2014-2016,Texas Instruments Incorporated
    *保留所有权利。
    *
    *
    只要
    符合以下条件*、允许以源代码和二进制形式重新分发和使用:
    *
    *源代码的重新分发必须保留上述版权
    声明*、此条件列表和以下免责声明。
    *
    ***二进制形式的再发行必须在
    
    *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。
    *
    ***未经
    
    事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。
    *
    *本软件由版权所有者和贡献者"按原样"提供
    *、
    
    不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或
    *贡献者都不对任何直接、间接、偶然、特殊、
    *模范、 或相应的损害(包括但不限于
    *采购替代产品或服务;丧失使用、数据或利润;
    *或业务中断)、但出于任何责任理论
    、*无论是在合同中、严格责任还是由于
    使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他)
    、*即使已获悉可能会发生此类损坏。
    //
    /*
    === timer.c ======
    *
    */
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include 
    
    #include 
    #include 
    
    /* TODO:是否将此外设寄存器定义移至目录? */
    typedef volatile struct ti_catalog_msp432_peripheral_timers_TimerRegs{
    uint16控制;
    uint16 cctl_0;
    uint16 cctl_1;
    uint16 cctl_2;
    uint16 cctl_3;
    uint16 cctl_4;
    uint16 cctl_5;
    uint16 cctl_6;
    uint16计数;
    uint16 cc_compare_0;
    uint16 cc_compare_1;
    uint16 cc_compare_2;
    uint16 cc_compare_3;
    uint16 cc_compare_4;
    uint16 cc_compare_5;
    uint16 cc_compare_6;
    uint16扩展;
    UINT16保留[6];
    uint16矢量;
    }ti_catalog_msp432_peripheral_timers_TimerRegs;
    
    #include "package/internal/Timer.xdc.h"
    
    #define mc 0x0020 /*模式、控制=连续递增计数*/
    #define TxCLR 0x0004 /*清除计时器计数器*/
    #define CCIE 0x0010 /*比较中断使能*/
    #define CCIFG 0x0001 /*比较中断挂起标志*/
    #define TSSEL 0x0100 /*源选择= ACLK */
    #define ID_MASK 0x00C0 /*输入分频器位掩码*/
    
    #define TIMER_CONTRAL_START MC
    #define TIMER_CONTRAL_CLEAR TxCLR
    #define TIMER_CONTRAL_DEFAULT TSSEL
    #define TIMER_COMPARE_INTR_ENABLE CCIE
    #define TIMER_COMPARE_INTR_PENDING CCIFG
    
    #define TIMER_deleted 0
    #define BAD_TIMER_ID 1
    #define NO_TIMER_AVAIL 2
    #define NO_HWI_OBJ 3
    #define BAD_PERIOD 4
    
    #define READ_DERAT等待 时间 允许的10 /*# MCLK 周期数
    计数的背对背读取*/
    
    #define SYS_PERI_HALTCTL_REG 0xE004300C /*外设停止控制寄存器*/
    #define REG (x)(*(volatile unsigned *)(x))))
    
    /*
    *=== Timer_getAvailMask ===
    */
    UINT Timer_getAvailMask()
    {
    返回(Timer_module->availmMask);
    }
    
    /*
    === Timer_getNumTimers ===
    *获取器件上可用的计时器外设数。
    /
    UINT Timer_getNumTimers ()
    {
    返回(Timer_numTimerDevices);
    }
    
    /*
    === Timer_getStatus ===
    *获取计时器的空闲/未使用状态。
    */
    Timer_Status Timer_getStatus (UINT timerId)
    {
    assert_isTrue (timerId < Timer_numTimerDevices、空);
    
    if (Timer_module->availmMask &(0x1 << timerId)){
    返回(Timer_Status_free);
    }
    否则{
    返回(Timer_Status_Inuse);
    }
    }
    
    /*
    === Timer_getMaxTicks ===
    //
    uint32 Timer_getMaxTicks (Timer_Object * obj)
    {
    返回(0x0000FFFF / obj->period);
    }
    
    //*
    === Timer_setAvailMask ===
    //
    bool Timer_setAvailMask (UINT mask)
    {
    UINT I;
    UINT 键;
    uINT tmpMask;
    
    KEY = Hwi_disable();
    tmpMask = mask;
    对于(i = 0;i < Timer_numTimerDevices;i++){
    /*检查遮罩是否正在将任何当前使用的定时器设置为可用*/
    if ((tmpMask & 0x1)&&(Timer_module->handles[i]!= NULL)){
    Hwi_restore (key);
    返回(false);
    }
    tmpMask = tmpMask >> 1;
    }
    timer_module->availmask = mask;
    Hwi_restore (key);
    
    返回(真);
    }
    
    /*
    ==== Timer_setNextTick ===
    *对计时器的中断阈值进行编程、以进行下一个节拍。
    //
    void Timer_setNextTick (Timer_Object * obj、uint32节拍)
    {
    TI_catalog_msp432_peripheral_timers_TimerRegs *计时器;
    uint32 newPeriod = obj-> period * ticks;
    UINT NEXT;
    UINT Previous;
    立即使用;
    
    /*获取计时器基址*/
    计时器=(ti_catalog_msp432_peripheral_timers_TimerRegs *)
    timer_module->device[obj->id].baseAddr;
    
    Previous = obj->pretingThreshold;
    
    /*下一个是相对于保存的当前计数*/
    next = obj->savedCurrent Count + newPeriod;
    
    /*设置下一个中断的比较阈值*/
    Timer->cc_compare_0 =下一个;
    
    /*
    *只有在计时器*至*阈值时,MSP432计时器才会中断。
    *因此我们必须检查以确保阈值设置不会太晚-
    *如果设置得太晚,则计时器计数将需要在下一个计时器计数之前换行
    *中断被触发。 为了避免这种情况、请在写入下一个之后
    *中断阈值、我们读取当前计数、如果是中断
    *根据当前计数设置的阈值太晚、我们再次写入
    *连接到计时器以触发立即中断。
    *
    *对于"下一个"阈值大于"上一个"的情况、
    *计时器不会在下一个目标计时中断之前换行。 这种情况
    *创建下面显示的三个区域(A、B、C)、其中电流"现在"
    * count 将驻留:
    *
    * FFFF | -
    * | B
    * |<-- 下一步 -
    * | A
    * |<-- 上一页-
    * | C
    * 0 | -
    *
    * A -"现在"大于"上一个"、小于"下一个":
    *这是"正常"区域、在该区域中阈值在之前设置
    *下一个阈值、无需调整。
    *
    * B -"现在"大于"下一步":已设置阈值
    *稍后、立即触发中断。
    *
    * C -"现在"小于"上一个":阈值设置为延迟、触发
    *立即中断。
    *
    *对于"下一个"阈值小于"上一个"的情况、
    *计时器计数预计会在下一个节拍中断之前结束。
    *这将创建下面显示的三个区域(D、E、F)、其中电流为
    *"现在"计数将驻留在:
    *
    * FFFF | -
    * | D
    * |<-- 上一页-
    * | F
    * |<-- 下一步 -
    * | e
    * 0 | -
    *
    * D -"现在"大于"上一个":这是"正常"
    在下一个阈值之前设置阈值的区域、
    *不需要调整。
    *
    * E -"现在"小于"下一步":这是另一个"正常"区域、
    *其中阈值设置得足够早、没有调整
    *需要。
    *
    * F -"现在"大于或等于"下一个"且小于
    *"previous":阈值设置得太晚、立即触发中断。
    *
    
    /*获取当前计时器计数*/
    现在= Timer_getCount (obj);
    
    /*如果不希望换行为零... *
    如果(下一个>上一个){
    
    /*情况"B":现在大于或等于下一个、立即中断*/
    if (现在>= next){
    timer->cctl_0 |= CCIFG;
    }
    
    /*案例"C":现在<上一个、计数已结束、立即中断*/
    否则{
    如果(现在<上一个){
    timer->cctl_0 |= CCIFG;
    }
    }
    
    
    /*否则,正在等待通过零的换行... *
    否则{
    
    /*案例 F:现在介于下一个和上一个之间、立即中断*/
    如果((现在<上一个)&&(现在>=下一个){
    timer->cctl_0 |= CCIFG;
    }
    }
    }/*
    
    
    === Timer_Module_startup ===
    *对所有静态创建和构造
    的*定时器调用 postInit 以初始化它们。
    */
    int Timer_Module_startup (int status)
    {
    int i;
    Timer_Object *对象;
    
    if (Timer_starpNeeded){
    对于(i = 0;i < Timer_numTimerDevices;i++){
    obj = Timer_module->handles [i];
    /*如果定时器是静态创建/构造的*/
    if ((obj!= NULL)&&(obj->staticInst)){
    Timer_postInit (obj、NULL);
    }
    }
    
    
    返回(Startup_DONE);
    }
    
    /*
    ==== Timer_startup ===
    *在调用 main()后在这里。 从 BIOS_start()调用。
    */
    void Timer_startup ()
    {
    int i;
    Timer_Object *对象;
    
    if (Timer_starpNeeded){
    对于(i = 0;i < Timer_numTimerDevices;i++){
    obj = Timer_module->handles [i];
    /*如果定时器是静态创建/构造的*/
    if ((obj!= NULL)&&(obj->staticInst)){
    if (obj->startMode = Timer_StartMode_Auto){
    Timer_start (obj);
    }
    }
    
    }
    }/*
    
    
    === Timer_getHandle ===
    */
    Timer_Handle Timer_getHandle (UINT id)
    {
    assert_isTrue ((id < Timer_numTimerDevices)、NULL);
    返回(Timer_module->handle [id]);
    }
    
    /*
    === timer_instance_init ===
    * 1. 根据 id
    * 2选择计时器。 将计时器标记为正在使用
    中* 3. 使用参数*
    4初始化计时器 obj。 如果 tickFxn = NULL
    * 5、则创建 Hwi。 初始化计时器
    * 6. 配置计时器(wrt 仿真、频率等)
    * 7. 设置周期
    * 8. Timer_start ()
    *
    /
    int Timer_instance_init (Timer_Object * obj、int id、Timer_Functr tickFxn、const Timer_Params *参数、Error_Block * EB)
    {
    INT 状态;
    UINT 键;
    int i;
    Hwi_Params HwiParams;
    UINT tempId = 0xFFFF;
    
    if (id >= Timer_numTimerDevices){
    if (id!= Timer_any){
    ERROR_RAISE (EB、Timer_E_INvalidTimer、id、0);
    返回(BAD_TIMER_ID);
    }
    }
    
    KEY = Hwi_disable();
    
    if (id = Timer_any){
    对于(i = 0;i < Timer_numTimerDevices;i++){
    IF (((Timer_anyMask &(1 << I)))
    &&(Timer_module->availMask &(1 << i)){
    timer_module->availMask &&μ~(1 << i);
    tempId = I;
    中断;
    }
    }
    
    否则,如果(Timer_module->availmMask &(1 << id)){
    timer_module->availMask &=~(1 << id);
    tempId = id;
    }
    
    Hwi_restore (key);
    
    obj->staticInst = false;
    
    if (tempId = 0xFFFF){
    ERROR_RAISE (EB、Timer_E_notavailable、id、0);
    返回(NO_TIMER_AVAIL);
    }
    否则{
    obj->id = tempId;
    }
    
    if (params->clockSource == Timer_Source_ACLK){
    obj->controlRegInit = 0x0100 | params->inputDivider;
    }
    否则、如果(params->clockSource == Timer_Source_SMCLK){
    obj->controlRegInit = 0x0200 | params->inputDivider;
    }
    否则、如果(params->clockSource == Timer_Source_external){
    obj->controlRegInit = 0x0000 | params->inputDivider;
    }
    否则、如果(params->clockSource == Timer_Source_external_inverted){
    obj->controlRegInit = 0x0300 | params->inputDivider;
    }
    否则{
    返回(NO_HWI_OBJ);
    }
    
    obj->runMode = params->runMode;
    obj->startMode = params->startMode;
    obj->period = params->period;
    obj->periodType = params->periodType;
    obj->arg = params->arg;
    obj->intNum = Timer_module->device[obj->id].intNum;
    obj->tickFxn = tickFxn;
    obj->pretThreshold = 0;
    obj->savedCurrent Count = 0;
    obj->rollovers = 0;
    obj->synchronous = params->synchronous;
    
    if (params->extFreq.lo =0){
    if (params->clockSource == Timer_Source_ACLK){
    obj->frequency .lo = ClockFreqs_ACLK;
    }
    否则、如果(params->clockSource == Timer_Source_SMCLK){
    obj->frequency .lo = ClockFreqs_SMCLK;
    }
    }
    否则{
    obj->frequency .lo = params->extFreq.lo;
    }
    obj->frequency .hi = params->extFreq.hi;
    
    obj->inputDivider = params->inputDivider;
    obj->inputDividerExp= params->inputDividerExp;
    
    if (obj->tickFxn){
    if (params->hwiParams){
    hwi_Params_copy (&hwiParams、(params->hwiParams));
    }
    否则{
    hwi_Params_init (&hwiParams);
    }
    
    hwiParams.arg =(UARg) obj->id;
    
    if (obj->runMode = Timer_RunMode_Continuous){
    if (params->festing == true){
    obj->hwi = hwi_create (obj->intNum、Timer_periodicNestStub、
    hwiParams、EB);
    }
    否则{
    obj->hwi = hwi_create (obj->intNum、Timer_periodicStub、
    hwiParams、EB);
    }
    }
    否则{
    if (params->festing == true){
    obj->hwi = hwi_create (obj->intNum、Timer_oneShotNestStub、
    hwiParams、EB);
    }
    否则{
    obj->hwi = hwi_create (obj->intNum、Timer_oneShotStub、
    hwiParams、EB);
    }
    }
    
    if (obj->hwi == NULL){
    返回(NO_HWI_OBJ);
    }
    }
    否则{
    obj->hwi = NULL;
    }
    
    timer_module->handles [obj->id]= obj;
    
    Timer_initDevice (obj);
    
    if (obj->periodType = Timer_PeriodType_micros){
    if (!Timer_setPeriodMicroSecs (obj、obj-> period)){
    ERROR_RAISE (EB、Timer_E_CANnotSupport、obj-> Period、0);
    Hwi_restore (key);
    返回(BAD_PERIOD);
    }
    }
    
    状态= Timer_postInit (obj、EB);
    
    if (status){
    返回(状态);
    }
    
    if (obj->startMode = Timer_StartMode_Auto){
    Timer_start (obj);
    }
    
    返回(0);
    }/*
    
    
    ==== timer_reconfig ===
    *
    ** 1. 使用参数初始化 obj
    * 2. timer_init()
    * 3. 配置计时器(wrt 仿真、频率等)
    * 4. 设置周期
    * 5. Timer_start ()
    *
    /
    void Timer_reconfig (Timer_Object * obj、Timer_Functr tickFxn、常量
    Timer_Params *参数、Error_Block * EB)
    {
    obj->controlRegInit = params->controlRegInit | params->inputDivider;
    obj->runMode = params->runMode;
    obj->startMode = params->startMode;
    obj->periodType = params->periodType;
    obj->pingThreshold = params->pingThreshold;
    obj->rollovers = 0;
    obj->savedCurrent Count = 0;
    obj->synchronous = params->synchronous;
    obj->inputDividerExp= params->inputDividerExp;
    if (obj->periodType = Timer_PeriodType_micros){
    if (!Timer_setPeriodMicroSecs (obj、params->period)){
    ERROR_RAISE (EB、Timer_E_cannnotSupport、params->period、0);
    }
    }
    否则{
    obj->period = params->period;
    }
    
    obj->arg = params->arg;
    obj->tickFxn = tickFxn;
    
    if (params->extFreq.lo){ /*(extFreq.hi 被忽略)*/
    obj->frequency .lo = params->extFreq.lo;
    }
    
    Timer_postInit (obj、EB);
    
    if (obj->startMode = Timer_StartMode_Auto){
    Timer_start (obj);
    }
    }
    
    /*
    === timer_instance_finalize ===
    */
    void Timer_instance_finalize (Timer_Object * obj、int status)
    {
    UINT 键;
    
    /*注意:下面的开关中掉电是有意的*/
    开关(状态){
    /* Timer_delete ()*/
    案例定时器_已删除:
    
    /* setPeriodMicroSecs 失败*/
    案例 BAD_PERIOD:
    Timer_initDevice (obj);
    if (obj->hwi){
    hwi_delete (&obj->hwi);
    }
    
    /* Hwi 创建失败*/
    案例 NO_HWI_OBJ:
    
    /*计时器不可用*/
    案例 NO_TIMER_AVAIL:
    
    /*无效的计时器 ID */
    案例 BAD_TIMER_ID:
    
    默认值:
    中断;
    }
    
    KEY = Hwi_disable();
    timer_module->availMask |=(0x1 <<obj->id);
    timer_module->handles [obj->id]= NULL;
    Hwi_restore (key);
    }
    
    /*
    ==== Timer_start ====
    *
    ** 1. Hwi_disable()
    * 2. 清除计数器
    * 3. 清除计时器中断标志
    * 4. 设置下一个比较阈值(每个配置的周期)
    * 5. 启用计时器中断
    * 6. 启动计时器
    * 7. Hwi_restore ()
    *
    /
    void Timer_start (Timer_Object * obj)
    {
    TI_catalog_msp432_peripheral_timers_TimerRegs *计时器;
    UINT 键;
    
    计时器=(ti_catalog_msp432_peripheral_timers_TimerRegs *)
    timer_module->device[obj->id].baseAddr;
    
    KEY = Hwi_disable();
    
    /*重置计时器计数*/
    timer -> control |= timer_control_clear;
    
    /*清除计时器中断标志*/
    TIMER->cctl_0 &=~TIMER_COMPARE_INTR_PENDING;
    
    /* 0之前的阈值*/
    obj->pretThreshold = 0;
    
    /*为下一个中断设置比较阈值*/
    Timer->cc_compare_0 = obj->period;
    
    /*启用捕捉/比较0中断*/
    timer->cctl_0 |= timer_compare_intR_enable;
    
    /*启动计时器*/
    timer -> control |= timer_control_start;
    
    Hwi_restore (key);
    }
    
    /*
    ==== timer_stop ======
    *
    ** 1. 停止计时器
    * 2. 禁用计时器中断
    *
    /
    void Timer_stop (Timer_Object * obj)
    {
    TI_catalog_msp432_peripheral_timers_TimerRegs *计时器;
    
    计时器=(ti_catalog_msp432_peripheral_timers_TimerRegs *)
    timer_module->device[obj->id].baseAddr;
    
    /*停止计时器*/
    timer->control = obj->controlRegInit | obj->inputDivider;
    
    /*禁用捕捉/比较0中断*/
    timer->cctl_0 &=~timer_compare_intR_enable;
    
    /*清除计时器中断标志*/
    timer->cctl_0 &=~timer_compare_intR_pending;
    }
    
    //
    *=== timer_setPeriod ===
    *
    ** 1. 停止计时器
    * 2. 在 timer obj 中设置周期值
    *
    /
    void Timer_setPeriod (Timer_Object * obj、uint32 period)
    {
    Timer_stop (obj);
    obj->period = period;
    }
    
    //*
    === Timer_setPeriodMicroSecs ===
    *
    ** 1. 停止计时器
    * 2. 计算计数
    * 3. 在 timer obj
    *
    */
    bool Timer_setPeriodMicroSecs (Timer_Object * obj、uint32 period)
    {中设置新的周期值
    Types_FreqHz freqHz;
    uint32计数;
    uint32 freqKHz;
    
    Timer_stop (obj);
    
    Timer_getFreq (obj、&freqHz);
    freqKHz = freqHz.lo / 1000;
    
    if (Timer_checkOverflow (freqKHz、Period/1000)){
    返回(false);
    }
    否则{
    计数=(freqKHz *周期)/ 1000;
    obj->period =计数;
    obj->periodType = Timer_PeriodType_Counts;
    return (true);
    }
    }
    
    /*
    === TIMER_TRIGGER ===
    *
    ** 1. 停止计时器
    * 2. 写入 insts
    * 3的周期。 启动计时器。
    *
    */
    void Timer_trigger (Timer_Object * obj、uint32 insts)
    {
    UINT 键;
    
    /*请按照正确的程序进行动态期间更改*/
    KEY = Hwi_disable();
    
    /*为扫描定时器强制 SMCLK */
    obj->controlRegInit &=~0x0100; /*清除 ACLK 位*/
    obj->controlRegInit |= 0x0200; /*启用 SMCLK */
    
    Timer_stop (obj);
    
    Timer_setPeriod (obj、insts);
    Timer_start (obj);
    Hwi_restore (key);
    }
    
    /*
    ==== Timer_getPeriod ===
    */
    uint32 Timer_getPeriod (Timer_Object * obj)
    {
    return (obj->period);
    }
    
    //*
    ==== Timer_getCount ===
    */
    uint32 Timer_getCount (Timer_Object * obj)
    {
    TI_catalog_msp432_peripheral_timers_TimerRegs *计时器;
    UINT 优先;
    UINT second;
    
    计时器=(ti_catalog_msp432_peripheral_timers_TimerRegs *)
    timer_module->device[obj->id].baseAddr;
    
    /*如果定时器的源时钟与 CPU 同步:只读计数一次*/
    if (obj->synchronous){
    First = timer -> count;
    }
    
    /*否则、必须执行多次读取以避免可能的伪值*/
    否则{
    /*读取两次、需要相同的值或在读取延迟内*/
    执行{
    First = timer -> count;
    秒=计时器->计数;
    } while ((first!= second)&&((second - first)> read_latency));
    }
    
    返回((((UINT32)优先)& 0xFFFF);
    }
    
    /*
    ===== Timer_oneShotStub ===
    */
    void Timer_oneShotStub (UArg arg)
    {
    Timer_Object *对象;
    obj = Timer_module->句柄[(UINT) arg];
    
    /*停止计时器(并禁用此中断源)*/
    Timer_stop (obj);
    
    /*调用 tick 函数*/
    obj->tickFxn (obj->arg);
    }
    
    /*
    ===== Timer_oneShotNestStub ===
    */
    void Timer_oneShotNestStub (UArg arg)
    {
    Timer_Object *对象;
    obj = Timer_module->句柄[(UINT) arg];
    
    /*停止计时器(并禁用此中断源)*/
    Timer_stop (obj);
    
    /*启用中断以允许嵌套*/
    Hwi_enable();
    
    /*调用 tick 函数*/
    obj->tickFxn (obj->arg);
    
    /*禁用中断以解除 ISR 的干扰*/
    Hwi_disable();
    }
    
    /*
    ===== Timer_periodicStub ===
    */
    void Timer_periodicStub (UArg arg)
    {
    Timer_Object *对象;
    TI_catalog_msp432_peripheral_timers_TimerRegs *计时器;
    
    obj = Timer_module->句柄[(UINT) arg];
    
    计时器=(ti_catalog_msp432_peripheral_timers_TimerRegs *)
    timer_module->device[obj->id].baseAddr;
    
    /*清除计时器中断标志*/
    TIMER->cctl_0 &=~TIMER_COMPARE_INTR_PENDING;
    
    /*用于动态模式锁存预防性阈值和检测滚动*
    if (obj->runMode = Timer_RunMode_dynamic){
    /*
    *如果当前阈值小于预防阈值
    *则发生了翻转。
    *
    *如果当前阈值等于前推阈值、则计时器
    *计数换行并生成新中断;递增
    *用于恢复勾选的翻转计数。
    *
    if (obj->deleThreshold >= timer->cc_compare_0){
    obj->rollovers += 1;
    }
    
    /*保存先前的阈值*/
    obj->deleThreshold = timer ->cc_compare_0;
    }
    否则{
    /*保存先前的阈值*/
    obj->deleThreshold = timer ->cc_compare_0;
    obj->savedCurrent Count = timer->cc_compare_0;
    
    /*设置下一个中断阈值;如果设置太晚、立即中断*/
    Timer_setNextTick (obj、1);
    }
    
    /*调用 tick 函数*/
    obj->tickFxn (obj->arg);
    }
    
    /*
    ===== Timer_periodicNestStub ===
    */
    void Timer_periodicNestStub (UArg arg)
    {
    Timer_Object *对象;
    TI_catalog_msp432_peripheral_timers_TimerRegs *计时器;
    
    obj = Timer_module->句柄[(UINT) arg];
    
    计时器=(ti_catalog_msp432_peripheral_timers_TimerRegs *)
    timer_module->device[obj->id].baseAddr;
    
    /*清除计时器中断标志*/
    TIMER->cctl_0 &=~TIMER_COMPARE_INTR_PENDING;
    
    /*用于动态模式锁存预防性阈值和检测滚动*
    if (obj->runMode = Timer_RunMode_dynamic){
    /*
    *如果当前阈值小于预防阈值
    *则发生了翻转。
    *
    if (obj->deleThreshold > timer->cc_compare_0){
    obj->rollovers += 1;
    }
    
    /*保存先前的阈值*/
    obj->deleThreshold = timer ->cc_compare_0;
    }
    否则{
    /*保存先前的阈值*/
    obj->deleThreshold = timer ->cc_compare_0;
    obj->savedCurrent Count = timer->cc_compare_0;
    
    /*设置下一个中断阈值;如果设置太晚、立即中断*/
    Timer_setNextTick (obj、1);
    }
    
    /*允许嵌套其他中断... *
    timer->cctl_0 &=~timer_compare_intR_enable;
    Hwi_enable();
    
    /*调用 tick 函数*/
    obj->tickFxn (obj->arg);
    
    /*禁用中断以解除 ISR 的干扰*/
    Hwi_disable();
    timer->cctl_0 |= timer_compare_intR_enable;
    }
    
    //
    *=== Timer_getExpiredCounts ===
    *
    *该 API 由 TimestampProvider 用作检索时间戳
    *的一部分,它使用计时器和计时器。 它返回自
    *上次处理的计时器中断以来的过期计数。
    *
    *必须在禁用中断的情况下调用此 API;TimestampProvider
    *必须在检索节拍数并调用此
    * API 时禁用中断。
    *
    * TimestampProvider 使用32位计时器和32位节拍数来跟踪
    *时间戳。 节拍数来自时钟模块、或
    *存储在 TimestampProvider 的模块状态、
    并在计时器到期时由 ISR 递增*。
    *
    *对于 MSP432、我们有16位计时
    器、并使用计时器比较功能*在达到特定阈值计数时触发中断。
    在达到
    *下一个阈值的过程中、*计时器计数可能会翻转(变为零)。 我们需要将此翻转作为
    *确定过期计数的一部分。
    *
    *我们还需要处理
    计时器使用较大周期值的情况*、并且计时器正在快速计时(例如、通过
    SMCLK 选择的 CPU *速率)。 在这种情况下、
    *在定时器达到阈值之前禁用中断、然后
    *定时器达到阈值计数并断言中断、
    然后*在本例程中读取中断之前继续向上计数。 如果
    *计时器滚过零、那么我们需要知道有一个中断
    *暂挂、否则我们会报告低计数、而周期加
    *低计数则会有所不同。
    *
    *为了确保捕获中断、我们对中断标志进行采样、读取
    * count、然后再次对中断标志进行采样:
    *
    标志1内
    * 计数
    * intrFlag2
    *
    *如果设置了 intrFlag1、则我们知道我们已达到周期计数、
    *需要将其添加到报告的计数。 如果设置了 intrag2、但
    * intrag1未设置、则我们知道计时器刚刚达到阈值、只
    需*报告周期计数。
    *
    *如果两个中断标志都未设置、则我们可以
    通过*将计数与之前的中断阈值(保存在
    *计时器对象中)进行比较来计算过期计数。 如果当前计数大于或等于
    *先前的阈值、则我们知道没有计数器翻转
    *、过期计数仅为
    :*
    结果=计数-推诿阈
    值*
    如果当前计数小于前一阈值、则我们知道
    自上一个 ISR 以来已发生*计数器翻转。 在这种情况下、
    *过期计数必须包括上一阈值和
    *零之间的计数、加上滚动超过零后的任何计数:
    *
    结果=(0 -前推特雷什)+计数
    *
    *用于将当前计数与前一阈
    
    值进行比较的类似逻辑*可用于我们知道已设置了 intrFlag1的情况,并且我们*需要计算要添加到周期计数的计数。
    *
    /
    uint32 Timer_getExpiredCounts (Timer_Object * obj)
    {
    TI_catalog_msp432_peripheral_timers_TimerRegs *计时器;
    uint32结果32;
    uint32 count32;
    uint32阈值32;
    uint32周期32;
    uint32前推32;
    bool intrFlag1;
    bool intrFlag2;
    
    计时器=(ti_catalog_msp432_peripheral_timers_TimerRegs *)
    timer_module->device[obj->id].baseAddr;
    
    intrFlag1 =定时器->cctl_0和定时器_COMPARE_INTR_PENDING;
    count32 = Timer_getCount (obj)& 0xFFFF;
    intrFlag2 = timer ->cctl_0 & timer_compare_intR_pending;
    prep32 = obj->pingThreshold & 0xFFFF;
    
    /*在读取计数前中断挂起? *
    if (intrFlag1){
    THRESH32 =定时器->cc_compare_0 & 0xFFFF;//中断的阈值
    period32 = Timer_getPeriod (obj)& 0xFFFF;//周期计数
    
    /*达到阈值;尚未通过零折返*/
    if (count32 >= thresh32){
    result32 =(count32 - thresh32)+ period32;
    }
    达到/*阈值;计数已换至零*/
    否则{
    result32 =(0x10000 - thresh32)+ count32 + period32;
    }
    }
    
    /*新中断现在暂挂,何时未在读取计数之前*/
    否则、如果(intrFlag2){
    result32 = Timer_getPeriod (obj)& 0xFFFF;/*返回周期计数*/
    }
    
    /*未达到中断阈值;检查是否已通过零打包*/
    否则、如果(count32 >= pste32){
    result32 = count32 - tpste32;
    }
    
    /*未达到中断阈值;计数已换至零*/
    否则{
    result32 =(0x10000 -前推32)+ count32;
    }
    
    返回(result32);
    }
    
    /*
    ==== Timer_getExpiredTicks ===
    //
    uint32 Timer_getExpiredTicks (Timer_Object * obj、uint32 tickPeriod)
    {
    uint32刻度;
    
    节拍数= Timer_getExpiredCounts (obj)/ tickPeriod;
    
    返回(节拍数);
    }
    
    /*
    === Timer_getCurrentTick ===
    *使用48位精度。
    *在32.768 KHz 时、即8、589、934、592秒
    *或节拍前272年的计算错误
    */
    uint32 Timer_getCurrentTick (Timer_Object * obj、bool saveFlag)
    {
    uint32的推广活动;
    UINT 电流计数;
    uint32 tick;
    uint32 s1;
    UINT r;
    
    当前计数= Timer_getCount (obj);
    
    滚动=obj->滚动;
    
    if (currCount < obj->preffThreshold){
    滚动+= 1;
    }
    
    S1 =翻转/ obj->周期; /* 48位的高32 */
    r =滚动- s1 * obj->周期; /*上除法的余数*/
    tick =(((uint32) r << 16)+ currCount)/ obj-> period;//较低的16位*/
    Tick =((UINT32)(s1 & 0xFFFF)<< 16)+(Tick & 0xFFFF);
    
    /*保存供 Timer_setNextTick()稍后使用*/
    if (saveFlag!= 0){
    obj->savedCurrent Count = tick * obj-> period;
    }
    
    返回(tick);
    }
    
    /*
    ==== Timer_getFreq ===
    */
    void Timer_getFreq (Timer_Object *、Types_FreqHz *频率)
    {
    UINT 分频器;
    
    switch (obj->controlRegInit & ID_MASK){
    案例 Timer_ID_1:
    分频器= 1;
    中断;
    
    案例 Timer_ID_2:
    分频器= 2;
    中断;
    
    案例 Timer_ID_4:
    分频器= 4;
    中断;
    
    默认值:
    分频器= 8;
    中断;
    }
    
    divider *=(obj->inputDivdiverExp+1);
    
    FREQ->lo = obj->frequency .lo / divider;
    FREQ->HI = 0;
    }
    
    /*
    === Timer_getFunc ===
    */
    Timer_Functr Timer_getFunc (Timer_Object * obj、UArg* arg)
    {
    *arg = obj->arg;
    返回(obj->tickFxn);
    }/*
    
    
    === Timer_setFunc ===
    */
    void Timer_setFunc (Timer_Object * obj、Timer_FuncPtr fxn、UArg arg)
    {
    obj->tickFxn = fxn;
    obj->arg = arg;
    }
    
    /*
    === Timer_checkOverflow ====
    //
    bool Timer_checkOverflow (uint32 a、uint32 b)
    {
    返回((b > 0)&&(a > Timer_MAX_PERIODE/b));
    }
    
    /*=== Timer_initDevice =====
    *
    ** 1. 停止计时器(将控制寄存器设置回默认值)
    * 2. 禁用计时器中断
    * 3. 清除所有挂起的中断
    * 4. 清除计数器
    *
    /
    void Timer_initDevice (Timer_Object * obj)
    {
    TI_catalog_msp432_peripheral_timers_TimerRegs *计时器;
    UINT 键;
    
    计时器=(ti_catalog_msp432_peripheral_timers_TimerRegs *)
    timer_module->device[obj->id].baseAddr;
    
    KEY = Hwi_disable();
    
    /*停止计时器;设置默认控制寄存器*/
    timer->control = mc | obj->controlRegInit;
    timer->expansion = obj->inputDivExp;
    
    /*清除计时器中断标志*/
    TIMER->cctl_0 &=~TIMER_COMPARE_INTR_PENDING;
    
    /*重置计时器计数*/
    timer -> control |= timer_control_clear;
    
    /*在 CPU 暂停时冻结计时器*/
    reg (SYS_PERI_HALTCTL_REG)|= 1 << obj->id;
    
    Hwi_restore (key);
    }
    
    /*
    ==== Timer_postInit ===
    //
    int Timer_postInit (Timer_Object * obj、Error_Block * EB)
    {
    UINT 键;
    
    KEY = Hwi_disable();
    
    Timer_initDevice (obj);
    
    timer_setPeriod (obj、obj->period);
    
    Hwi_restore (key);
    
    返回(0);
    }
    

    如果有人有一个指示如何重新构建 TI-RTOS/Energia 的指针、这样我就可以减少 TI-RTOS 可用的定时器数量、请注意。

    谢谢!

    Rob

     

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    哎呀! 您应该在 ta_up.c 中注释掉 Interrupt_enableSlepOnIsrExit();

    Rob
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我在原计划中注意到的另一点是: 如果我将优先级提高到32以下的任何地方, 就像这样; 

      Hwi_setPriority (INT_ADC14、31);

    我卡在 Hwi.c 中

    void Hwi_exHandler (UINT * exstack、UINT LR)
    {
    Hwi_module->exACTIVe[0]= true;
    
    /*如果没有插入异常处理程序,请在此处旋转*/
    while (Hwi_excHandlerFunc == NULL ){
    ;
    }
    
    Hwi_exHandlerFunc (exstack、LR);
    }
    

    如果插入位置没有异常、则会在此处旋转。

    Rob

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

    大家好、

    我还不知道为什么、但至少在此时、这是有效的。  中断的优先级似乎是帮助它进入此状态的一件事情。  我现在要将这个问题标记为已解决。  代码如下:

    extern "C"{
    #include 
    };
    
    //按 reset 时,设置例程运行一次:
    void setup(){
    Serial.begin(115200);
    adc14_();
    
    startSampling();
    }//
    
    循环例程连续运行:
    void loop(){
    静态 int i=0;
    //delay (500);
    serial.print (i++);
    serial.print (":");
    serial.print (TA3R);
    serial.print (");
    serial.println ("Hello from Copy (2) of ADC14_!");
    }
    

    和.c 文件:

    /*
    --------------------------------
    * MSP432 DriverLib - v4_00_00_11
    *----------------------
    *
    *-版权所有-、BSD、BSD
    *版权所有(c) 2017、德州仪器(TI)公司
    *保留所有权利。
    *
    *
    只要
    符合以下条件*、允许以源代码和二进制形式重新分发和使用:
    *
    *源代码的重新分发必须保留上述版权
    声明*、此条件列表和以下免责声明。
    *
    ***二进制形式的再发行必须在
    
    *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。
    *
    ***未经
    
    事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。
    *
    *本软件由版权所有者和贡献者"按原样"提供
    *、
    
    不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或
    *贡献者都不对任何直接、间接、偶然、特殊、
    *模范、 或相应的损害(包括但不限于
    *采购替代产品或服务;丧失使用、数据或利润;
    *或业务中断)、但出于任何责任理论
    、*无论是在合同中、严格责任还是由于
    使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他)
    、*即使已获悉可能会发生此类损坏。
    *--/copyrights-*/*
    MSP432 ADC14 -不重复的多通道采样
    *
    说明:在此代码示例中,
    用户 A DriverLib API 演示了能够扫描多个* ADC 通道的功能。 转换
    *内存寄存器 ADC_MEM0 - ADC_MEM3被配置为分别读取
    A6、A12、A10、A8的转换*结果。 转换被启用、然后使用
    一个软件切换来*切换采样。 重复模式未启用、仅采样
    *发生一次(用户应暂停调试器以观察
    *结果)。 在采集完最终样本后、
    * ADC_MEM3的中断被触发、结果存储在 resultsBuffer 缓冲区中。
    *
    * MSP432P401
    * ----------
    * /|\| |
    * || |
    * -|RST P4.7 |<-- A6 (模拟输入、测量值、实际值)
    * | P4.1 |<-- A12 (模拟输入、测量值、虚数)
    * | P4.3 |<-- A10 (模拟输入、基准实数)
    * | P4.5 |<-- A8 (模拟输入、基准虚数)
    * | |
    * | |
    *
    4.1、4.3、4.5、4.7是最终所需的引脚。
    *
    *作者:Timothy Logan
    *这是 Rob Frohne 修改的、以在8kHz 采样率下执行多个 ADC。
    秘书长的报告 /#include
    
    #define SAMPLE_LENGTH 128
    
    uint16_t refRe[SAMPLE_LENG];
    uint16_t refI[SAMPLE_LENG];
    uint16_t measure[SAMPLE_LENGTH]
    
    
    
    ;extern volatile bodyADC;bendool Measurement = false;int numberFrefestencyotiM[SAMPLE_LENGTH];frequencyIndex
    float;frequencyIndex
    volatile botonool ADC = false;
    
    void ADC14_IRQHandler (void);
    
    int adc14_(void)
    {
    
    /*停止 WDT */
    WDT_A_HOLDTimer();
    
    //寄存器中断
    Hwi_Params 参数;
    Hwi_Params_init (params);
    Hwi_create (INT_ADC14、ADC14_IRQHandler、&params、0);
    Hwi_setPriority (INT_ADC14、60);
    
    //Interrupt_enableSlepOnIsrExit();
    RESPos = 0;
    //设置为 Vcore1
    /*
    PCM_setCoreVoltageLevel (PCM_VCORE1);
    
    //设置为使用 DCDC
    //PCM_setPowerState (PCM_AM_DCDC_VCORE1);
    
    //初始化时钟系统
    因为我们需要 Energia 时钟设置、所以对这些内容进行了注释。 。
    *相应调整计时器的数据结构。 时间
    *转换之间的时间可能是这些转换的四倍
    *参数、但这似乎是实现一切的最简单方法
    *立即一起玩。
    //FlashCtl_setWaitState (FLASH_BANK0、2);
    //FlashCtl_setWaitState (FLASH_BANK1、2);
    PCM_setPowerState (PCM_AM_DCDC_VCORE1);
    cs_setDCOCenteredFrequency (CS_DCO_FREQUENCY);
    //CS_setDCOFrequency (24000000);
    CS_initClockSignal (CS_MCLK、CS_DCOCLK_SELECT、CS_Clock_divider);
    CS_initClockSignal (CS_SMCLK、CS_DCOCLK_select、CS_clock_divider);
    *
    
    
    /*初始化 ADC (MCLK/1/1)*/
    ADC14_enableModule();
    ADC14_initModule (ADC_CLOCKSOURCE_MCLK、ADC_PREDIVIDER_1、ADC_DIVIDER_1、
    0);
    
    //配置调试引脚作为调试输出...
    GPIO_setAsOutputPin (GPIO_PORT_P5、GPIO_PIN5);
    GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0);
    
    //Configuring GPIO for Analog In
    GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P4、
    GPIO_PIN1 | GPIO_PIN3 | GPIO_PIN5 | GPIO_PIN7、GPIO_TICE_MODULE_FUNCTION);
    
    //配置 ADC 存储器(ADC_MEM0 - ADC_MEM3 (A6、A12、A10、A8)、不重复)
    //具有内部2.5V 基准
    ADC14_configureMultiSequenceMode (ADC_MEM0、ADC_MEM3、false);//无重复模式。
    ADC14_configureConversionMemory (ADC_MEM0、
    ADC_VREFPOS_INTBUF_VREFNEG_VSS、
    ADC_INPUT_A6、ADC_NONDIFFERENTIAL_INPUTES);
    ADC14_configureConversionMemory (ADC_MEM1、
    ADC_VREFPOS_INTBUF_VREFNEG_VSS、
    ADC_INPUT_A12、ADC_NONDIFFERENTIAL 输入);
    ADC14_configureConversionMemory (ADC_MEM2、
    ADC_VREFPOS_INTBUF_VREFNEG_VSS、
    ADC_INPUT_A10、ADC_NONDIFFERENTIAL 输入);
    ADC14_configureConversionMemory (ADC_MEM3、
    ADC_VREFPOS_INTBUF_VREFNEG_VSS、
    ADC_INPUT_A8、ADC_NONDIFFERENTIAL 输入);
    
    /*配置 Timer_A*/
    Timer_A_configureUpMode (timer_A1_base、&upModeConfig);
    
    /*在 CCR1中配置 TIMER_A3 *
    Timer_A_initCompare (timer_A1_base、&compareConfig);
    
    /*将样本触发器配置为来自 TIMER_A3并进行设置
    *在触发后自动迭代*/
    ADC14_setSampleHoldTrigger (ADC_TRIGGER_SOURCE3、false);
    
    /*将采样计时器设置为自动单步执行序列
    *转换。
    *
    ADC14_enableSampleTimer (ADC_AUTOMODIFY_DIOTIVation);
    
    /*当通道3上的转换完成时启用中断*/
    ADC14_enableInterrupt (ADC_INT3);
    //ADC14_enableConversion();//不需要,因为我们在.ino 中启用它。
    
    /*启用中断*/
    INTERRUPT_enableInterrupt (INT_ADC14);
    interrupt_enableMaster();
    
    /*启动计时器*/
    Timer_A_startCounter (timer_A1_base、timer_A_up_mode);
    //Hwi_enable();
    
    返回1;
    }
    
    
    void ADC14_IRQHandler (void)
    {
    uint64_t status;
    静态 int i = 0;
    //GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN0);
    status = ADC14_getEnabableInterruptStatus();
    ADC14_clearInterruptFlag (status);
    //GPIO_toggleOutputOnPin (GPIO_PORT_P5、GPIO_PIN5);
    ADC14_disableConversion();
    
    if (status & ADC_INT3)
    {
    //ADC14_disableConversion();
    印度尼西亚 ADC = false;
    ADC14_getMultiSequenceResult (resultsBuffer);
    measRe[i]= resultsBuffer[0];
    measIM[i]= resultsBuffer[1];
    refRe[i]= resultsBuffer[2];
    refIm [i]= resultsBuffer[3];
    //i=(i+1)%SAMPLE_LENGTH;
    GPIO_toggleOutputOnPin (GPIO_PORT_P5、GPIO_PIN5);
    如果(i!=sample_length)
    {
    i++;
    //ADC14_enableConversion();
    }
    其他
    {
    I=0;
    印度尼西亚 ADC = true;
    //ADC14_enableConversion();
    }
    }
    ADC14_enableConversion();
    }
    
    
    void startSampling (void)
    {
    //Timer_A_initCompare (timer_A1_base、&compareConfig);
    ADC14_enableConversion();//我需要这么做是一个谜
    //而不是仅仅调用 ADC14_enableConversion()
    //从.ino 文件!
    } 

    和标头:

    /*
    * adc14_.h
    *
    *创建日期:2017年5月12日
    * 作者:Frohro
    *
    
    #ifndef COPY2_ADC14_H_
    #define COPY2_ADC14_H_
    
    /* DriverLib 包括*/
    #include 
    #include 
    
    /*标准包括*/
    #include 
    
    #include 
    #define SMCLK_FREQ 12000000
    #define SAMPLE_FREQ 8000
    //Timer_A 连续模式配置参数
    CONST Timer_A_UpModeConfig upModeConfig =//这确实起作用
    {
    Timer_A_CLOCKSOURCE_SMCLK、 // SM 时钟源
    Timer_A_CLOCKSOURCE_divider _1、 // SMCLK/1 = 24MHz
    (SMCLK_FREQ/SAMPLE_FREQ)、
    Timer_A_TAIE_INTERRUPT_DISABLE、 //禁用计时器 ISR
    Timer_A_CCIE_CCR0_INTERRUPT_DISABLE、//禁用 CCR0
    Timer_A_do 清除 //清除计数器
    };
    
    /* Timer_A 比较配置参数*/
    CONST Timer_A_CompareModeConfig compareConfig =
    {
    Timer_A_CAPTURECOMPARE 寄存器_1、 //使用 CCR1
    Timer_A_CAPTURECMOLE_INTERRUPT_DISABLE、//禁用 CCR 中断
    Timer_A_OUTPUTMODE_SET_RESET、 //切换输出但是
    (SMCLK_FREQ/SAMPLE_FREQ) //应为8kHz 采样率
    };
    
    /*静态*/
    静态易失性 uint_fast16_t resultsBuffer[uint8_MAX];
    静态易失性 uint8_t resPos;
    
    int adc14_(void);
    void ADC14_IRQHandler (void);
    void startSampling (void);
    
    
    
    
    #endif /* COPY2_ADC14_H_* 

    这一切都是未经清理的、但它似乎以8kHz 的频率中断、这太棒了!

    感谢所有的帮助!

    Rob

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

    感谢您的介绍。 我几乎没有机会从周末实际阅读这些内容。 我要提到的是、我认为问题的一部分来自 Energia。 Energia 本身会将多个任务设置为同一优先级、这些任务可能是问题的一部分。 我看到你在你的新源代码中设置了 Hwi 的优先级、在我看来、这可能是你现在正在解决的问题的关键。 而不是深入调试它。