И так, данный пост не является рассказом о какой-либо поделке. Это лишь тест, эксперимент, работы с таймером на atmega.
И смотрим что вышло... А вышло вроде все хорошо, только вот фигня получается: нажимаем кнопку и видим, что в первом регистре, вместо "1" горит черт знает что, а точнее один лишний сегмент "E". :( Почему? Я не знаю и понять не могу. День колупался - не пойму где лажа. :( Та же фигня на других цифрах. Не на всех правда. Но от этого не легче.
Может кто сказать, где у меня косяк? :) Просьба ногами не бить, ибо пробую писать под микроконтроллеры первые разы. Простенькие программы писал уже, а таймер вот в первый раз решил запрограммировать. :)
UPD: Нашел где косяк. :( Блин, давно на C/C++ не писал, привык к питону, вот и накосячил. :) В общем ошибка грубая и старая как мир! ;) Надо проверять размерность массива, а именно надо заменить:
на
и больше никогда так не делать. ;) Ну в принципе наскоро писал, поленился написать полностью, поставил цифрю... За что и огреб. :)
Для начала собираем простенькую схемку:
После чего загружаем туда следующий скетч:
//vim: syntax=c:tabstop=2:softtabstop=2:shiftwidth=2 #define BUTTON 12 // пин для подключения кнопки #define REGS 4 // количество регистров экрана int anods[REGS] = {8,9,10,11}; // пины анодов int pins[] = {0,1,2,3,4,5,6}; // пины семисегментного индикатора volatile int d[REGS] = {3,3,3,3}; // сюда пишем число для отображения volatile int reg = 0; // тут сохраняем номер разряда, с которым будет работать обработчик прерывания volatile int prev_reg = REGS - 1; // тут номер предыдущего обработанного разряда bool button_state = false; // текущее состояние кнопки int dig[] = { 0b01111111, // чисто - индекс 0 0b00111111, // - - индекс 1 0b00011100, // градус - индекс 2 0b01000000, // 0 - индекс 3 0b01111001, // 1 - индекс 4 0b00100100, // 2 - индекс 5 0b00110000, // 3 - индекс 6 0b00011001, // 4 - индекс 7 0b00010010, // 5 - индекс 8 0b00000010, // 6 - индекс 9 0b01111000, // 7 - индекс 10 0b00000000, // 8 - индекс 11 0b00010000, // 9 - индекс 12 0b00001000, // A - индекс 13 0b00000011, // b - индекс 14 0b01000110, // C - индекс 15 0b00100001, // d - индекс 16 0b00000110, // E - индекс 17 0b00001110, // F - индекс 18 }; ISR(TIMER2_OVF_vect) // вектор прерывания по переполнению { digitalWrite(anods[prev_reg], LOW); // отрубаем аноды матрицы int i = 0; // счетчик битов for(int mask=1; i<8; mask<<=1) // цикл маски битов { digitalWrite(pins[i++], (dig[d[reg]] & mask) ? HIGH: LOW); // берем поочередно биты и включаем нужные } digitalWrite(anods[reg], HIGH); // как выставили все биты катодов, можно включить и анод текущего разряда prev_reg = reg; // сохраняем номер зажженного разряда reg++; // увеличиваем разряд, что бы в следующий раз его включать if(reg == REGS) // если это последний разряд... reg = 0; // ... начинаем с начального разряда } void setup() { for(int i=0; i < sizeof(pins); i++) // выставим пины в out и погасим сегменты { pinMode(pins[i], OUTPUT); digitalWrite(pins[i], LOW); } pinMode(12, INPUT); // пин для кнопки поставим в in for(int i=0; i < sizeof(anods); i++) // отключим аноды { pinMode(anods[i], OUTPUT); digitalWrite(anods[i], LOW); } //настраиваем Timer2: делитель /256, WGM mode 0 - по переполнению TCCR2A = 0; TCCR2B = 1<<CS22 | 1<<CS21; //Timer2 включаем прерывание по переполнению TIMSK2 = 1<<TOIE2; //обнуляем таймер TCNT2 = 0; } void loop() { delay(100); // чуток подождем :) дребезг кнопки для простоты не обрабатываем if(digitalRead(BUTTON) == HIGH && !button_state) // если нажата кнопка и флаг не выставлен (ранее не была нажата) прибавляем в младший разряд единицу { button_state = true; // флаг выставляем, что кнопка нажата d[0]++; // собственно увеличиваем разряд на единицу for(int i=0; i<REGS; i++) // далее проверяем переполнение разрядов { if(d[i] > 12) { d[i] = 3; d[i+1]++; } } } else if(digitalRead(BUTTON) == LOW && button_state) // если кнопку отпустили, но ранее она была нажата (флаг выставлен) то... button_state = false; // ...убираем флаг
}
И смотрим что вышло... А вышло вроде все хорошо, только вот фигня получается: нажимаем кнопку и видим, что в первом регистре, вместо "1" горит черт знает что, а точнее один лишний сегмент "E". :( Почему? Я не знаю и понять не могу. День колупался - не пойму где лажа. :( Та же фигня на других цифрах. Не на всех правда. Но от этого не легче.
Может кто сказать, где у меня косяк? :) Просьба ногами не бить, ибо пробую писать под микроконтроллеры первые разы. Простенькие программы писал уже, а таймер вот в первый раз решил запрограммировать. :)
UPD: Нашел где косяк. :( Блин, давно на C/C++ не писал, привык к питону, вот и накосячил. :) В общем ошибка грубая и старая как мир! ;) Надо проверять размерность массива, а именно надо заменить:
for(int mask=1; i<8; mask<<=1) // цикл маски битов
на
for(int mask=1; i<sizeof(pins); mask<<=1) // цикл маски битов
и больше никогда так не делать. ;) Ну в принципе наскоро писал, поленился написать полностью, поставил цифрю... За что и огреб. :)