Всем привет! Решил вот сделать ребенку мигающие светодиоды на велосипед (а заодно наконец покодить под микроконтроллеры). Сам я по професии электрик (не радиотехника), но было это давно. Сечас программист на Java. Си тоже учил, но опять же давно. Купил я ATMega8A, программатор TL866A и несколько светодиодов. Позапускал пару простых примеров, посмотрел/почитал мануалы и решил приступить к самому главному. Мигать светодиодами надо программно и чтоб была возможность мигать одновременно с разной частотой. В связи с этим решил не использовать delay, а сделать правильно, через таймеры. В общем написал код для таймера, для мигания, отладил в Atmel Studio 6 (AVR Studio) и попытался проэмулировать это дело в протеусе. Вот тут началось неладное. Светодиоды мигали на глаз со случайной частотой. В отладчике студии время между вызовами таймера примерно совпадает с ожидаемым (+- пару миллисекунд). Упростил немного код, пробовал менять частоту мигания таймера, ничего не помогает. Я подумал что в протеусе что-то со временем во время эмуляции, и решил проверить на реальной МК. Но когда залил код в МК, оказалось что на нем светодиод вообще не мигает а просто светит. Думал дело в частоте МК, посмотрел фьюзы, вроде частота такая же как в отладке студии. Вот код:
Код
#include <avr/interrupt.h> // Установить бит в 1 #define SB(reg, bit) reg |= (1<<bit) // Установить бит в 0 #define CB(reg, bit) reg &= ~(1<<bit) // Проверить установлен ли бит #define VB(reg, bit) reg & (1<<bit) // Инвертировать бит #define TB(reg, bit) reg ^= (1<<bit) // 0b00000001 #define T100MS 0 // 0b00000010 #define T500MS 1 // 0b00000100 #define T1000MS 2 // 0b00001000 #define T2000MS 3 // 0b00010000 #define T5000MS 4 uint8_t timer500ms = 0; uint8_t timer1000ms = 0; uint8_t timer2000ms = 0; uint8_t timer5000ms = 0; uint8_t dataTimer = 0b00000000; // Прерывание каждые 100 миллисекунд // Устанавливает флаг в соответствии с прошедшим временем ISR(TIMER2_COMP_vect) { SB(dataTimer, T100MS); if ((++timer500ms) == 5) { timer500ms = 0; SB(dataTimer, T500MS); } if ((++timer1000ms) == 10) { timer1000ms = 0; SB(dataTimer, T1000MS); } if ((++timer2000ms) == 20) { timer2000ms = 0; SB(dataTimer, T2000MS); } if ((++timer5000ms) == 50) { timer5000ms = 0; TB(PORTC, 2); TB(PORTC, 3); TB(PORTC, 4); TB(PORTC, 5); SB(dataTimer, T5000MS); } } int main(void) { DDRB |= 0b00000000; DDRC |= 0b00111111; DDRD |= 0b00001111; // Пределитель 1:1 SB(TCCR2, CS20); // Режим сброс при совпадении CB(TCCR2, WGM20); SB(TCCR2, WGM21); // Прерывание при совпадении CB(TIMSK, TOIE2); SB(TIMSK, OCIE2); // Количество тактов перед прерыванием OCR2 = 100; // 1мгц // Разрешить глобальные прерывания asm("sei"); while(1) { if (VB(dataTimer, T5000MS)) { // TB(PORTC, 2); // TB(PORTC, 3); // TB(PORTC, 4); // TB(PORTC, 5); // Сброс времени CB(dataTimer, T5000MS); } } }
Думал что что-то с МК, добавил в основной цикл мигание с delay, примерно такое:
При этом в реальном МК светодиод мигал, но не через 1 секунду, а реже. К стати в это время другие светодиоды (оставшиеся на таймере) тоже мигали, но так же с неправильной частотой (вроде гораздо чаще чем должны). Прикрепляю схему подключения МК. но при тесте я подключал только один слабенький светодиод с резистором. Всего остального небыло. Очень прошу вашей помощи в решении этой проблемы.