Вот, посидел пару вечеров и написал управление для RGB. Код прилагается:
Код:
.def temp=R16 - под всякую фигню .def ncur=R18 - номер текущей задачи .def kf=R19 - коэффициент ШИС .def sch=R20 - "счетчик задач" .cseg //Здесь таблица прерываний Reset: ldi temp,255 out DDRD,temp ldi temp,0b00000101 //clk:128 out TCCR2,temp ldi temp,0b11000000 out TIMSK,temp ldi temp,0 out TCNT2,temp ldi kf,1 out OCR2,kf //тут иниц. стека ldi sch,0 ldi ncur,0 rcall Load ldi ncur,1 rcall Load rcall CurTask sei Loop: rjmp Loop TIM2_Comp: rcall Load rcall CurTask reti TIM2_OVF: rcall Load rcall CurTask rcall Load subi sch,3 rcall CurTask reti //Идет перечисление задач Redon: SBI PortD,7 //0 ret Greenon: SBI PortD,6 //1 ret Blueon: SBI PortD,5 //2 ret Redoff: CBI PortD,7 //3 ret Greenoff: CBI PortD,6 //4 ret Blueoff: CBI PortD,5 //5 ret KU: //6 (kf - коэффициент Up - растет) inc kf out OCR2,kf cpi kf,254 breq SbrosU ret SbrosU: rcall CurTask rcall Load subi sch,-3 ret KD: //7 (см. 6) dec kf out OCR2,kf cpi kf,1 breq SbrosD ret SbrosD: rcall CurTask rcall Load subi sch,-3 ret Table: .dw RedOn,Greenon,BlueOn,Redoff,Greenoff,blueoff,KU,KD//0,1,2,3,4,5,6,7,8 - таблица "операций" Tasks: .db 4,1,6,1,3,0,7,3,5,2,6,2,4,1,7,4,3,0,6,0,5,2,7,5 //задачи в порядке выполнения Load: cli lsl ncur ldi ZL,low(Table*2) ldi ZH,high(Table*2) ldi r17,0 ldi r16,0 add ZL,ncur adc ZH,r17 lpm r16,Z+ lpm r17,Z movw ZH:ZL,r17:r16 sei icall ret CurTask: cli ldi ZL,low(Tasks*2) ldi ZH,high(Tasks*2) ldi r17,0 add ZL,sch adc ZH,r17 lpm mov ncur,R0 inc sch sei ret
Извиняюсь за громоздкий код Вопрос такой: 1)Когда счетчик дозодит до конца массива, то что он загружает? Просто процедуры цикличного переливания нет, а программа возвращается к началу. Почему? 2)Вроде ШИМ везде одинаков. Но, например, переход от голубого к синему, а затем к фиолетовому - заметно падение яркости. При переходе, например, от красного к желтому и затем зеленого - такого заметного перехода нет. Это особенность человеческого зрения? 3)Как можно ещё оптимизировать программу? Заранее благодарю за помощь!
1)Когда счетчик дозодит до конца массива, то что он загружает?
То, что идет дальше во флеше, а это коды команд (cli, lsl ncur, ldi ZL,low(Table*2)) и т.д)
gauss писал(а):
[...]все остальные вопросы [...]
Сильно сомневаюсь что структура программы вообще верная... После комента "Здесь таблица прерываний" самой таблицы нету, и куда при прерывании попадет контроллер неизвестно (скорее всего куда-то в район инициализации). Просто обозвать метку в произвольном месте "TIM2_Comp:" вовсе не обозначает что туда попадет обработчик прерывания (или она действительно по 23-му адресу???). Либо ставьте ее по нужному адресу, либо используйте директиву .org (но это тут вряд ли поможет). А, и еще: "тут иниц. стека" - и где она??? Короче исправляйте прогу, а там видно будет...
1)То есть, получается, что фактически адрес массива загружается заного, поэтому все и работает? На самом деле программа работает. Таблицу прерываний и иниц. стека не писал здесь, чтобы уменьшить объем кода. Таблица выглядит так (взята из даташита):
после 2,7,5 пойдет читать дальше флеш, т.е. код команды CLI, код команды LSL, потом коды LDI и констант table*2 и так пока ncur и sch не обнулятся (переполнятся), потом пойдет снова.
Ну ясное дело что на асме короче по объему выйдет, но важен же результат и практичность, а не то что большая часть памяти пустует..... Данный вариант Сишной реализации отжирает 440 байт (43% у тиньки 13-й). Даже остается место для раздолья, я уже не говорю про более старшие камни.
Ну ясное дело что на асме короче по объему выйдет.....
... это смотря как писать, приведенная ТС "простыня" явно не пример для подражания. PS. Ваш код наверное будет занимать поменьше Flash_a если заменить
Код:
if (blue++ & 0x40) blue -= 2; if (blue == 0x40) blue = 0; if (blue == 0x3f) blue = 0x7f; if (green++ & 0x40) green -= 2; if (green == 0x40) green = 0; if (green == 0x3f) green = 0x7f; if (red++ & 0x40) red -= 2; if (red == 0x40) red = 0; if (red == 0x3f) red = 0x7f;
То есть лучше будет после массива Tasks прописать jmp Reset, чтобы начать программу сначала?
Не получится так. LPM считает код команды JMP в регистр (по 1 байту из 2), потом код адреса метки reset (тоже по 1 байту). Выполнять он его с чего будет? Выполняется только тот код, который находится по адресу в PC (счетчик команд). Вот если после LPM сделать сравнение регистра Z например с меткой в следующей после tasks строчке, то можно и jmp на сброс поставить, а можно просто обнулить счетчики которые к Z прибавляются.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 18
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения