我正在开展个人项目,攻击万用表并为其添加背光。我正在使用Attiny13。
我有以下代码:
/* IR_Switch.c
*
* Created: 30/11/2014 23:52:15
* Author: keenox
*/
#define F_CPU 128000UL // 128kHz osc, no prescaling
#define SEC(VAL) ((unsigned int)(VAL) * F_CPU / 256)
#define INV_SEC(VAL) (F_CPU / 256 / (unsigned int)(VAL))
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/sleep.h>
#define FORCE_INLINE //__attribute__((always_inline))
#define PWM_ON() do { TCCR0A |= _BV(COM0A1); } while (0)
#define PWM_OFF() do { TCCR0A &= ~_BV(COM0A1); } while (0)
#define COUNTER_ON() do { counter = 0; TIMSK0 = _BV(TOIE0); } while (0)
#define COUNTER_OFF() do { TIMSK0 = 0; } while (0)
#define LED_ON() ( (TCCR0A & _BV(COM0A1)) || (PORTB & _BV(PINB0)) )
#define BUTTON_DOWN() ((~PINB) & _BV(PINB3))
#define BUTTON_UP() (PINB & _BV(PINB3))
#define TIMEOUT 15
char step = 50;
unsigned long counter = 0;
void ledFull(unsigned char _val)
{
PWM_OFF();
if (_val)
PORTB |= _BV(PINB0);
else
PORTB &= ~_BV(PINB0);
}
void setLed()
{
if (OCR0A > 249)
ledFull(1);
else if (OCR0A < 6)
ledFull(0);
else
PWM_ON();
}
ISR(TIM0_OVF_vect)
{
counter++;
if (BUTTON_UP())
{
if (counter >= INV_SEC(4))
{
PORTB |= _BV(PINB4);
if (!LED_ON())
{
COUNTER_OFF();
}
else if (counter >= SEC(TIMEOUT))
{
ledFull(0);
COUNTER_OFF();
}
}
}
else if (counter > SEC(3))
{
// Change intensity every one sec while button down
counter -= SEC(1);
if (OCR0A > 249 || OCR0A < 6)
step = -step;
OCR0A += step;
setLed();
}
}
ISR(PCINT0_vect)
{
cli();
PCMSK = 0x0;
if (BUTTON_DOWN())
{
MCUCR |= _BV(ISC00); // Switch to rising edge
COUNTER_ON();
}
else
{
MCUCR &= ~_BV(ISC00); // Switch to falling edge
if (counter <= INV_SEC(2)) // Normal push
{
PORTB &= ~_BV(PINB4);
}
else if (counter <= SEC(2))
{
if (LED_ON())
{
ledFull(0);
COUNTER_OFF();
}
else
{
setLed();
}
}
}
PCMSK = _BV(PCINT3);
sei();
}
int main(void)
{
DDRB = _BV(PINB4) | _BV(PINB0); // All inputs, but PB4 output
PORTB = 0xFF & ~_BV(PINB0); // All 1, except PINB0
MCUCR |= _BV(ISC01); // Falling edge interrupt
GIMSK = _BV(PCIE); // Activate only pin change interrupt
PCMSK = _BV(PCINT3); // PB3 interrupt mask
TCCR0A = _BV(WGM01) | _BV(WGM00); // Set OC0A at TOP, Fast PWM
TCCR0B = _BV(CS00); // Timer on, No prescaling
OCR0A = 255; // Max bright
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
COUNTER_OFF();
while (1)
{
sleep_enable();
#if defined(sleep_bod_disable)
sleep_bod_disable();
#endif
sei();
sleep_cpu();
sleep_disable();
}
}
问题是它只在第一次中断(按钮按下)时唤醒,执行它然后什么都没有。 如果我不使用sleep(仅在(1);)时,程序按预期运行。 你知道这可能是什么问题吗?
LE:已添加完整代码。 如果我有:
sei();
while (1) {}
然后一切正常。我只想用睡眠来减少消耗。
答案 0 :(得分:2)
您的睡眠模式为&#34;掉电模式&#34; 如7.1.3 of the reference manual
中所述&#34;只有外部复位,看门狗复位,掉电 复位,INT0上的外部电平中断或引脚更改中断可唤醒MCU。此睡眠模式会暂停所有生成的时钟&#34;
因此处理按钮中断,但是按下按钮时启用的定时器中断永远不会触发,因为返回睡眠模式会禁用定时器。
你想要&#34;空闲&#34;睡眠模式。