Как контролировать мощность attiny13a через прерывание смены контакта?
Я пытаюсь контролировать мощность attity13a и включать/выключать светодиод.
Я иду к целям:
- После нажатия кнопки0 светодиод будет мигать 5 секунд, а затем attiny13a перейдет в спящий режим.
- После того, как вы нажмете кнопку1, разбудите attiny13a, после чего загорится светодиод.
Кнопка0 для сна и мигания светодиода.
button1, чтобы проснуться и включить светодиод.
Не могли бы вы объяснить, что не так в этом скетче, пожалуйста?
спасибо за ваши ответы.
код:
#define F_CPU 1200000UL
#define LED PB2 // PB2
#define BUTTON1 PB1 // PCINT1
#define BUTTON0 PB0 // PCINT0
#define HIGH 1
#define LOW 0
#define INPUT 0
#define OUTPUT 1
#define INPUT_PULLUP 2
#define FALSE 0
#define TRUE 1
#define _BV(bit) (1 << (bit))
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
void pinMode(uint8_t pin, uint8_t mode)
{
if(mode == OUTPUT) // Закрепить как вывод
DDRB |= _BV(pin);
else // Пин как ввод или подтягивание ввода
{
DDRB &= ~_BV(pin); // Устанавливаем пин как вход
if(mode == INPUT_PULLUP)
PORTB |= _BV(pin); // Включить подтягивающие резисторы
}
}
void digitalWrite(uint8_t pin, uint8_t val)
{
if(val)
PORTB |= _BV(pin); // Установить вывод на высокий уровень
else
PORTB &= ~_BV(pin); // Устанавливаем низкий уровень вывода
}
uint8_t digitalRead(uint8_t pin)
{
return !!(PINB & _BV(pin));
}
// идти спать
ISR(PCINT0_vect)
{
if(digitalRead(BUTTON0)){
int i=0;
while(i<10){
blink();i=i+1;
}
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu();
}
}
//проснуться
ISR(PCINT1_vect){
if(digitalRead(BUTTON1)){
digitalWrite(LED, HIGH);
}
}
void blink(){
digitalWrite(LED, LOW);
_delay_ms(500);
digitalWrite(LED, HIGH);
_delay_ms(500);
}
int main(void)
{
pinMode(BUTTON0, INPUT_PULLUP);
pinMode(BUTTON1, INPUT_PULLUP);
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
// Устанавливает маску прерывания смены контакта PB0, PB1
PCMSK |= _BV(PCINT0)|_BV(PCINT1);
// Включает прерывания глобально после установки
//сей();
SREG |= _BV(SREG_I);
while(TRUE){}
}
@Kvartu, 👍1
Обсуждение1 ответ
Лучший ответ:
▲ 1
#define F_CPU 1200000UL
#define LED PB2 // PB2
#define BUTTON1 PB1 // INT0
#define BUTTON0 PB0 // PCINT0
#define HIGH 1
#define LOW 0
#define INPUT 0
#define OUTPUT 1
#define INPUT_PULLUP 2
#define FALSE 0
#define TRUE 1
#define _BV(bit) (1 << (bit))
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
void pinMode(uint8_t pin, uint8_t mode){
if(mode == OUTPUT) // Закрепить как вывод
DDRB |= _BV(pin);
else // Пин как ввод или подтягивание ввода
{
DDRB &= ~_BV(pin); // Устанавливаем пин как вход
if(mode == INPUT_PULLUP)
PORTB |= _BV(pin); // Включить подтягивающие резисторы
}
}
void digitalWrite(uint8_t pin, uint8_t val){
if(val)
PORTB |= _BV(pin); // Установить вывод на высокий уровень
else
PORTB &= ~_BV(pin); // Устанавливаем низкий уровень вывода
}
uint8_t digitalRead(uint8_t pin){
return !!(PINB & _BV(pin));
}
//проснуться
ISR(INT0_vect){
sleep_disable();
//кли(); // Отключаем глобальные прерывания
digitalWrite(LED, HIGH);
}
void blink(){
digitalWrite(LED, LOW);
_delay_ms(1000);
digitalWrite(LED, HIGH);
_delay_ms(1000);
}
// идти спать
ISR(PCINT0_vect)
{
//кли(); // Отключаем глобальные прерывания
if(!digitalRead(BUTTON0)){
cli(); // Отключаем глобальные прерывания
blink();
digitalWrite(LED, LOW);
sei(); // Включаем глобальные прерывания
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu();
}
}
int main(void)
{
// разрешено внешнее прерывание
MCUCR=0;
//MCUCR=0b00000000;
GIMSK|=_BV(INT0); // разрешено внешнее прерывание INT0 - PB1
// Устанавливает маску прерывания смены вывода
GIMSK|=_BV(PCIE);
PCMSK|=_BV(PCINT0);//PB0
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
pinMode(BUTTON1, INPUT_PULLUP);//INT0 - PB1
pinMode(BUTTON0, INPUT_PULLUP);//PCINT0 - PB0
// Включает прерывания глобально после установки
//SREG |= _BV(SREG_I);
sei(); // Включаем глобальные прерывания
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu();
while(TRUE){}
return 0;
}
,
@Kvartu
Смотрите также:
- При использовании Arduino Uno в качестве ISP: "Yikes! Invalid device signature" - плохое соединение, неверную конфигурацию или неверную версию avrdude?
- avrdude: ошибка проверки, первое несоответствие в байте 0x0000 : 0x00 != 0x16 с использованием USBasp
- Управление конфигурациями через EEPROM путем записи в шестнадцатеричный файл
- Аналог AtTiny читает всегда 1023
- Arduino IDE не будет использовать выбранный порт
- Проблемы с загрузкой кода в ATTiny84 с помощью Sparkfun AVR Pocket Programmer и ATTinyCore
- Предохранители ATTiny84 считываются как 0
- проблема с ценностью конверсии
Программа работает? Если нет, то каково его поведение?, @Edgar Bonet
Светодиод горит и ничего не происходит при нажатии на кнопки, @Kvartu
Как подключен светодиод?, @Majenko
Обратите внимание, что у
blink()
отсутствует задержка в состоянииHIGH
, а у tiny13 нетPCINT1_vect
., @Edgar BonetКороткая ножка светодиода подключена к GND. Длинная ножка светодиода подключена к резистору (1кОм) и к PB2, @Kvartu
Обновлена функция мерцания., @Kvartu
Объясните, пожалуйста, как правильно перейти в режим энергосбережения и вывести attiny из режима энергосбережения?, @Kvartu
Вам необходимо включить PCIE в GIMSK для распознавания прерываний PCINT. Также все прерывания проходят через PCINT0_vect, и вы должны различать контакты внутри него., @Majenko
Помимо проблем, указанных выше, ваш код также не учитывает отказ от переключения., @Gerben
действительно ли программа загружается в attiny13a? ... вы можете запустить простую программу, которая мигает светодиодом?, @jsotola