Библиотека 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 и обнаружил, что он не использует никаких таймеров или прерываний, поэтому я совершенно озадачен.
@stib, 👍0
1 ответ
Блин, это была какая-то нубская ошибка. У меня был настроен обработчик прерываний для прерывания переполнения, но когда я поменял код для прерывания Compare Match, я не сделал для него обработчик. Так что, поскольку есть прерывание без обработчика, похоже, оно просто сбрасывается, отсюда и весь этот блестящий мусор, который я видел на ЖК-дисплее.
Добавление этого решило проблему:
ISR(TIMER1_COMPA_vect)
{
j++;
}
- Использование millis() и micros() внутри процедуры прерывания
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Использование TIMER0_COMPB_vect
- Ошибка: "'lcd' does not name a type" при использовании библиотеки LiquidCrystal.
- Какие Arduino поддерживают ATOMIC_BLOCK?
- 4-битный счетчик вверх и вниз
- TCCR1A и TCCR2A на Леонардо
- Включить и отключить отдельные прерывания