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.

[参考译文] MSP432P401R:按下外部按钮来复位 Timer_A

Guru**** 2524460 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/685423/msp432p401r-reset-timer_a-by-pushing-an-external-button

器件型号:MSP432P401R

目前、我编写的代码在 Timer_A 确定的时间成功地打开和关闭 ADC 但是、我想知道是否有任何方法可以使用外部按钮来重置 Timer_A、这样我就可以按下一个按钮将 Timer_A 的计数重置为0、因为我发现的所有示例都涉及使用 Timer_A 来检测按钮是否被按下?  

编辑:我编写了一些测试代码、以便在 P3.0上的外部按钮成功触发 GPIO 中断时使 LED2上的红色 LED 闪烁、并在中断未发生时使 LED2上的绿色 LED 闪烁。 但是、尽管我做出了最大努力、但它仍然没有中断。 是否有人能指出我解决这个新问题的正确方向(我在下面包含了测试代码)?

/*测试外部按钮是否会切换 P2.0 (V1)上的红色 LED */

#include "msp.h"
#include "mytime.h"

volatile int button_flag = 0; //标记为信号按钮按
void setFreq (int freq);
void delayM (int n、int freq);

void main (void)
{
setFreq (FREQ_3_MHz);

WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器

//初始化端口3 (按钮连接)

P3->SEL0 = BIT0;//清除寄存器选择
P3->SEL1 = BIT0;//清除寄存器选择
P3->DIR = BIT0;
P3->OUT = BIT0;
P3->REN = BIT1;//上拉使能电阻

P3->IES = BIT1;//高-低转换时中断
P3->IFG = BIT0;//清除任何挂起标志
P3->IE = BIT1;//启用端口3中断

//用于调试
P2->SEL1 &=~BIT2;//P2.1是简单的 I/O
P2->SEL0 &=~BIT2;
P2->DIR |= BIT2;// P2.1设置为输出引脚
P2->DIR |= BIT1;// P2.0设置为输出引脚
P2->OUT &=~BIT0;// LED 初始为低电平(关闭)
P2->OUT &=~BIT1;// LED 初始为低电平(关闭)

NVIC->ISER[3]= 1 <<(PORT3_IRQn)& 31);

//启用全局中断
__ENABLE_IRQ();

while (1){ //无限循环
if (button_flag = 1){
P2->OUT |=1; //打开 P2.0红色 LED
delayMs (500、FREQ_3_MHz);
P2->OUT &=~1; //关闭红色 P2.0
delayMs (500、FREQ_3_MHz);

button_flag = 0; //复位标志
}否则{
P2->OUT |= 2; //打开 P2.1绿色 LED
delayMs (500、FREQ_3_MHz);
P2->OUT &=~2; //关闭 P2.1绿色 LED
delayMs (500、FREQ_3_MHz);
}
}



