RGB сосулька

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Аватара пользователя
Сообщения: 109
Зарегистрирован: Ср дек 09, 2009 00:22:27
Откуда: г. Бендеры Приднестровье.

Сообщение ment-bu2 »

Изображение
это желтеньким чего такое?


Если я правильно понял - то это кажись резюки...?

И ещё... каким программатором шили?
Спасибо.
Реклама
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

сопротивления 200 Ом их там 20 штук
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 109
Зарегистрирован: Ср дек 09, 2009 00:22:27
Откуда: г. Бендеры Приднестровье.

Сообщение ment-bu2 »

[uquote="Serzh2000",url="/forum/viewtopic.php?p=3526948#p3526948"]сопротивления 200 Ом их там 20 штук[/uquote]
чем шили? какая программа и какой программатор?
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

программатор
Вложения
avrdude_prog-v.3.3.zip
(813.53 КБ) 203 скачивания
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 109
Зарегистрирован: Ср дек 09, 2009 00:22:27
Откуда: г. Бендеры Приднестровье.

Сообщение ment-bu2 »

[uquote="Serzh2000",url="/forum/viewtopic.php?p=3526951#p3526951"]программатор[/uquote]
Принял. Спасибо! Буду делать звёздочку. Удачи Вам!!
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 557
Зарегистрирован: Пт июл 04, 2008 19:29:15
Откуда: Мурманск

Сообщение Bullet »

https://radiokot.ru/circuit/light/run/78/
Есть эффект капли, читай, изучай, делай.
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA

Сообщение GoldenAndy »

Давайте тогда попробуем разложить все по полочкам.

есть фрагмент схемы:
Изображение
Это фрагмент реальной схемы часов с подсветкой, там реализовано 32 уровня яркости индивидуально для каждого светодиода (я когда то выкладывал описание этих часов - вот. Там и видосик есть свечения этих РГБ светодиодов.)

На схеме - 12 РГБ-светодиодов, подключенных к двум портам Меги 32.
По факту это 36 отдельных светодиодов, включенных матрицей 6х6.
(на самом деле не важно, какая мега, тут подойдет даже тинька 2313 - у нее тоже найдется 12 линий ввода/вывода)

Т.е. реализована динамическая индикация (почти как в звездочке, сделанной на базе часов - только в часах матрица - 4х8).

Здесь к 6 битам порта А подключено по 6 анодов светодиодов, к 6 линиям порта В - по 6 катодов, через резисторы.
Вот что бы зажечь один светодиод - нужно подать 1 на вывод порта А и 0 на вывод порта В.
На пересечении линий от портов А и В загорится светодиод.

Можно вывести 1 на линию порта А и нужное количество 0 на линии порта В - тогда загорится нужное число светодиодов, подключенных к этой линии от порта А.
Потом мы на эту линию порта А можем вывести 0, а 1 - на следующую линию порта А, тогда , подавая нолики и единички на порт В, можно зажечь следующие 6 светодиодов.

Если переключать линии порта быстро-быстро (условно - 1000 раз в секунду), то можно на эту матрицу выводить нужное изображение.

А теперь немножко магии.

Мы выводим на линию РА0 единичку на период 1 мс.
А на линии РВ0 и РВ1 - выводим нолик.
Но через 0,5мс мы выводим на линию РВ1 единичку.

И что у нас получается ? Светодиод, подключенный к линии РВ0 горел 1 миллисекунду, а тот, что на РВ1 - пол миллисекунды.
Визуально - светодиоды будут светиться с разной яркостью.

Ниже я опишу алгоритм для 4 уровней яркости.

Внимательно смотрим за руками.
у атмеловских контроллеров есть таймеры. Их целых два даже в 2313 тине.
А в Меге 8 - целых три. Нам хватит одного.

Открываете даташит на ваш контроллер. Смотрите, как настроить таймер, что бы он переполнялся 4-5 тысяч раз за секунду.
Навскидку - тактовая 8 МГц, таймер 8 бит, итого, при предделителе =1 он переполнится 8000000/256=31250 раз в секунду. Многовато.
Ставим делитель 8. 8000000/(8*256) = 3906 раз в секунду. Почти то , что надо. На этом и остановимся.

