大家好、我正在尝试这个去抖 代码。 使用复位开关(S1)和 Launchpad 开关 P1.3 (S2)。 按下 S1时、绿色 LED 亮起。 按下 S2时、红色 LED 亮起。 如果按下两个开关中的一个超过1.5秒、两个 LED 将亮起、当释放开关时、两个 LED 将关闭。 这是完美的。 我添加了一个外部开关并将其连接到 P2.1 (S3)。 其功能与 launchpad 的 S2相同。 按下按钮 P2.1 (S3)时,检测到脉动,红色 LED 亮起。 然后我释放按钮、但红色 LED 不会熄灭、大约1.5秒后、绿色 LED 也会亮起。 执行此操作后、其他两个按钮(S1和 S2)继续正常工作、但 S3不再检测到任何脉动。 这种情况就好像未检测到按钮 P2.1已被释放、然后 P2.1中的中断似乎被禁用。
为了更容易找到错误、我添加的代码部分是'InitializeSwitch2'方法和最后两条看门狗 ISR 行:
#include "msp430g2553.h"
#define FLIP_HOLD (0x3300 | WDTHOLD) //保留其他位时保持翻转
#define S1 1 //开关1标志掩码
#define S2 2 //开关2标志掩码
#define Moth 3 //两个开关标志掩码
#define PRESSDURATION 47 //长按持续时间47*32ms = 1.5s
//事件*/
#define Switch1 #define Switch1 1 #1
volatile char PressCountS1 = 0;
volatile char PressCountS2 = 0;
volatile char SwitchState = 0;//在中断内部使用标志来存储当前开关状态
volatile char pressed = 0;//用于指示开关的标志 Press
volatile char PressRelease = 0; //用于指示开关按压和释放
易失性字符 longPress = 0的标志;//用于指示开关长按
空配置 WDT (空);
空初始化 Switch2 (空);//开关 P1.3
空初始化3 (空);//开关 P2.1
空主(空)
{
ConfigureWDT();
BCSCTL1 = CALBC1_1MHz;//将 DCO 设置为1MHz
DCOCTL = CALDCO_1MHz;//将 DCO 设置为1MHz
P1DIR |=(BIT0|BIT6);//将 P1.0和 P1.6上的 LED 设置为输出
P1OUT |=(BIT0|BIT6);//打开 P1.0和 P1.6 LED 以指示初始状态
InitializeSwitch2();//初始化连接到 P1.3的 Switch 2
InitializeSwitch3();//初始化连接到 P2.1的 Switch 2
while (1){
IF (预发布)
{
PressRelease 和=~(S1 + S2);//清除开关标志以指示开关按压已被处理
}
_bis_SR_register (LPM0_Bits + GIE);
}
}
void ConfigureWDT (void){
//看门狗计时器(WDT)将用于对 s1和 s2进行去抖
WDTCTL = WDTPW + WDTHOLD + WDTNMIES + WDTNMI;//WDT 密码+停止 WDT +检测 RST 按钮下降沿+将 RST/NMI 引脚设置为 NMI
IFG1 &=~(WDTIFG + NMIIFG);//清除 WDT 和 NMI 中断标志
IE1 |= WDTIE + NMIIE;//启用 WDT 和 NMI 中断
}
//此函数配置按钮,以便
在按下按钮时触发中断*。 这些中断将由 Port1_ISR()*/
void InitializeSwitch2 (void){处理
P1DIR &=~BIT3;//将按钮引脚设置为输入引脚
P1OUT |= BIT3;//为按钮设置上拉电阻
P1REN |= BIT3;//为按钮启用上拉电阻器、以使引脚保持高电平直到按下
P1IES |= BIT3;//启用中断以在下降沿(高电平(未按下)到低电平(按下)转换)触发
P1IFG &=~BIT3;//清除按钮的中断标志
P1IE |= BIT3;//为按钮
启用端口1上的中断}
void InitializeSwitch3 (void){
P2DIR &=~BIT1;//将按钮引脚设置为输入引脚
P2OUT |= BIT1;//为按钮设置上拉电阻
P2REN |= BIT1;//为按钮启用上拉电阻、以使引脚保持高电平直到按下
P2IES |= BIT1;//启用中断以在下降沿(高电平(未按下)到低电平(按下)转换)触发
P2IFG &=~BIT1;//清除按钮的中断标志
P2IE |= BIT1;//为按钮启用端口1上的中断
}
// ISR 在 nRST/NMI 引脚上检测 s1的产生/中断
//注意 NMI 中断的发生会自动禁用 NMI 中断使能。
#pragma vector = NMI_Vector
_中断 void NMI_ISR (void)
{
if (IFG1 & NMIIFG)//检查 NMI 中断是否由 nRST/NMI 引脚引起
{
IFG1 &=~NMIIFG;//清除 NMI 中断标志
IF (WDTCTL & WDTNMIES)//检测到下降沿
{
P1OUT |= BIT6;//打开 P1.0红色 LED 以指示开关1已按下
SwitchState |= S1;//将 Switch 1 State 设置为 pressed
已按下|= S1;//设置 S1已按下标志
PressCountS1 = 0;//重置开关2长按计数
WDTCTL = WDT_MDLY_32 | WDTNMI;// WDT 32ms 延迟+将 RST/NMI 引脚设置为 NMI
//注意:WDT_MDLY_32 = WDTPW | WDTTMSEL | WDTCNTCL // WDT 密码+间隔模式+清除计数
//注意:这也会将 NMI 中断设置为在上升沿触发
}
else //检测到上升沿
{
P1OUT &=~(BIT6+BIT0);//关闭 P1.6和 P1.0 LED
SwitchState &=~S1;//重置开关1已按下标志
PressRelease |= S1;//设置 Press and released 标志
WDTCTL = WDT_MDLY_32 | WDTNMIES | WDTNMI;// WDT 32ms 延迟+下降沿+将 RST/NMI 引脚设置为 NMI
}
__BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//Wake CPU
} //请注意、NMIIE 现在被清除;WDT_ISR 将在32ms 后设置 NMIIE
否则{//*在此处添加代码以处理其他类型的 NMI (如果有)
}
#pragma vector=Port1_vector
__interrupt void Port1_ISR (void)
{
IF (P1IFG & BIT3)// Checkamos que se ha *** el pulpador conectado al P1.3
{
P1IE &=~BIT3;//禁用按钮中断以避免退回
P1IFG &=~BIT3;//清除按钮的中断标志
IF (P1IES 和 BIT3)
{//检测到下降沿
P1OUT |= BIT0;//打开 P1.0红色 LED 以指示开关2已按下
SwitchState |= S2;//将 S2状态设置为按下
按下|= S2;//设置开关2按下标志
PressCountS2 = 0;//重置开关2长按计数
}
其他
{//检测到上升沿
P1OUT &=~(BIT0+BIT6);//关闭 P1.0和 P1.6 LED
SwitchState &=~S2;//重置开关2状态
PressRelease |= S2;//设置按压和释放标志
}
P1IES ^= BIT3;//切换边沿检测
IFG1 &=~WDTIFG;//清除 WDT 的中断标志
WDTCTL = WDT_MDLY_32 |(WDTCTL & 0x007F);//使用与 NMI 中断设置的相同 NMI 状态重新启动 WDT
__BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//Wake CPU
}
}
#pragma vector=port2_vector
__interrupt void port2_ISR (void)
{
IF (P2IES & BIT1)// Checkamos que se ha *** el pulpador conectado al P2.1
{
P2IE &=~BIT1;//禁用按钮中断以避免退回
P2IFG &=~BIT1;//清除按钮的中断标志
IF (P2IES 和 BIT1)
{//检测到下降沿
P1OUT |= BIT0;//打开 P1.0红色 LED 以指示开关2已按下
SwitchState |= S2;//将 S2状态设置为按下
按下|= S2;//设置开关2按下标志
PressCountS2 = 0;//重置开关2长按计数
}
其他
{//检测到上升沿
P1OUT &=~(BIT0+BIT6);//关闭 P1.0和 P1.6 LED
SwitchState &=~S2;//重置开关2状态
PressRelease |= S2;//设置按压和释放标志
}
P2IES ^= BIT1;//切换边沿检测
IFG1 &=~WDTIFG;//清除 WDT 的中断标志
WDTCTL = WDT_MDLY_32 |(WDTCTL & 0x007F);//使用与 NMI 中断设置的相同 NMI 状态重新启动 WDT
__BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//Wake CPU
}
}
// WDT 用于通过延迟重新启用 NMIIE 和 P1IE 中断来对 s1和 s2进行去抖
//并计时印刷
#pragma vector 的长度= WDT_vector
__interrupt void WDT_ISR (void)
{
如果(开关状态和 S1)//检查开关1是否按下
{
如果(++PressCountS1 =PRESSDURATION )//长按持续时间47*32ms =1.5s
{
P1OUT |= BIT0;//打开 P1.1 LED 以指示长按
长按|= S1;//设置长按标志中的 S1位
__BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//Wake CPU
}
}
如果(开关状态和 S2)//检查开关2是否按下
{
如果(++PressCountS2=PRESSDURATION )//长按持续时间47*32ms =1.5s
{
P1OUT |= BIT6;//打开 P1.2 LED 以指示长按
长按|= S2;//设置长按标志中的 S2位
__BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//Wake CPU
}
}
IFG1 &=~NMIIFG;//清除 NMI 中断标志(如果已通过弹跳进行设置)
P1IFG &=~BIT3;//清除按钮中断标志(如果已通过弹跳进行设置)
IE1 |= NMIIE;//重新启用 NMI 中断以检测下一个边沿
P1IE |= BIT3;//重新启用 P1.3上按钮的中断
P2IFG &=~BIT1;//清除按钮中断标志(如果它已通过弹跳进行设置)
P2IE |= BIT1;//重新启用 P2.1上按钮的中断
}
提前感谢。
此致、
弗兰·马丁