Библиотека LiquidCrystal и таймеры кажутся несовместимыми.

Если я установлю таймер 2 в режим сравнения совпадений, мой ЖК-дисплей перестанет работать. Если я использую прерывание переполнения, оно работает нормально.

Вот мой тестовый код. У меня есть функция цикла(), которая делает свое дело, и прерывание по таймеру, которое увеличивает другую переменную, просто чтобы показать, что она работает.

#include <LiquidCrystal.h>
#include <avr/interrupt.h>
#include <avr/io.h>

LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );   //Пыла для ЖК-экрана Freetronics 16x2. ЖК-дисплей:

int i;
volatile int j;
void setup()
{
  i=0;
  j=0;
  //кнопка ввода постоянного тока
  pinMode( A0, INPUT ); //убедимся, что A0 является входом
  digitalWrite( A0, LOW ); //убедимся, что подтягивание отключено на A0
  //управление подсветкой ЖК-дисплея
  pinMode( 10, OUTPUT ); //D10 — это вывод
  digitalWrite( 10, HIGH ); //вывод управления подсветкой D10 имеет высокий уровень (включен)
  //настраиваем количество столбцов и строк на ЖК-дисплее:
  lcd.begin( 16, 2 );

  // установка прерывания по таймеру
  cli(); //отключаем глобальные прерывания
  TCCR1A = 0;   //устанавливаем tccr1a и tccr1b в 0
  TCCR1B = 0;
  //устанавливаем бит cs10 и cs12, чтобы таймер работал с тактовой частотой iSpeed/ 1024
  TCCR1B |= (1 << CS10);
  TCCR1B |= (1 << CS12);

  // Режим сравнения совпадений **Не работает**:
  //устанавливаем регистр сравнения совпадений
  OCR1A = 15624;
  // включаем режим CTC
  TCCR1B |= (1 << WGM12);
  // включаем прерывание сравнения Timer1
  TIMSK1 = (1 << OCIE1A);

  // Режим переполнения **Работает**
  // включаем прерывание переполнения
  // TIMSK1 = (1 << TOIE1);

  //включаем глобальное прерывание
  sei();
}
void loop()
{
  lcd.setCursor( 0, 0 ); //верхний левый
  lcd.print(i);
  lcd.setCursor(0,1); //Нижний левый
  lcd.print(j);
  delay(500);
  lcd.clear();
  i++;
}

ISR(TIMER1_OVF_vect)
{
  j++;
}

Если я использую прерывания переполнения, все работает нормально, счетчик цикла() отображается в верхней строке, а счетчик прерываний — во второй, но, используя прерывания переполнения, я ограничен тем временем, которое дают мне различные прескалеры.

Если я использую сравнение, на ЖК-дисплее в первой строке отображаются лишь слабые мерцающие квадраты, как будто он что-то делает, но слишком быстро, чтобы ЖК-дисплей мог отобразить.

Я посмотрел исходный код Liquidcrystal.cpp и обнаружил, что он не использует никаких таймеров или прерываний, поэтому я совершенно озадачен.

, 👍0


1 ответ


1

Блин, это была какая-то нубская ошибка. У меня был настроен обработчик прерываний для прерывания переполнения, но когда я поменял код для прерывания Compare Match, я не сделал для него обработчик. Так что, поскольку есть прерывание без обработчика, похоже, оно просто сбрасывается, отсюда и весь этот блестящий мусор, который я видел на ЖК-дисплее.

Добавление этого решило проблему:

ISR(TIMER1_COMPA_vect)
{
  j++;
}
,