Теперь заводим себе массивчик двумерный по размеру нашей матрички светодиодов. В этот массив в основной программе будем писать состояния нужные наших светодиодов - яркость кажого светодиода - от 0 до 4. 0 - не горит, 4 - горит с максимальной яркочтью.

Заводим 2 глобальных счетчика - один - это счетчик наших линий, подключенных к катодам , он будет считать от 0 до 5, второй - счетчик фаз яркости для каждой линии.
Изначально, при старте счетчики обнулены.

И начинаем шаманить в обработчике прерывания переполнения таймера (не забыть разрешить прерывания от таймера и глобальные):
Проверяем состояние счетчика фаз. Если нулевое:
  • выдаем единички на все светодиодные линии порта В - светодиоды погаснут.
  • Выдаем нолик на линию порта А , соответствующую значению счетчика линий.
  • Увеличиваем счетчик линий. Если он стал больше 5 (у нас же матрица 6х6 - счетчик считает от 0 до 5) - пишем в него 0.
  • Пишем в счетчик фаз четверку.
  • выводим 1 на линию порта А, соответствующую счетчику линий.
теперь перебираем значения в нашем массиве яркостей для выбранной линии.
И сравниваем значение в массиве со значением счетчика фаз. Если они равны = выводим на соответствующую линию потра В нолик. Остальные биты порта В не трогаем!
Теперь уменьшаем счетчик фаз на 1 - и выходим из прерывания.

Все, автомат управления светодиодами - готов.
Он тикает почти 4000 раз в секунду.
каждые 4 тика переключает линию матрицы светодиодов, в течении 4 тактов управляет длительностью свечения светодиодов в выбранной линии. Т.е. по сути у нас получилось программное управление яркостью для 36 независимых светодиодов.
Линии переключаются со скоростью 3906/4 - 976 раз в секунду. Цикл перебора всех 6 линий будет выполняться 976/6 = 162 раза в секунду.
И при этом мы можем управлять яркостью каждого светодиода независимо.

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

Если вдруг есть сложности с англоязычным даташитом - можно посмотреть книжки Евстифеева - по сути это вольный перевод даташитов.
Так же поищите книжицу Белова - Самоучитель разработчика устройств на МК AVR - в ней, кроме описания контроллера тини 2313, есть еще разработка нескольких схем, в т.ч. и бегущих огней (надо если - я куда то выложу Белова и Евстифеева).

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

И да, не у всех есть установленный протеус, посему лучше выкладывать схему в виде картинки в пост с вопросом и прикладывать прямо в текст поста фрагмент листинга. (для листинга в редакторе даже кнопочка есть - Code)
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

с новым годом!

все каникулы провозился все равно не пойму.
теперь перебираем значения в нашем массиве яркостей
как их перебрать весь интернет просмотрел все пишут в авр студио и используют библиотеки....

пофигу эта динамика пока хоть 10 светиков засветить с разной яркостью.
Изображение
Навскидку - тактовая 8 МГц, таймер 8 бит, итого, при предделителе =1 он переполнится 8000000/256=31250 раз в секунду. Многовато.
Ставим делитель 8. 8000000/(8*256) = 3906 раз в секунду. Почти то , что надо. На этом и остановимся.
сделано

Код: Выделить всё

TCNT0=0b00000000;
TCCR0=0b00000100;
Теперь заводим себе массивчик двумерный по размеру нашей матрички светодиодов. В этот массив в основной программе будем писать состояния нужные наших светодиодов - яркость кажого светодиода - от 0 до 4. 0 - не горит, 4 - горит с максимальной яркочтью.
с двумерными массивами не знаю как пока давайте без динамики попробуем
счетчик фаз яркости
сделано

Код: Выделить всё

 interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
 
    faza++; if (faza > 10) {
		faza = 0;
        }
			
 
 }
теперь перебираем значения в нашем массиве яркостей для выбранной линии.
И сравниваем значение в массиве со значением счетчика фаз. Если они равны = выводим на соответствующую линию потра В нолик. Остальные биты порта В не трогаем!
Теперь уменьшаем счетчик фаз на 1 - и выходим из прерывания.
тут я застрял. в принципе понятно, что Вы объяснили, но на практике как это сделать не получается у меня :solder:
Вложения
sosulka.zip
(60.2 КБ) 205 скачиваний
сосулька.png
(63.97 КБ) 376 скачиваний
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA

