прерывание вывода 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 раз. У меня вопрос: почему иногда светодиод мигает быстрее во много раз, когда вывод прерывания ни к чему не подключен (открыт)? Разве у него не было внутреннего подтягивающего резистора или мне следует использовать внешний подтягивающий резистор в моей схеме?

Спасибо

, 👍0


2 ответа


Лучший ответ:

0

Это не просто ответ, это некоторые комментарии и предложения по вашему вопросу. программа, которая, я надеюсь, поможет вам писать более чистый код:

  1. Поскольку вы, похоже, избегаете использования базовой библиотеки Arduino, вы можете а также написать свой собственный main() вместо того, чтобы полагаться на тот, что есть в ядро. Таким образом, у вас есть простая программа на языке C, которую можно скомпилировать либо внутри, либо вне фреймворка Arduino.

  2. Вместо непрозрачных констант, таких как 0b00100000, используйте имена битов. Эти названия определены в техническом описании и предоставлены avr-libc. Обычно они используются с макросом _BV(), который расширяется до (1<<(x)).

  3. Для тех из нас, у кого в голове нет полного технического описания, Полезны комментарии или два, описывающие, что делает каждый бит.

  4. Чтобы изменить только один бит из порта, используйте синтаксис PORTB |= ...; или PORTB &= .... Компилятор достаточно умен, чтобы превратить это в отдельные инструкции по сборке, а именно sbi и cbi.

  5. Вместо того, чтобы повторять десять раз одни и те же строки, используйте цикл.

Применяя эти предложения, ваша программа будет выглядеть примерно так:

#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

Внутренний подтягивающий резистор активируется только в том случае, если вы активируете его в своем коде. Для этого вам нужно записать 1 в соответствующий бит в регистре PORTB, в то время как регистр DDRB настроен на то, чтобы вывод был входом.

Таким образом, прерывание срабатывает случайным образом, поскольку вывод был плавающим.

Поскольку вы в настоящее время всегда пишете во весь PORTB, вам нужно изменить последний бит на 1 при каждой записи PORTB. Или вы можете записать 1 в него в setup() и изменить только один выходной бит в PORTB с помощью

PORTB ^= 0b00010000;

Это переключит только ваш выходной контакт.

,