Switch statement 开关去抖动
有人能帮我换一下吗?我读了Gansle和avr的文章,但仍然不是很清楚。不明白如何使用定时器溢出中断 我想在STK600上执行以下任务: 1) 读取开关,对其中任何一个进行去抖动 2) 对开关动作的两个边缘进行去抖动,接通和断开 我有以下代码: main.cSwitch 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" /*************
#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;
}
在尝试使用计时器之前,您应该阅读更多关于它是什么以及它是如何工作的。抱歉..我没有意识到这一点。否则,我将遵循此论坛中提供的帮助。抱歉..我没有意识到这一点。否则,我将遵循此论坛中提供的帮助。