Сообщение GoldenAndy »

Так. Язык Си. это уже проще.

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

[uquote="goldenandy",url="/forum/viewtopic.php?p=3537314#p3537314"]есть фрагмент схемы:
Изображение
Теперь заводим себе массивчик двумерный по размеру нашей матрички светодиодов. В этот массив в основной программе будем писать состояния нужные наших светодиодов - яркость кажого светодиода - от 0 до 4. 0 - не горит, 4 - горит с максимальной яркочтью.[/uquote]

двумерный массив - он как одномерный. но только двумерный.
unsigned char LedsLevels[6][6]; - вот как раз массивчик 6*6 байтиков. Все просто.
Обращаемся к нему так : LedsLevels[3][5] = 4; - вот мы в ячейку по адресу 3:5 записали четверку.

[uquote="goldenandy",url="/forum/viewtopic.php?p=3537314#p3537314"]Заводим 2 глобальных счетчика - один - это счетчик наших линий, подключенных к катодам , он будет считать от 0 до 5, второй - счетчик фаз яркости для каждой линии.
Изначально, при старте счетчики обнулены.[/uquote]
unsigned char Lines = 0, Phase = 0;

[uquote="goldenandy",url="/forum/viewtopic.php?p=3537314#p3537314"]И начинаем шаманить в обработчике прерывания переполнения таймера (не забыть разрешить прерывания от таймера и глобальные):
Проверяем состояние счетчика фаз. Если нулевое:
  • выдаем единички на все светодиодные линии порта В - светодиоды погаснут.
  • Выдаем нолик на линию порта А , соответствующую значению счетчика линий.
  • Увеличиваем счетчик линий. Если он стал больше 5 (у нас же матрица 6х6 - счетчик считает от 0 до 5) - пишем в него 0.
  • Пишем в счетчик фаз четверку.
  • выводим 1 на линию порта А, соответствующую счетчику линий.
[/uquote]

Код: Выделить всё

    if (Phase==0) {
        PORTB = 0x3F;
        PORTA = 0;
        Lines++;
        if (Lines>5) Lines = 0;
        Phase = 4;
        PORTA = 1 << Lines;  //выводим 1 на линию порта А, соответствующую счетчику линий.
    }
[uquote="goldenandy",url="/forum/viewtopic.php?p=3537314#p3537314"]теперь перебираем значения в нашем массиве яркостей для выбранной линии.
И сравниваем значение в массиве со значением счетчика фаз. Если они равны = выводим на соответствующую линию потра В нолик. Остальные биты порта В не трогаем!
Теперь уменьшаем счетчик фаз на 1 - и выходим из прерывания.[/uquote]

перебираем:

Код: Выделить всё

unsigned char i;
for (i=0; i<6; i++) {
   if (LedsLevels[Lines][i]==Phase) PORTB &= ~(1<<i);//выводим на соответствующую линию потра В нолик
}
Phase--;

___________________

TCNT0=0b00000000;
TCCR0=0b00000100;

Не пишите так. Это 1.Нечитаемо, 2. зависит от контроллера.
Правильно как то вот так:

Код: Выделить всё

	TCCR1A = ( 0 << WGM11 ) | ( 0 << WGM10 );
	TCCR1B = ( 0 << WGM13 ) | ( 1 << WGM12 ) | ( 0 << CS12 ) | ( 0 << CS11 ) | ( 1 << CS10 );
	OCR1A = F_CPU/1000 - 1;
	TIMSK |= ( 1 << OCIE1A ); 
Да, тут придется больше писать, но это,блин, читаемый код!
И вероятность ошибок гораздо ниже.

_____
У меня светодиоды спецом были подключены анодами к одному порту, а катодами к другому, причем не в разнобой, а последовательно, к битам от 0 до 5.
Это позволяет перебирать все эти биты портов в циклах.
У вас просто 11 статически подключенных диодов.

Тут придется каждый светик включать и выключать индивидуально.

заводим массив яркостей для 11 светодиодов
volatile unsigned char Leds[11];
и счетчик фаз
volatile unsigned char Phase = 0;

обработчик прерывания:

Код: Выделить всё

if (Phase == 0 ){
  Phase = 4; // 4 уровня яркости
  // гасим все 10 светодиодов
  PORTC=0;
  PORTD=0;
}
// а теперь перебираем ваши яркости в массиве.
// я тут напишу линейный код, если у вас будет желание обернуть это хозяйство в цикл или еще как сократить/алгоритмизировать - не буду возражать
if (Leds[0] == Phase) PORTD |= (1 << 0);
if (Leds[1] == Phase) PORTD |= (1 << 1);
if (Leds[2] == Phase) PORTD |= (1 << 2);
if (Leds[3] == Phase) PORTD |= (1 << 3);
if (Leds[4] == Phase) PORTD |= (1 << 4);
if (Leds[5] == Phase) PORTD |= (1 << 5);
if (Leds[6] == Phase) PORTD |= (1 << 6);
if (Leds[7] == Phase) PORTD |= (1 << 7);
if (Leds[8] == Phase) PORTC |= (1 << 1);
if (Leds[9] == Phase) PORTC |= (1 << 0);
if (Leds[10] == Phase) PORTC |= (1 << 5);
Phase --;

вот как то так оно будет.

Модификатор volatile говорит компилятору, что обращение к массиву и к счетчику фазы не нужно оптимизировать....

все пишут в авр студио и используют библиотеки....
Нуууу... давайте не будем путать язык программирования и среду разработки.
Авр Студия удобна для написания кода.
Но с тем же успехом можно писать в NotePad++ - там тоже есть подсветка синтаксиса и куча вкусностей...

А библиотеки? Ну так удобнее - большинство простых операций уже описаны в виде библиотек. Так проще.
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

спасибо большое подробные разъяснения!!!
попробую дальше повозится прям вдохновение появилось, а то чуть руки не опустились на эту сосульку.

то ка не догнал
OCR1A = F_CPU/1000 - 1;
что это означает
зачем частоту делить 1000 и вычесть 1
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA

Сообщение GoldenAndy »

[uquote="Serzh2000",url="/forum/viewtopic.php?p=3542194#p3542194"]то ка не догнал

Код: Выделить всё

OCR1A = F_CPU/1000 - 1;
что это означает
зачем частоту делить 1000 и вычесть 1[/uquote]

Не заморачивайтесь, это просто пример, как нужно записывать инициализацию периферии МК.

У меня первый таймер был использован как System Clock, он должен срабатывать 1000 раз в секунду.
WGM1[3:0] = 0100 - это СТС режим таймера.
Считает он от 0 и до OCR1A.

Тактируется напрямую от F_CPU.

Соответственео, что бы получить прерывание от таймера 1000 раз в секунду, таймер должен отсчитать F_CPU/1000 импульсов от источника.

А , поскольку таймер считает от 0 - то F_CPU/1000-1.

При клоке в 8 МГц имеем верх счета 8000000/1000-1 = 7999.
Т.е. таймер каждые 8000 тиков будет мне генерировать прерывание.
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

ясно.

и еще раз спасибо у меня кое что получается
в протеусе почти не видно попробую собрать на макетки завтро
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

я с ново в тупик
никак не пойму
заводим массив яркостей для 11 светодиодов
volatile unsigned char Leds[11];
если нет фигурных скобок то там все нолики, так?
теперь перебираем значения в нашем массиве яркостей для выбранной линии.
И сравниваем значение в массиве со значением счетчика фаз. Если они равны = выводим на соответствующую линию потра В нолик. Остальные биты порта В не трогаем!
Теперь уменьшаем счетчик фаз на 1 - и выходим из прерывания.
там одни ноли и есть
if (ноль == Phase) PORTD |= (1 << порт);

то есть когда Phase равна нулю светики все загорятся по очереди, но Leds никогда не станет 1,2,3,4 так?

как же яркость меняется?

и еще в протеусе смотрю постоянно Phase выходит за пределы ноля и четверки
Изображение
я не так настроил таймер0 ?
Спойлер#include <mega8.h>
#include <delay.h>

unsigned char Leds[10];
volatile unsigned char Phase = 4;// счетчик фаз