void PORT3_IRQHandler (void) // P3.0的中断处理程序
{
button_flag = 1; //set flag to signal button pressed.(检测到按压信号。
P3->IFG &=~BIT0; //清除 P3.0挂起中断标志
P3->IE |= BIT0; //禁用 P3.0的去抖中断
}

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

    您需要为 GPIO 引脚按压创建中断、并在中断处理程序中禁用计时器并将其复位。 此外、确保针对任何已失效的中断挂起状态清除 NVIC 状态。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Nyssa、

    每个按钮有两个特性:
    逻辑:可以打开或关闭
    相切:任何按钮切换都会在导通和关断之间切换时使线路不可测性。
    这种不确定性、取决于机械设计、需要几毫秒、几十年甚至更多的时间。
    在大多数情况下、计时器延迟用于跳过不可确定的时间周期。
    在其他一些情况下、可以使用 RC 滤波器。

    因此、使用计时器传递按钮上的振动等效效果
    然后重置您的 Timer_A 相应的参考手册中的值。

    请记住、在调试期间、您不仅可以跟踪变量、还可以跟踪 MPU 寄存器。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Amit、

    非常感谢您的回答! 我已经开始编写一个简单的测试程序 、当我按下连接到 P3.0的外部按钮时、通过使 P2.0上的红色 LED 闪烁、可以测试 GPIO 中断。 但是、中断似乎不起作用。 当我运行该程序(下面包含的代码)时、无论按下按钮如何、P2.0上的红色 LED 都将保持亮起状态。 我想知道您是否可以查看它、并让我知道我是否在使用 GPIO 中断的正确轨道上。 谢谢!

    /*测试外部按钮是否会在 P2.0 (V1)上切换红色 LED */
    
    #include "msp.h"
    #include "mytime.h"
    
    void setFreq (int freq);
    void delayM (int n、int freq);
    
    volatile uint8_t button_flag = 0;
    
    void main (void)
    {
    setFreq (FREQ_3_MHz);
    
    WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器
    
    //初始化端口3 (按钮连接)
    P3->SEL0 = 0x00;//清除寄存器选择
    P3->SEL1 = 0x00;//清除寄存器选择
    P3->DIR = 0xFF;
    P3->OUT = 0x00;
    P3->REN |= 2; //使能电阻器
    
    P3->IES = 0x02;//高-低转换时中断
    P3->IFG = 0x00;//清除任何挂起标志
    P3->IE = 0x02;//启用端口3中断
    
    P2->SEL1 &=~1; /*将 P2.0配置为简单 I/O */
    P2->SEL0 &=~1;
    P2->DIR = 0x01;
    
    NVIC->ISER[3]= 1 <<(PORT3_IRQn)& 31);
    
    //启用全局中断
    __ENABLE_IRQ();
    
    while (1){ //无限循环-主程序
    if (button_flag = 1){
    P2->OUT |= 1;//打开 P2.0红色 LED
    delayMs (500、FREQ_3_MHz);
    P2->OUT &=~1;//关闭 P2.0红色
    delayMs (500、FREQ_3_MHz);
    
    button_flag = 0; //复位标志
    P3->IFG &=~0x02; //清除挂起的中断标志
    P3->IE |= 0x02; //启用中断
    }
    }
    
    
    void PORT3_IRQHandler (void) //中断处理程序
    {
    button_flag = 1; //将标志设置为检测到信号按钮按压
    }
    

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

    我强烈建议至少使用 DriverLib、因为它增加了代码可读性方面更清晰的内容、并且还可以防止缺少中断矢量启用等简单问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    >当我按下连接到 P3.0的外部按钮时
    > P3->IE = 0x02;//启用端口3中断
    [等人]
    这将启用 P3.1 (1 << 1)而不是 P3.0 (1 << 0)的引脚中断。
    这些位有预定义的名称:BIT0、BIT1等、这使得跟踪更加容易。 该行可能如下所示:
    > P3->IE |= BIT0;//为 P3.0启用端口中断
    [与其他参考文献类似]
    ------------
    > P3->DIR = 0xFF;
    这使得 P3.0 (连同其它 P3.x)成为一个输出、但它应该是一个输入。 尝试:
    > P3->DIR &=~BIT0;// P3.0输入
    ------------
    您需要清除 ISR 内部的 IFG、否则它将不断中断。 移动此行:
    > P3->IFG &=~BIT0; //清除 P3.0挂起中断标志
    ISR 中。
    ------------
    > P2->DIR = 0x01;
    此行正常(在0x01->BIT0之后)、但 P2->OUT 在复位时未定义、因此您的 LED 可能会在开启或关闭时启动。 LaunchPad LED 为高电平有效、因此添加以下内容:
    > P2->OUT &=~BIT0; // LED 初始低电平(关闭)
    ------------
    未经请求:我的 Launchpad 的按钮位于 P1.1和 P1.4、而不是 P3.0。 您是否制作了自己的按钮?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    非常感谢您的帮助! 我进行了您建议的更改、但遗憾的是我的代码仍然无法正常工作。

    为了回答您的问题、我将一个外部按钮连接到了 P3.0。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    "不工作"涵盖了很多领域。 它的作用是什么? 是否达到 ISR 中设置的断点(按下按钮时)?

    我建议进行一些更改[有些是模式]。 您的代码现在是什么样的?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    目前、"不起作用"是指无论按多少次按钮、代码都永远不会进入 ISR。 P2.1上的绿色 LED 持续闪烁、表示从未设置 button_flag 变量。 我在下面添加了我的代码。

    /*测试外部按钮是否会切换 P2.0 (V1)上的红色 LED */
    
    #include "msp.h"
    #include "mytime.h"
    
    volatile int button_flag = 0; //标记为信号按钮按
    void setFreq (int freq);
    void delayM (int n、int freq);
    
    void main (void)
    {
    setFreq (FREQ_3_MHz);
    
    WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器
    
    //初始化端口3 (按钮连接)
    
    P3->SEL0 = BIT0;//清除寄存器选择
    P3->SEL1 = BIT0;//清除寄存器选择
    P3->DIR = BIT0;
    P3->OUT = BIT0;
    P3->REN = BIT1;//上拉使能电阻
    
    P3->IES = BIT1;//高-低转换时中断
    P3->IFG = BIT0;//清除任何挂起标志
    P3->IE = BIT1;//启用端口3中断
    
    //用于调试
    P2->SEL1 &=~BIT2;//P2.1是简单的 I/O
    P2->SEL0 &=~BIT2;
    P2->DIR |= BIT2;// P2.1设置为输出引脚
    P2->DIR |= BIT1;// P2.0设置为输出引脚
    P2->OUT &=~BIT0;// LED 初始为低电平(关闭)
    P2->OUT &=~BIT1;// LED 初始为低电平(关闭)
    
    NVIC->ISER[3]= 1 <<(PORT3_IRQn)& 31);
    
    //启用全局中断
    __ENABLE_IRQ();
    
    while (1){ //无限循环
    if (button_flag = 1){
    P2->OUT |=1; //打开 P2.0红色 LED
    delayMs (500、FREQ_3_MHz);
    P2->OUT &=~1; //关闭红色 P2.0
    delayMs (500、FREQ_3_MHz);
    
    button_flag = 0; //复位标志
    }否则{
    P2->OUT |= 2; //打开 P2.1绿色 LED
    delayMs (500、FREQ_3_MHz);
    P2->OUT &=~2; //关闭 P2.1绿色 LED
    delayMs (500、FREQ_3_MHz);
    }
    }
    
    
    
    void PORT3_IRQHandler (void) // P3.0的中断处理程序
    {
    button_flag = 1; //set flag to signal button pressed.(检测到按压信号。
    P3->IFG &=~BIT0; //清除 P3.0挂起中断标志
    P3->IE |= BIT0; //禁用 P3.0的去抖中断
    } 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    "BIT0"指(例如) P3.0、因此所有这些都应使用 BIT0、而不是 BIT1:
    >P3->REN = BIT1;//上拉使能电阻
    >P3->IES = BIT1;//高-低转换时中断
    >P3->IE = BIT1;//启用端口3中断
    --------------------
    这些应酌情指 BIT0/BIT1 (分别为 P2.0/P2.1):
    >P2->SEL1 &=~BIT2;//P2.1是简单的 I/O
    >P2->SEL0 &=~BIT2;
    >P2->DIR |= BIT2;// P2.1设置为输出引脚
    >P2->DIR |= BIT1;// P2.0设置为输出引脚
    --------------------
    >P3->IFG = BIT0;//清除任何挂起标志
    这实际上会触发中断(尽管由于上述原因、中断未被启用)。 [实际上、还有其他 MCU 写入1会将该位清零、但不会将该位清零。] 请尝试:
    >P3->IFG = 0;//清除任何挂起标志(包括 P3.0)
    --------------------
    >P3->IE |= BIT0; //禁用 P3.0的去抖中断
    这实际上会启用中断、而不是禁用中断。 尝试:
    >P3->IE &=~BIT0; //禁用 P3.0的去抖中断
    -----------------------------------------------------------
    禁用 IE 以及 while ()中的延迟是一个去抖的好主意。 但是,任何 IFG (嗯,不管怎样,第一个 IFG)都将继续堆积,所以在 while ()的底部,请确保在重新启用之前清除它们:
    > P3->IFG = 0;//清除任何挂起标志
    >P3->IE |= BIT0;//重新启用 P3.0中断
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    非常感谢您的所有帮助! 遗憾的是、我已经对您的所有建议进行了更改、但结果仍然相同(无论按下按钮、绿色 LED 都会持续闪烁)、我真的不明白为什么。 我在下面添加了我的代码、以防我错过任何其他明显错误。 我还确认、按下 P3.0时、我正在使用的按钮确实会将其拉至接地。

    
    
    /*测试外部按钮是否会切换 P2.0 (V1)上的红色 LED */
    
    #include "msp.h"
    #include "mytime.h"
    
    volatile int button_flag = 0; //标记为信号按钮按
    void setFreq (int freq);
    void delayM (int n、int freq);
    
    void main (void)
    {
    setFreq (FREQ_3_MHz);
    
    WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器
    
    //初始化端口3 (按钮连接)
    
    P3->SEL0 = BIT0;//清除寄存器选择
    P3->SEL1 = BIT0;//清除寄存器选择
    P3->DIR = BIT0;
    P3->OUT = BIT0;
    P3->REN = BIT0;//启用上拉电阻
    
    P3->IES = BIT0;//高-低转换时中断
    P3->IFG = 0; //清除任何挂起标志
    P3->IE = BIT0;//启用端口3中断
    
    //用于调试
    P2->SEL1 &=~BIT2;//P2.1是简单的 I/O
    P2->SEL0 &=~BIT2;
    P2->DIR |= BIT2;// P2.1设置为输出引脚
    P2->DIR |= BIT1;// P2.0设置为输出引脚
    P2->OUT &=~BIT0;// LED 初始为低电平(关闭)
    P2->OUT &=~BIT1;// LED 初始为低电平(关闭)
    
    //启用全局中断
    __ENABLE_IRQ();
    
    //在 NVIC 模块中启用中断
    NVIC->ISER[0]= 1 <<(PORT3_IRQn)& 31);
    
    while (1){ //无限循环
    if (button_flag = 1){
    P2->OUT |= BIT0; //打开 P2.0红色 LED
    delayMs (500、FREQ_3_MHz);
    P2->OUT &=~BIT0; //关闭 P2.0红色 LED
    delayMs (500、FREQ_3_MHz);
    
    button_flag = 0; //复位标志
    P3->IFG = 0; //清除任何挂起标志
    P3->IE |= BIT0; //重新启用 P3.0中断
    }否则{
    P2->OUT |= BIT1; //打开 P2.1绿色 LED
    delayMs (500、FREQ_3_MHz);
    P2->OUT &=~BIT1; //关闭 P2.1绿色 LED
    delayMs (500、FREQ_3_MHz);
    }
    
    }
    
    
    
    void PORT3_IRQHandler (void) // P3.0的中断处理程序
    {
    button_flag = 1; //set flag to signal button pressed.(检测到按压信号。
    P3->IFG = 0; //清除 P3.0挂起中断标志
    P3->IE &=~BIT0; //禁用 P3.0的去抖中断
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    替换以下内容:
    P3->SEL0 = BIT0;//清除寄存器选择
    P3->SEL1 = BIT0;//清除寄存器选择
    P3->DIR = BIT0;
    凭借这些功能:
    P3->SEL0 = 0;//清除寄存器选择
    P3->SEL1 = 0;//清除寄存器选择
    P3->DIR = 0; //所有输入
    ----------------
    替换以下内容:
    P2->SEL1 &=~BIT2;//P2.1是简单的 I/O
    P2->SEL0 &=~BIT2;
    P2->DIR |= BIT2;// P2.1设置为输出引脚
    P2->DIR |= BIT1;// P2.0设置为输出引脚
    凭借这些功能:
    P2->SEL1 &=~Ω(BIT0|BIT1);//P2.0、P2.1 AS
    P2->SEL0 &=~(BIT0|BIT1);// 简单 I/O
    P2->DIR |=(BIT0|BIT1);// P2.0,P2.1设置为输出引脚
    ----------------
    替换此项:
    NVIC->ISER[0]= 1 <<(PORT3_IRQn)& 31);
    为此:
    NVIC_EnableIRQ (PORT3_IRQn);
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    非常感谢您的所有帮助! 它现在工作得非常完美。