Switch statement 开关去抖动

Switch statement 开关去抖动,switch-statement,avr,Switch Statement,Avr,有人能帮我换一下吗?我读了Gansle和avr的文章,但仍然不是很清楚。不明白如何使用定时器溢出中断 我想在STK600上执行以下任务: 1) 读取开关,对其中任何一个进行去抖动 2) 对开关动作的两个边缘进行去抖动,接通和断开 我有以下代码: main.c #include <avr/io.h> #include <avr/interrupt.h> #include "timer.h" #include "debounce.h" /*************

有人能帮我换一下吗?我读了Gansle和avr的文章,但仍然不是很清楚。不明白如何使用定时器溢出中断

我想在STK600上执行以下任务:

1) 读取开关,对其中任何一个进行去抖动 2) 对开关动作的两个边缘进行去抖动,接通和断开

我有以下代码:

main.c

#include <avr/io.h> 
#include <avr/interrupt.h> 
#include "timer.h" 
#include "debounce.h" 

/************* Constant definitions **********************/ 

#define NUM_SWITCHES      8 

/************* External Variable ******************/ 


/***************************************************************/

int main(void) 
{ 
   uint8_t LEDs = 0;                  // displayed data 
   uint8_t i;                        // loop counter 
   uint8_t   temp;                     // used for detecting switch changes from off to on 
   uint8_t switchData;                  // present switch data 
   uint8_t lastSwitchData = 0x00;         // previous switch data
   /* 
    * INITIALIZATIONS 
    */ 
   DDRB = 0x00;      /* Initialize port B for input (switches) */
   DDRD = 0xff;      /* Initialize port D for output (LEDs) */ 
   PORTD = ~LEDs;      /* All LEDs initially OFF */ 
   InitTimer0(); 
   sei(); 

   for ( ; ;)   /* BEGIN forever loop */ 
   { 
       switchData = GetSwitchData(); 

       if (switchData != lastSwitchData) 
       {    
         temp = switchData & ~lastSwitchData; 
         for (i=0; i<NUM_SWITCHES; i++) 
         { 
            switch (temp & _BV(i)) 
            { 
            case 0x01:               // count down 
               LEDs--; 
               break; 
            case 0x02:               // count up 
               LEDs++; 
               break; 
            case 0x04:               // rotate right 
               temp = LEDs & 0x01;      // LSB    
               LEDs >>= 1; 
               LEDs |= temp << 7;      // LSB rotates into MSB 
               break; 
            case 0x08:               // rotate left 
               temp = LEDs & 0x80;      // MSB 
               LEDs <<= 1; 
               LEDs |= temp >> 7;      // MSB rotates into LSB 
               break; 
            case 0x10:               // 1's complement 
               LEDs = ~LEDs; 
               break; 
            case 0x20:               // 2's complement 
               LEDs = ~LEDs; 
               LEDs++; 
               break; 
            case 0x40:               // swap nibbles: 
               temp = LEDs & 0x0F;      // low nibble 
               LEDs >>= 4;            // high nibble -> low nibble 
               LEDs |= temp << 4;      // low nibble -> high nibble 
               break; 
            default:   // switch 7, or no switches, do nothing 
               break; 
            } 
            PORTD = ~LEDs;    
            lastSwitchData = switchData; 
         } 
      } 
   } 
}
#包括
#包括
#包括“timer.h”
#包括“debounce.h”
/*************常量定义************************/
#定义NUM_开关8
/*************外部变量******************/
/***************************************************************/
内部主(空)
{ 
uint8\u t LED=0;//显示的数据
uint8\u t i;//循环计数器
uint8_t temp;//用于检测开关从关闭到打开的变化
uint8\u t switchData;//显示开关数据
uint8\u t lastSwitchData=0x00;//以前的交换机数据
/* 
*初始化
*/ 
DDRB=0x00;/*初始化输入端口B(交换机)*/
DDRD=0xff;/*为输出初始化端口D(LED)*/
PORTD=~LEDs;/*所有指示灯最初关闭*/
InitTimer0();
sei();
对于(;;)/*永远开始循环*/
{ 
switchData=GetSwitchData();
if(switchData!=lastSwitchData)
{    
temp=开关数据&~lastSwitchData;
对于(i=0;i>=1;
发光二极管|=温度>=4;//高半字节->低半字节
LED |=高温半尖晶石
打破
默认值://开关7,或无开关,不执行任何操作
打破
} 
PORTD=~led;
lastSwitchData=开关数据;
} 
} 
} 
}
定时器