// ----------------------------------------------------------------------------------------
interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
if (Phase == 0 ){
Phase = 4; // 4 уровня яркости

PORTC=0; // гасим все 10 светодиодов
PORTD=0;
}
}//=================== main ==========


//основаня функция
void main(void){


//настройка портов

PORTB=0b00000000;
DDRB=0b00000000;
PORTC=0b00000000; //порт С 4 первые по умолчанию 1
DDRC=0b00000011; //порт С 4 первые ноги на вывод
PORTD=0b00000000; //порт D по умолчанию все ноги на 0
DDRD=0b11111111; //порт D все ноги на вывод


TCCR0 = 0;
TIMSK |= 0b00000001;
TCCR0 |= (0<<CS02)|(1<<CS01)|(0<<CS00);

#asm("sei") // Глобальные прерывания включения

// -------------------------------- рабочая часть ------------------------------------------
while (1) {

// а теперь перебираем ваши яркости в массиве.
// я тут напишу линейный код, если у вас будет желание обернуть это хозяйство в цикл или еще как сократить/алгоритмизировать - не буду возражать
if (Leds[0] == Phase) PORTD |= (1 << 0);
if (Leds[1] == Phase) PORTD |= (1 << 1);
if (Leds[2] == Phase) PORTD |= (1 << 2);
if (Leds[3] == Phase) PORTD |= (1 << 3);
if (Leds[4] == Phase) PORTD |= (1 << 4);
if (Leds[5] == Phase) PORTD |= (1 << 5);
if (Leds[6] == Phase) PORTD |= (1 << 6);
if (Leds[7] == Phase) PORTD |= (1 << 7);
if (Leds[8] == Phase) PORTC |= (1 << 1);
if (Leds[9] == Phase) PORTC |= (1 << 0);
Phase --;

}; // ----------------------------- рабочая часть (end) ------------------------------------

} // ================= end main ======

//
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- The End -=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
может что не так понял не сочтите за наглость объясните, пожалуйста.
Вложения
sosulka.zip
(62.71 КБ) 185 скачиваний
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

Где-то так
Спойлер

Код: Выделить всё

/*******************************************************
This program was created by the
CodeWizardAVR V3.10 Advanced
Automatic Program Generator
© Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date    : 16.12.2018
Author  : 
Company : 
Comments: 


Chip type               : ATmega168P
Program type            : Application
AVR Core Clock frequency: 16,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*******************************************************/

#include <mega168.h>

#include <delay.h>


volatile unsigned int f=400,    // время кадра
             h=5,      // число повторов эффекта
             z=1000;   // ms для паузы после эффекта 
                         
volatile unsigned char Phase=0, Lines = 0; 

// Declare your global variables here
     //unsigned char A[5][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}};
     //unsigned char B[5][4] = {{0,0,0,1},{0,0,0,1},{0,0,0,1},{0,0,0,1},{0,0,0,1}};
    // unsigned char C[5][4] = {{2,0,2,0},{2,0,2,0},{2,0,2,0},{2,0,2,0},{2,0,2,0}};
    // unsigned char D[5][4] = {{3,0,3,0},{3,0,3,0},{3,0,3,0},{3,0,3,0},{3,0,3,0}};
    // unsigned char E[5][4] = {{0,4,0,0},{0,4,0,0},{0,4,0,0},{0,4,0,0},{0,4,0,0}};
    // unsigned char F[5][4] = {{0,4,0,0},{0,4,0,0},{0,4,0,0},{0,4,0,0},{0,4,0,0}};
    // unsigned char G[5][4] = {{3,0,3,0},{3,0,3,0},{3,0,3,0},{3,0,3,0},{3,0,3,0}};
    // unsigned char H[5][4] = {{2,0,2,0},{2,0,2,0},{2,0,2,0},{2,0,2,0},{2,0,2,0}};  
    // unsigned char I[5][4] = {{0,0,0,1},{0,0,0,1},{0,0,0,1},{0,0,0,1},{0,0,0,1}};
    // unsigned char J[5][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}};



flash char flasher_0[200] =
	{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
      2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,
      3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,
      0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,
      0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,
      3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,
      2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,
      0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    };   
    

