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.

[参考译文] CCS/MSP430F5529:通过 PWM 和 WDT_ISR 使 LED 褪色

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/948750/ccs-msp430f5529-fading-led-with-pwm-and-wdt_isr

器件型号:MSP430F5529

工具/软件:Code Composer Studio

您好!  我有一段代码、总共大约6秒、它成功地使 LED 进入和退出。  我想知道是否有办法让 WDT_ISR 改变 LED 亮度?  (可能处于间隔模式)?

#include 

void _delay_ms (volatile unsigned int length){
volatile unsigned int delay = 0;
for (delay = 0;delay < length;delay++){
_delay_cycles (1000);
}
}

int main (void){

WDTCTL = WDTPW + WDTHOLD;//停止 WDT

//**注意:此设置需要在电路板上的 LED1和 P1.2之间放置一根跳线**

P1DIR |= BIT2; //为输出设置 Timer A 0.1 (P1.2)
P1SEL |= BIT2; //P1.2特殊功能
SFRIE1 |= WDTIE;//启用 WDT 中断

TA0CCR0 = 350;
TA0CCTL1 = OUTMOD_7;
TA0CCR1 = 0;

TA0CTL = tassel_1 + MC_1;

volatile signed int i = 0;

while (1){

对于(I = 1;I < 309;I += 5){
TA0CCR1 = I;
_delay_ms (50);
}

对于(I = 309-1;I > 0;I -= 5){
TA0CCR1 = I;
_delay_ms (50);
}
}

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

    我更改了代码一位、我认为 WDT_ISR 工作正常。  它可以正常地使 LED 变暗、而不会出现问题。  我现在遇到了另外2个尝试实现的中断的问题。  我想让开关1暂停衰减、开关2恢复衰减。  我以为我所要做的就是停止和重新启动 WDT 来实现这一点、但似乎我错了。  如果我能获得一些帮助、我将不胜感激。

    #include 
    
    void _delay_ms (volatile unsigned int length){
    volatile unsigned int delay = 0;
    for (delay = 0;delay < length;delay++){
    _delay_cycles (1000);
    }
    }
    
    int main (void)
    {
    WDTCTL = WDT_MDLY_32;//设置 WDT 间隔
    _EINT(); //启用中断
    
    //**注:此设置需要在板上的 LED1和 P1.2之间放置一根跳线**
    
    P1DIR |= BIT2; //为输出设置计时器 A 0.1 (P1.2)
    P1SEL |= BIT2; // P1.2特殊功能
    SFRIE1 |= WDTIE;//启用 WDT 中断
    
    P1DIR &=~BIT1; //将 P1.1设置为输入(SW2)
    P1REN |= BIT1; //启用上拉电阻器
    P1OUT |= BIT1; //正确的 IO 所需
    P1IE |= BIT1; //在 P1.1上启用中断
    P1IES |= BIT1; //为中断启用 hi->lo 边缘
    P1IFG &=~BIT1; //清除任何错误的中断标志
    
    P2DIR &=~BIT1; //将 P2.1设置为输入(SW1)
    P2REN |= BIT1; //启用上拉电阻器
    P2OUT |= BIT1; //正确的 IO 所需
    P2IE |= BIT1; //在 P2.1上启用中断
    P2IES |= BIT1; //为中断启用 hi->lo 边缘
    P2IFG &=~BIT1; //清除任何错误的中断标志
    
    TA0CCR0 = 350;
    TA0CCTL1 = OUTMOD_7;
    TA0CCR1 = 0;
    
    TA0CTL = tassel_1 + MC_1;
    
    while (1){}//在这里等待
    }
    
    #pragma vector = WDT_vector
    __interrupt void watchdog_timer (void)
    {
    volatile signed int i = 0;
    对于(I = 1;I < 309;I += 5){
    TA0CCR1 = I;
    _delay_ms (50);
    }
    
    对于(I = 309-1;I > 0;I -= 5){
    TA0CCR1 = I;
    _delay_ms (50);
    }
    }
    
    //此 ISR 处理 SW1键按
    #pragma vector = port2_vector
    __interrupt void port2_ISR (void)
    {
    //让我们清除标志
    P2IFG &=~BIT1;
    
    //去抖部分
    _DELAY_CYCLES (25000);
    
    //如果 SW1未按下,则返回
    if ((P2IN&BIT1)!=0x00)
    返回;
    WDTCTL = WDTPW + WDTHOLD;//停止 WDT
    }
    
    //此 ISR 处理 SW2键按
    #pragma vector = Port1_vector
    __interrupt void Port1_ISR (void)
    {
    //让我们清除标志
    P1IFG &=~BIT1;
    
    //去抖部分
    _DELAY_CYCLES (25000);
    
    //如果未按下 SW2,则返回
    if (((P1IN&BIT1)!=0x00)
    返回;
    WDTCTL = WDT_MDLY_32;//设置 WDT 间隔
    }
    

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

    1) 1)中断在进入 ISR 时被禁用。 因此,当 watchdog_timer()正在运行时,按钮不会中断它。 这是 ISR 非常短的原因之一。

    2) 2)看门狗间隔为32ms、但 ISR 需要6秒。 在完成时、WDT 将触发另一个中断。 WDTIFG 的优先级高于任一端口 IFG [参考数据表(SLAS590N)表6-1]、因此它将(始终)优先、并且端口 ISR 将永远不会运行。

    我建议您将褪色代码(返回)移到 main()中,并让按钮设置一个开/关字节,以控制褪色循环的工作方式。

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

    哦、我明白了。  首先是不可能尝试这种方法。  我将其改回 main 中的循环、并尝试创建一个简单的 int 变量作为0/1标志。  出于某种原因、我的按钮仍然不会暂停/重新启动淡入淡出。  相反、SW1会导致 LED 在完全淡入周期后暂停、而 SW2无法重新启动。  以下是我的更新代码:

    #include 
    
    volatile signed int i = 0;
    volatile unsigned int j = 1;
    
    void _delay_ms (volatile unsigned int length)
    {
    volatile unsigned int delay = 0;
    for (delay = 0;delay < length;delay++)
    {
    _delay_cycles (1000);
    }
    }
    
    int main (void)
    {
    WDTCTL = WDTPW + WDTHOLD;//停止看门狗计时器
    _EINT(); //启用中断
    
    //**注:此设置需要在板上的 LED1和 P1.2之间放置跳线**
    
    P1DIR |= BIT2; //为输出设置计时器 A 0.1 (P1.2)
    P1SEL |= BIT2; // P1.2特殊功能
    
    P1DIR &=~BIT1; //将 P1.1设置为输入(SW2)
    P1REN |= BIT1; //启用上拉电阻器
    P1OUT |= BIT1; //正确的 IO 所需
    P1IE |= BIT1; //在 P1.1上启用中断
    P1IES |= BIT1; //为中断启用 hi->lo 边缘
    P1IFG &=~BIT1; //清除任何错误的中断标志
    
    P2DIR &=~BIT1; //将 P2.1设置为输入(SW1)
    P2REN |= BIT1; //启用上拉电阻器
    P2OUT |= BIT1; //正确的 IO 所需
    P2IE |= BIT1; //在 P2.1上启用中断
    P2IES |= BIT1; //为中断启用 hi->lo 边缘
    P2IFG &=~BIT1; //清除任何错误的中断标志
    
    TA0CCR0 = 350;
    TA0CCTL1 = OUTMOD_7;//定时器 A 处于增/减模式
    TA0CCR1 = 0;
    
    TA0CTL = tassel_1 + MC_1;
    
    while (j = 1)//在这里等待中断
    {
    对于(I = 1;I < 309;I += 5){
    TA0CCR1 = I;
    _delay_ms (50);
    }
    
    对于(I = 309-1;I > 0;I -= 5){
    TA0CCR1 = I;
    _delay_ms (50);
    }
    }
    }//
    
    此 ISR 处理 SW1键按
    #pragma vector = port2_vector
    __interrupt void port2_ISR (void)
    {
    //让我们清除标志
    P2IFG &=~BIT1;
    
    //去抖部分
    _DELAY_CYCLES (25000);
    
    //如果 SW1未按下,则返回
    if ((P2IN&BIT1)!=0x00)
    {
    返回;
    }
    //暂停褪色
    if (j ==1)
    {
    J = 0;
    }
    }
    
    //此 ISR 处理 SW2键按
    #pragma vector = Port1_vector
    __interrupt void Port1_ISR (void)
    {
    //让我们清除标志
    P1IFG &=~BIT1;
    
    //去抖部分
    _DELAY_CYCLES (25000);
    
    //如果未按下 SW2,则返回
    if (((P1IN&BIT1)!=0x00)
    {
    返回;
    }
    //继续褪色
    if (j ==0)
    {
    J = 1;
    }
    }
    

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

    好的、我将它非常接近正常运行。  我更改了环路位以解决编码错误。  现在、其行为是 SW1始终暂停衰减、但 SW2在恢复时随机决定衰减的方向。  有时、当我按下它时、它将恢复其所处方向的衰减、有时它将反转衰减的方向。

    #include 
    
    volatile signed int i = 0;
    volatile unsigned int j = 1;
    
    void _delay_ms (volatile unsigned int length)
    {
    volatile unsigned int delay = 0;
    for (delay = 0;delay < length;delay++)
    {
    _delay_cycles (1000);
    }
    }
    
    int main (void)
    {
    WDTCTL = WDTPW + WDTHOLD;//停止看门狗计时器
    _EINT(); //启用中断
    
    //**注:此设置需要在板上的 LED1和 P1.2之间放置跳线**
    
    P1DIR |= BIT2; //为输出设置计时器 A 0.1 (P1.2)
    P1SEL |= BIT2; // P1.2特殊功能
    
    P1DIR &=~BIT1; //将 P1.1设置为输入(SW2)
    P1REN |= BIT1; //启用上拉电阻器
    P1OUT |= BIT1; //正确的 IO 所需
    P1IE |= BIT1; //在 P1.1上启用中断
    P1IES |= BIT1; //为中断启用 hi->lo 边缘
    P1IFG &=~BIT1; //清除任何错误的中断标志
    
    P2DIR &=~BIT1; //将 P2.1设置为输入(SW1)
    P2REN |= BIT1; //启用上拉电阻器
    P2OUT |= BIT1; //正确的 IO 所需
    P2IE |= BIT1; //在 P2.1上启用中断
    P2IES |= BIT1; //为中断启用 hi->lo 边缘
    P2IFG &=~BIT1; //清除任何错误的中断标志
    
    TA0CCR0 = 350;
    TA0CCTL1 = OUTMOD_7;//定时器 A 处于增/减模式
    TA0CCR1 = 0;
    
    TA0CTL = tassel_1 + MC_1;
    
    while (1)//在这里等待中断
    {
    对于(I;j = 1 && I < 309;I += 5)
    {
    TA0CCR1 = I;
    _delay_ms (50);
    }
    
    for (i;j = 1 && I > 0;i = 5){
    TA0CCR1 = I;
    _delay_ms (50);
    }
    }
    }//
    
    此 ISR 处理 SW1键按
    #pragma vector = port2_vector
    __interrupt void port2_ISR (void)
    {
    //让我们清除标志
    P2IFG &=~BIT1;
    
    //去抖部分
    _DELAY_CYCLES (25000);
    
    //如果 SW1未按下,则返回
    if ((P2IN&BIT1)!=0x00)
    {
    返回;
    }
    //暂停褪色
    if (j ==1)
    {
    J = 0;
    }
    }
    
    //此 ISR 处理 SW2键按
    #pragma vector = Port1_vector
    __interrupt void Port1_ISR (void)
    {
    //让我们清除标志
    P1IFG &=~BIT1;
    
    //去抖部分
    _DELAY_CYCLES (25000);
    
    //如果未按下 SW2,则返回
    if (((P1IN&BIT1)!=0x00)
    {
    返回;
    }
    //继续褪色
    if (j ==0)
    {
    J = 1;
    }
    }