大家好、团队成员
我使用的是 MSP430FR5994 Launchpad 套件。 我正在尝试使用函数"timer_delay (delay);"初始化计时器、但我没有收到任何中断。
我能够使 LED 闪烁并使用其他代码访问开关输入。 要访问开关、我必须按照 E2E 论坛中的规定更新 MSP430FR5994.h 文件。
下面随附了我使用的代码。 请查看。
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.
大家好、团队成员
我使用的是 MSP430FR5994 Launchpad 套件。 我正在尝试使用函数"timer_delay (delay);"初始化计时器、但我没有收到任何中断。
我能够使 LED 闪烁并使用其他代码访问开关输入。 要访问开关、我必须按照 E2E 论坛中的规定更新 MSP430FR5994.h 文件。
下面随附了我使用的代码。 请查看。
你(们)好
根据建议更新了代码、但仍然无法正常工作。 我还更新了行 initContParam.clockSourceDivider= timer_A_CLOCKSOURCE_divider; 更新为 initContParam.clockSourceDivider= timer_A_CLOCKSOURCE_divider;16;
IE,SMCLK 将为16MHz。 因此、使用 TIMER_A_CLOCKSOURCE_DEVIDER_16将时钟源设置为1MHz。
代码的目的是生成1秒的延迟。 因此、我设置 initCompParam.compareValue= 0xF4240;启用中断以检测比较器达到0xF4240。 到达后、应调用 ISR 并将延迟设置为1、从而结束循环。
当调用 timer_delay()时,延迟被分配为0。
请对使用的代码和方法进行评论。
什么(精确)不起作用?
不能使用 compareValue 0xF4240、因为 compareValue (和 TA1CCR0)仅为16位。 我很惊讶编译器没有就此向您发出警告。
您可以将输入时钟除以最高8*8=64,因此使用 SMCLK=16MHz 时,您可以得到一个(65536/(16MHz/64))=~0.262秒的周期。 如果您想使用 SMCLK、我建议您将延迟分解为较小的单位、例如250ms 或可能10ms。
在另一个线程中、您的电路板上似乎有一个32kHz 晶体。 ACLK 可以很容易地计数1秒(compareValue=CCR0=32768U-1)。
未经请求:对于延迟、您可能会发现向上计数模式比连续模式更方便。
你(们)好
按照建议,我使用向上计数模式和时钟源 ACLK/64 (32.768kHz)更新了代码。 因此、为了获得1s 延迟、我将 initContParam.timerPeriod=0x0200设置为等于1秒的周期。 我创建了两个函数 timer_init ()和 timer_delay (uint32_t delay)。 使用 timer_delay()我想创建启动计时器,在计时器使用中断例程到达0x200时检查 DELAY_FLAG 是否设置为1,然后停止计时器,返回主函数。
目前,代码卡在 timer_delay()内的 while 循环中,LED 停止闪烁。
请检查更新后的代码并告诉我问题是什么。
你(们)好
代码如下。
#include "./MSP430FR5xx_6xx/driverlib.h"
#include
//#include
void initClock (void);
void timer_init (void);
void timer_delay (uint32_t);
int Flag1 = 0、flag2 = 0;
volatile int delay_flag = 0;
INT 计数= 0;
int SW1_state=1、SW2_state=1;
int main (空)
{
volatile uint32_t i;
volatile uint8_t SW1、SW2;
volatile uint16_t SW1_INTERRUPT=1、SW2_INTERRUPT=1、SW1_INTERRUPT_PRE、SW2_INTERRUPT_PRE;
volatile uint16_t timer_value=0;
volatile uint32_t delay = 0;
计数= 0;
//停止看门狗计时器
WDT_A_HOLD (WDT_A_base);
//initClock();
timer_init();
GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0); //设置红色 LED 输出
GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN0); //红色 LED 关闭
GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN1); //设置绿色 LED 输出
GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN1); //绿色 LED 关闭
GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P5、GPIO_PIN6); // S1 P5.6:PxDIR、PxOUT 和 PxREN 寄存器
GPIO_selectInterruptEdge (GPIO_PORT_P5、GPIO_PIN6、GPIO_HIGH_TO_LOW_TRANSITION); // S1 P5.6:PxIES 寄存器
GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P5、GPIO_PIN5); // S2 P5.5:PxDIR、PxOUT 和 PxREN 寄存器
GPIO_selectInterruptEdge (GPIO_PORT_P5、GPIO_PIN5、GPIO_HIGH_TO_LOW_TRANSITION); // S2 P5.5:PxIES 寄存器
SW1 = GPIO_getInputPinValue (GPIO_PORT_P5、GPIO_PIN6);
SW2 = GPIO_getInputPinValue (GPIO_PORT_P5、GPIO_PIN5);
//SW1_STstate = SW1和0x08;
//禁用 GPIO 上电默认高阻抗模式以激活先前配置的端口设置
PMM_unlockLPM5 ();
//将所有 P5IFG 设为零
P5IFG = 0x00;
//将所有 P5IFG 设为零
//TAIFG = 0x00;
GPIO_enableInterrupt (GPIO_PORT_P5、GPIO_PIN5);
GPIO_enableInterrupt (GPIO_PORT_P5、GPIO_PIN6);
_bis_SR_register (GIE); //启用所有中断
//*
//启用开关中断
GPIO_clearInterrupt (GPIO_PORT_P5、GPIO_PIN5);
GPIO_clearInterrupt (GPIO_PORT_P5、GPIO_PIN6);
//*/
SW1_INTERRUPT_PR= GPIO_getInterruptStatus (GPIO_PORT_P5、GPIO_PIN6);
SW2_INTERRUPT_PR= GPIO_getInterruptStatus (GPIO_PORT_P5、GPIO_PIN5);
while (1)
{
if (SW1_INTERRUPT_PRE!= GPIO_getInterruptStatus (GPIO_PORT_P5、GPIO_PIN6))
{
如果(SW1_INTERRUPT = 1)
{
SW1_INTERRUPT = 0;
}
其他
{
SW1_INTERRUPT = 1;
}
GPIO_clearInterrupt (GPIO_PORT_P5、GPIO_PIN6);
}
if (SW2_INTERRUPT_PRE!= GPIO_getInterruptStatus (GPIO_PORT_P5、GPIO_PIN5))
{
如果(SW2_INTERRUPT = 1)
{
SW2_INTERRUPT = 0;
}
其他
{
SW2_INTERRUPT = 1;
}
GPIO_clearInterrupt (GPIO_PORT_P5、GPIO_PIN5);
}
SW1 = GPIO_getInputPinValue (GPIO_PORT_P5、
GPIO_PIN6);
SW2 = GPIO_getInputPinValue (GPIO_PORT_P5、
GPIO_PIN5);
// if (GPIO_getInputPinValue (GPIO_PORT_P5、GPIO_PIN6)=GPIO_INPUT_PIN_HIGH)
如果(SW2_STACLE = 1)
{
IF (Flag1 = 0)
{
Flag1 = 10;
GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN1);
}
其他
{
Flag1 = Flag1--;
}
}
if (GPIO_getInputPinValue (GPIO_PORT_P5、GPIO_PIN6)=GPIO_INPUT_PIN_HIGH)
{
如果(标志2 = 0)
{
标志2 = 4;
GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN0);
}
其他
{
flag2 = flag2--;
}
}
//延迟
for (i=100000;i>0;i--);
延迟= 0xFFFFFFF;
Timer_delay (延迟);
//timer_value = Timer_A_getCounterValue (timer_A1_base);
//timer_delay (delay);
//timer_delay (delay);
//_delay_cycles (16000000);//等待160000个 CPU 周期
}
}
void timer_init()
{
//启动定时器_A
//Timer_A_initContinuousModeParam initContParam ={0};
Timer_A_initUpModeParam initContParam ={0};
initContParam.clockSource= TIMER_A_CLOCKSOURCE_ACLK;
initContactParam.clockSourceDivider= timer_A_CLOCKSOURCE_divider;
initContParam.timerPeriod=0x0200;
initContParam.timerInterruptEnable_TAIE= TIMER_A_TAIE_INTERRUPT_ENABLE;
initContParam.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;
initContParam.timerClear = timer_a_do _clear;
initContParam.startTimer=false;
Timer_A_initUpMode (timer_A1_base、&initContParam); // Timer_A_initContinuousMode
}
void timer_delay (uint32_t delay)
{
DELAY_FLAG = 0;
Timer_A_clear (timer_A1_base);
Timer_A_startCounter (timer_A1_base、timer_A_up_mode);
while (!delay_flag)
{
}
Timer_A_stop (timer_A1_base);
Timer_A_clearTimerInterrupt (timer_A1_base);
//Enter LPM0
//_bis_SR_register (LPM0_bits);
//用于调试器
//__no_operation();
}
#pragma vector=TIMER0_A1_vector
_interrupt void TIMER0_A1_ISR (void)
//void __attribute__((interrupt (TIMER0_A0_vector)) TIMER0_A0_ISR (void)
{
DELAY_FLAG = 1;
}
> #pragma vector=TIMER0_A1_vector
您使用的是 timer_A1_base、因此这应该是:
>#pragma vector=Timer1_A1_vector
--------
在 ISR 内部的某个位置,您需要使用以下内容来显式清除 TAIFG:
> Timer_A_clearTimerInterrupt (timer_A1_base);
否则、中断将仅保持触发状态。 (CCR0不需要这种情况、即 Timer1_A0_vector。) [参考用户指南(SLAU367P)第25.2.6节]
--------
> GPIO_enableInterrupt (GPIO_PORT_P5、GPIO_PIN5);
> GPIO_enableInterrupt (GPIO_PORT_P5、GPIO_PIN6);
您正在启用这些引脚中断、但我看不到它们的 ISR (PORT5_vector)。 其余代码似乎正在轮询中断状态、因此您可能应该只删除这些行。
你(们)好
1.是否可以使用 Timer_A_clear (timer_A1_base);重置计时器,以便在调用 timer_delay ()时它从零开始。 或者,无论何时调用 Timer_a_startCounter(),它都会自动从零开始计时器?
2.是定时器 A CCR0被称为 Timer0_A0_vector,CCR1作为 Timer0_A1_vector,... 定时器 B CCR0被称为 Timer1_A0_vector、CCR1被称为 Timer1_A1_vector、…… 请确认。
代码修改如下:添加了 ISR (PORT5_vector)。 此外、Timer_A_clearTimerInterrupt (timer_A1_base);已添加到 ISR 内部。
1) 1)是的、实际上您应该这样做。 Timer_A_stop 和 Timer_A_startCounter 都不会清除计数器。
2)主要是。 UG 章节25.2.6描述了每个定时器的两个不同的 IRQ -一个用于 CCR0、另一个用于所有其它定时器(包括 TAIFG)。 对于 TA0、这些是(如您所说) TIMER0_A0_VECTOR 和 TIMER0_A1_VECTOR。 对于 TA1、它们是 Timer1_A0_vector 和 Timer1_A1_vector。 对于 TB2、它们是 TIMER2_B0_vector 和 TIMER2_B1_vector。 这需要一点实践、但有一个系统。
那么、您的程序现在做什么呢?