flash char flasher_1[200] =
	{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
      0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
      0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,
      0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,
      0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,
      0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,
      0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,
      0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4
    };

flash char flasher_2[200] =
	{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
      2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
      2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
      4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
      4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
    };
            
   volatile flash char *u; 
   volatile char a;   
   
// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
unsigned char i; 

    if (Phase==0) {
        PORTD = 0x3F;
        PORTC = 0;
        Lines++;
        if (Lines>5) Lines = 0;
        Phase = 4;
        PORTC = 1 << Lines;  //выводим 1 на линию порта А, соответствующую счетчику линий.
    }

for (i=0; i<4; i++) {
   //if (LedsLevels[Lines][i]==Phase) PORTD &= ~(1<<i);//выводим на соответствующую линию потра В нолик
   a = *(u+Lines*4+i);
   if (a==Phase) PORTD &= ~(1<<i);//выводим на соответствующую линию потра В нолик
}
Phase--;
}


void view_pauza(void) {
       delay_ms(z);
}  
          
void view_flasher_0(void) {
     int i,j;             
    
   for (j =0; j<h;++j){
   
   for (i =0; i<9;++i){ 
      
      u = &(flasher_0[i*20]);
        delay_ms(f);
     } 
      
  }
  view_pauza();
}


void view_flasher_1(void) {
     int i,j;             
    
   for (j =0; j<h;++j){
   
   for (i =0; i<9;++i){ 
      
      u = &(flasher_1[i*20]);
        delay_ms(f);
     } 
      
  }
  view_pauza();
}