#include <avr/interrupt.h> 
#include <util/delay.h> 
#include "Timer.h" 
#include "debounce.h" 

/* 
 *   We want to generate a timer-overflow interrupt every 5ms.  The clock rate 
 *   is 8 MHz, which gives a tick time of 125 nanoseconds.  The maximum count 
 *   is 256, which gives a maximum time span of 256 x 0.125 = 32 us.  This is too 
 *   short, so use the pre-scaler and set it to /256.  That lets us count to 256 x 
 *   32us = 8.192 ms.  The clock ticks are now 125ns  x 256 = 32 us.  We need to 
 *   count for 5ms/32us = 156.25 counts.  That means the counter must be 
 *   pre-set to 256 - 156 = 100 so that it will generate an overflow when it rolls 
 *   over from 0xFF to 0.  There will be 200 interrupts per second. 
 */ 

void InitTimer0(void) 
{ 
        cli( );            // no interrupts while we're changing timer params! 

        TIMSK0 = 0;             /* disable OCIE2A, OCIE2B, TOIE2 */ 
   TCNT0 = TIMER0_INIT_VAL;   /* init count register */ 
   TCCR0A = 0; 
   TCCR0B = (1 << CS02 );      /* select prescaler: = 8 MHz / 256 => 32 us */ 
   TIFR0 = (1 << OCF0A) | (1 << OCF0B) | (1 << TOV0);         /* clear interrupt-flags */ 
   TIMSK0 = (1 << TOIE0);   /* enable Timer0 overflow interrupt */ 

} 
/* 
 * Timer0 overflow interrupt handler. 
 */ 
ISR(TIMER0_OVF_vect) 
{ 
   TCNT0 = TIMER0_INIT_VAL;      /* re-initialize timer count */ 
   DebounceSwitches(); 
} 
/* 
 * This handler for unused interrupts will cause the program to stall with 
 * the four middle LEDs ON. 
 */ 
ISR(__vector_default) 
{ 
   PORTB = 0xC3; 
   for ( ; ; );   // null statement - loop forever here 
}
#包括
#包括
#包括“Timer.h”
#包括“debounce.h”
/* 
*我们希望每5毫秒生成一个定时器溢出中断。时钟频率
*是8MHz,它给出125纳秒的滴答时间。最大计数
*是256,最大时间跨度为256 x 0.125=32 us。这也是
*简而言之,使用预定标器并将其设置为/256。这样我们就可以计算到256 x
*32us=8.192毫秒。时钟滴答现在是125ns x 256=32 us。我们需要
*5ms/32us的计数=156.25计数。这意味着计数器必须
*预设为256-156=100,以便在滚动时产生溢出
*从0xFF切换到0。每秒将有200次中断。
*/ 
void InitTimer0(void)
{ 
cli();//更改计时器参数时没有中断!
TIMSK0=0;/*禁用OCIE2A、OCIE2B、TOIE2*/
TCNT0=TIMER0\u INIT\u VAL;/*初始化计数寄存器*/
TCCR0A=0;
TCCR0B=(1 32美国*/
TIFR0=(1“去抖动”开关基本上是等待开关从(例如)数字高电平状态变为数字低电平状态

您应该阅读更多关于debounce的内容:

您可以通过两种方式完成:定时器中断或简单地轮询开关的状态。在您的情况下,如果您想使用定时器int,您需要设置它,然后,当您检测到开关改变状态时,定时器开始计数以消除开关的抖动

轮询方法要简单得多,但并非总是最好的:

if( switch_is_pressed() ){
  delay_ms(DEBOUNCE_TIME);
  if( switch_is_pressed() ) return 1;
}
在尝试使用计时器之前,您应该阅读更多关于它是什么以及它是如何工作的。

开关的“去抖动”基本上是等待开关从(例如)数字高状态变为数字低状态

您应该阅读更多关于debounce的内容:

您可以通过两种方式完成:定时器中断或简单地轮询开关的状态。在您的情况下,如果您想使用定时器int,您需要设置它,然后,当您检测到开关改变状态时,定时器开始计数以消除开关的抖动

轮询方法要简单得多,但并非总是最好的:

if( switch_is_pressed() ){
  delay_ms(DEBOUNCE_TIME);
  if( switch_is_pressed() ) return 1;
}

在尝试使用计时器之前,您应该阅读更多关于它是什么以及它是如何工作的。

抱歉..我没有意识到这一点。否则,我将遵循此论坛中提供的帮助。抱歉..我没有意识到这一点。否则,我将遵循此论坛中提供的帮助。