прерывание вывода attiny85 нестабильно
Я пытаюсь научиться программировать MC, так что, возможно, я не очень много знаю о MC. Я попытался проверить прерывание вывода ATtiny85 с помощью этого простого кода
#include <avr/io.h>
#include <avr/interrupt.h>
void setup()
{
GIMSK = 0b00100000;
PCMSK = 0b00000001;
sei();
DDRB = 0b00010000;
}
void loop()
{
PORTB = 0b00010000;
_delay_ms(500);
PORTB = 0b00000000;
_delay_ms(500);
}
ISR(PCINT0_vect)
{
PORTB = 0b00010000;
_delay_ms(100);
PORTB = 0b00000000;
_delay_ms(100);
PORTB = 0b00010000;
_delay_ms(100);
PORTB = 0b00000000;
_delay_ms(100);
PORTB = 0b00010000;
_delay_ms(100);
PORTB = 0b00000000;
_delay_ms(100);
PORTB = 0b00010000;
_delay_ms(100);
PORTB = 0b00000000;
_delay_ms(100);
PORTB = 0b00010000;
_delay_ms(100);
PORTB = 0b00000000;
_delay_ms(100);
PORTB = 0b00010000;
_delay_ms(100);
PORTB = 0b00000000;
_delay_ms(100);
PORTB = 0b00010000;
_delay_ms(100);
PORTB = 0b00000000;
_delay_ms(100);
PORTB = 0b00010000;
_delay_ms(100);
PORTB = 0b00000000;
_delay_ms(100);
PORTB = 0b00010000;
_delay_ms(100);
PORTB = 0b00000000;
_delay_ms(100);
PORTB = 0b00010000;
_delay_ms(100);
PORTB = 0b00000000;
_delay_ms(100);
}
Это просто мигающий код с прерыванием, чтобы заставить светодиод мигать быстрее в 10 раз. У меня вопрос: почему иногда светодиод мигает быстрее во много раз, когда вывод прерывания ни к чему не подключен (открыт)? Разве у него не было внутреннего подтягивающего резистора или мне следует использовать внешний подтягивающий резистор в моей схеме?
Спасибо
@juliussin, 👍0
2 ответа
Лучший ответ:
Это не просто ответ, это некоторые комментарии и предложения по вашему вопросу. программа, которая, я надеюсь, поможет вам писать более чистый код:
Поскольку вы, похоже, избегаете использования базовой библиотеки Arduino, вы можете а также написать свой собственный
main()
вместо того, чтобы полагаться на тот, что есть в ядро. Таким образом, у вас есть простая программа на языке C, которую можно скомпилировать либо внутри, либо вне фреймворка Arduino.Вместо непрозрачных констант, таких как
0b00100000
, используйте имена битов. Эти названия определены в техническом описании и предоставлены avr-libc. Обычно они используются с макросом_BV()
, который расширяется до(1<<(x))
.Для тех из нас, у кого в голове нет полного технического описания, Полезны комментарии или два, описывающие, что делает каждый бит.
Чтобы изменить только один бит из порта, используйте синтаксис
PORTB |= ...;
илиPORTB &= ...
. Компилятор достаточно умен, чтобы превратить это в отдельные инструкции по сборке, а именноsbi
иcbi
.Вместо того, чтобы повторять десять раз одни и те же строки, используйте цикл.
Применяя эти предложения, ваша программа будет выглядеть примерно так:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
ISR(PCINT0_vect)
{
for (int i = 0; i < 10; i++) {
PORTB |= _BV(PB4);
_delay_ms(100);
PORTB &= ~_BV(PB4);
_delay_ms(100);
}
}
int main(void)
{
PORTB = _BV(PB0); // внутренний подтягивающий резистор на PB0
GIMSK = _BV(PCIE); // включить прерывание по смене контакта
PCMSK = _BV(PCINT0); // определение изменения контакта на PCINT0 = PB0
DDRB = _BV(PB4); // вывод PB4 как выход
for (;;) {
PORTB |= _BV(PB4);
_delay_ms(500);
PORTB &= ~_BV(PB4);
_delay_ms(500);
}
}
Внутренний подтягивающий резистор активируется только в том случае, если вы активируете его в своем коде. Для этого вам нужно записать 1
в соответствующий бит в регистре PORTB
, в то время как регистр DDRB
настроен на то, чтобы вывод был входом.
Таким образом, прерывание срабатывает случайным образом, поскольку вывод был плавающим.
Поскольку вы в настоящее время всегда пишете во весь PORTB
, вам нужно изменить последний бит на 1
при каждой записи PORTB
. Или вы можете записать 1
в него в setup()
и изменить только один выходной бит в PORTB
с помощью
PORTB ^= 0b00010000;
Это переключит только ваш выходной контакт.
- PCINT0, PCINT1, PCINT2 и т. д. на ATtiny45/85
- Как назначить прерывание на нажатие кнопки с помощью ATtiny? (прерывание не срабатывает с моим кодом)
- Прерывание переполнения таймера AVR не работает
- ATtiny85 AC Phase Control для регулировки яркости лампочки
- Прерывать каждую секунду на ATTiny84 (и спать все остальное)
- Attiny85 Watchdog срабатывает только один раз
- Attiny85 Таймер 1 компаратор B не работает должным образом (в то время как A работает)
- ATtiny85 со сном и последовательным портом