void view_flasher_2(void) {
     int i,j;             
    
   for (j =0; j<h;++j){
   
   for (i =0; i<9;++i){ 
      
      u = &(flasher_2[i*20]);
        delay_ms(f);
     } 
      
  }
  view_pauza();
}

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit6=In Bit5=In Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out 
DDRC=(0<<DDC6) | (0<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
// State: Bit6=T Bit5=T Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=0 
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=Out Bit2=Out Bit1=Out Bit0=Out 
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=0 Bit2=0 Bit1=0 Bit0=0 
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 500,000 kHz
// Mode: Normal top=0xFF
// OC2A output: Disconnected
// OC2B output: Disconnected
// Timer Period: 0,512 ms
ASSR=(0<<EXCLK) | (0<<AS2);
TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (0<<WGM21) | (0<<WGM20);
TCCR2B=(0<<WGM22) | (0<<CS22) | (1<<CS21) | (1<<CS20);
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (0<<TOIE0);

// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (0<<TOIE1);

// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=(0<<OCIE2B) | (0<<OCIE2A) | (1<<TOIE2);

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIMSK=(0<<INT1) | (0<<INT0);
PCICR=(0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);

// USART initialization
// USART disabled
UCSR0B=(0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (0<<RXEN0) | (0<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
ADCSRB=(0<<ACME);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR1=(0<<AIN0D) | (0<<AIN1D);

// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);

// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here
         view_flasher_0();    
         view_flasher_1();
         view_flasher_2();
         
         
      }  
}
Пусть тебе таймер помогут настроить, а то у меня под 168мегу и 16МГц.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA

Сообщение GoldenAndy »

[uquote="Serzh2000",url="/forum/viewtopic.php?p=3542936#p3542936"]я с ново в тупик
никак не пойму
заводим массив яркостей для 11 светодиодов
volatile unsigned char Leds[11];
если нет фигурных скобок то там все нолики, так?[/uquote]
По стандарту Си - все переменные при объявлении обнуляются.
Но я стараюсь на это не надеяться и в программе обычно рисую секцию инициализации железа и переменных.


По коду - вы немножко напутали.

У вас есть 8-битный таймер. Вы его должны настроить на счет с предделителем 8. Для меги 8 - это таймеры 0 и 2, для тиньки 2313 - только таймер 0.
Можно настроить и таймер 1 в 8-битном режиме.

Вам нужно разрешить в настройках таймера прерывание по переполнению OVF0 (или OVF2, если заюзаете Т2 меги8)
в основной программе после настройки периферии и инициализации своих переменных разрешить глобальные прерывания.

теперь выписываем обработчик прерывания таймера.
В него попадает ВСЯ секция
Спойлер

Код: Выделить всё

if (Phase == 0 ){
  Phase = 4; // 4 уровня яркости
  // гасим все 10 светодиодов
  PORTC=0;
  PORTD=0;
}
// а теперь перебираем ваши яркости в массиве.
// я тут напишу линейный код, если у вас будет желание обернуть это хозяйство в цикл или еще как сократить/алгоритмизировать - не буду возражать
if (Leds[0] == Phase) PORTD |= (1 << 0);
if (Leds[1] == Phase) PORTD |= (1 << 1);
if (Leds[2] == Phase) PORTD |= (1 << 2);
if (Leds[3] == Phase) PORTD |= (1 << 3);
if (Leds[4] == Phase) PORTD |= (1 << 4);
if (Leds[5] == Phase) PORTD |= (1 << 5);
if (Leds[6] == Phase) PORTD |= (1 << 6);
if (Leds[7] == Phase) PORTD |= (1 << 7);
if (Leds[8] == Phase) PORTC |= (1 << 1);
if (Leds[9] == Phase) PORTC |= (1 << 0);
if (Leds[10] == Phase) PORTC |= (1 << 5);
Phase --;
По сути - это весь обработчик прерывания.

Всё. Переменную Phase в основной программе мы не трогаем. И никак больше светодиодами не управляем.
Этим займется прерывание. Ему будет совершенно фиолетово, что вы делаете в основной программе. Оно будет молотить свои 3906 раз в секунду.

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


Т.е. будет как то так:
Спойлер

Код: Выделить всё

#include <mega8.h>
#include <delay.h>

unsigned char Leds[10];
volatile unsigned char Phase = 0;// счетчик фаз  <----------------------------------- должен стартовать с 0


// _______
interrupt [TIM0_OVF] void timer0_ovf_isr(void) { 
if (Phase == 0 ){
   Phase = 4; // 4 уровня яркости
   PORTC=0; // гасим все 10 светодиодов
   PORTD=0;
   } 
if (Leds[0] == Phase) PORTD |= (1 << 0);
if (Leds[1] == Phase) PORTD |= (1 << 1);
if (Leds[2] == Phase) PORTD |= (1 << 2);
if (Leds[3] == Phase) PORTD |= (1 << 3);
if (Leds[4] == Phase) PORTD |= (1 << 4);
if (Leds[5] == Phase) PORTD |= (1 << 5);
if (Leds[6] == Phase) PORTD |= (1 << 6);
if (Leds[7] == Phase) PORTD |= (1 << 7);
if (Leds[8] == Phase) PORTC |= (1 << 1);
if (Leds[9] == Phase) PORTC |= (1 << 0);
Phase --; 
}


//=================== main ==========
//основаня функция
void main(void){ 
//настройка портов
PORTB=0b00000000; 
DDRB=0b00000000; 
PORTC=0b00000000; //порт С 4 первые по умолчанию 1
DDRC=0b00000011; //порт С 4 первые ноги на вывод
PORTD=0b00000000; //порт D по умолчанию все ноги на 0
DDRD=0b11111111; //порт D все ноги на вывод


TCCR0 = 0;
TIMSK |= 0b00000001;
TCCR0 |= (0<<CS02)|(1<<CS01)|(0<<CS00);

#asm("sei") // Глобальные прерывания включения

// заполним Ледс значениями стартовыми
unsigned char i;
for (i=0; i<10; i++) Leds[i] = i % 5; // массив заполнится значениями 0,1,2,3,4,0,1,2,3,4

// -------------------------------- рабочая часть ------------------------------------------
while (1) { 
   // а теперь будем двигать массив по кругу с какой то задержкой
   unsigned char buf = Leds[9];
   for (i=9; i>0; i--) Leds[i] = Leds[i-1];
   Leds[0] = buf;

   // и задержка
   delay_ms(200);
   }; // ----------------------------- рабочая часть (end) ------------------------------------

} // ================= end main ======

//
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- The End -=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
И да, delay_ms делает задержку тупым пустым циклом. Но у нас есть прерывание, которое тикает приблизительно 4000 раз в секунду. И пока МК в прерывании - задержка не считается.

Тут 2 варианта:
1. Забить на то, что 200 мс будут длиться чуть дольше - каждое прерывание будет сжирать пару-тройку десятков микросекунд... Навскидку - 5-10% добавится.
2. использовать тот факт, что прерывание таймера срабатывает 8МГц/(8*256) = 3906,25 раз в сек..... И завести либо глобальный счетчик, который будет меняться в таймере, а в основном цикле отслеживать изменение счетчика, либо завести какой то флажок срабатывания прерывания, который поднимать в прерывании, а в основной программе сбрасывать его и считать число поднятий флажка уже в основной программе.....
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

:shock: МЯУУУУУУУУУууууу!!!!!!!!!!!!

спасибо добрые люди!
теперь есть где когти поточить! :))
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA

Сообщение GoldenAndy »

Serzh2000, как когти наточите - результатом заточки поделитесь, пожалуйста. (Аж самому интересно, как оно выглядеть будет)
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

ЕС И ЧИЗ !
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

собрал я наконец сосульку RGB правда на макетки
Спойлер#include <mega8.h>

#include <delay.h>


volatile unsigned int f=200, // время кадра

z=1000; // ms для паузы после эффекта

volatile unsigned char Lines, Phase=0;

flash char flasher_0[200] =
{ 4,0,0,0,0,0,0,0,
3,4,0,0,0,0,0,0,
2,3,4,0,0,0,0,0,
1,2,3,4,0,0,0,0,
0,1,2,3,4,0,0,0,
0,0,1,2,3,4,0,0,
0,0,0,1,2,3,4,0,
0,0,0,0,1,2,3,4,
0,0,0,0,0,1,2,3,
0,0,0,0,0,0,1,2,
0,0,0,0,0,0,0,1,
0,0,0,0,0,0,0,0


};


volatile flash char *u;
volatile char a;

// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
unsigned char i;


if (Phase==0) {
PORTD = 0xFF;
PORTC = 0;

Phase = 4;
PORTC = (1 << Lines ); //выводим 1 на линию порта А, соответствующую счетчику линий.
}



for (i=0; i<8; i++) {

a = *(u+0*8+i);
if (a==Phase) PORTD &= ~(1<<i);//выводим на соответствующую линию потра В нолик
}
Phase--;
}


void view_pauza(void) {
delay_ms(z);
}

void view_flasher_0(void) {
int i;
Lines=0 ;



for (i =0; i<13;++i){

u = &(flasher_0[i*8]);
delay_ms(f);
}

view_pauza();
}


void view_flasher_1(void) {
int i;
Lines=1 ;



for (i =0; i<13;++i){

u = &(flasher_0[i*8]);
delay_ms(f);
}

view_pauza();
}

void view_flasher_2(void) {
int i;
Lines=2 ;


for (i =0; i<13;++i){

u = &(flasher_0[i*8]);
delay_ms(f);
}



view_pauza();
}
//=================== main ==========
void main(void)
{

//настройка портов
PORTB=0b00000000;
DDRB=0b00000000;
PORTC=0b00000000; //порт С 4 первые по умолчанию 1
DDRC=0b00000111; //порт С 4 первые ноги на вывод
PORTD=0b00000000; //порт D по умолчанию все ноги на 0
DDRD=0b11111111; //порт D все ноги на вывод



TCCR2 |= (0<<CS02)|(1<<CS01)|(0<<CS00);
TIMSK=0b01000000;
// 0b11000001
// || | |
// || | Timer0
// || Timer1
// |Timer2
//

#asm("sei") // Глобальные прерывания включения
//====================

while (1)
{
// Place your code here
view_flasher_0(); //красный
view_flasher_1(); //синий
view_flasher_2(); //зеленый


}
}
хотя может этот проект в железе и не будет существовать, но за то благодаря Вашей помощи
получился отличный движок
добавь лучи будет снежинка,
убавь один будет звезда
или скажем елочка на окно по четыре веточки и на каждой по восемь светиков

на следующий год обязательно что нибуть замучу.
Всем кто помогал, советовал большое спасибо!
Вложения
sosulk.zip
(96.21 КБ) 185 скачиваний
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA

Сообщение GoldenAndy »

А видосик, снятый на тапок?
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Контактная информация:
Ответить

Вернуться в «AVR»