Например TDA7294

Форум РадиоКот • Просмотр темы - Управление RGB светодиодом
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Ср дек 17, 2025 07:23:47

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 12 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: Управление RGB светодиодом
СообщениеДобавлено: Вт апр 30, 2013 18:31:19 
Держит паяльник хвостом
Аватар пользователя

Зарегистрирован: Сб янв 16, 2010 15:34:57
Сообщений: 920
Откуда: Sevsk/Moscow
Рейтинг сообщения: 0
Вот, посидел пару вечеров и написал управление для 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)Как можно ещё оптимизировать программу?
Заранее благодарю за помощь!

_________________
:idea:


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Вт апр 30, 2013 19:26:59 
Друг Кота
Аватар пользователя

Карма: 32
Рейтинг сообщений: 238
Зарегистрирован: Пт янв 29, 2010 10:27:40
Сообщений: 3868
Откуда: Москва
Рейтинг сообщения: 0
gauss писал(а):
1)Когда счетчик дозодит до конца массива, то что он загружает?

То, что идет дальше во флеше, а это коды команд (cli, lsl ncur, ldi ZL,low(Table*2)) и т.д)
gauss писал(а):
[...]все остальные вопросы [...]

Сильно сомневаюсь что структура программы вообще верная...
После комента "Здесь таблица прерываний" самой таблицы нету, и куда при прерывании попадет контроллер неизвестно (скорее всего куда-то в район инициализации). Просто обозвать метку в произвольном месте "TIM2_Comp:" вовсе не обозначает что туда попадет обработчик прерывания (или она действительно по 23-му адресу???). Либо ставьте ее по нужному адресу, либо используйте директиву .org (но это тут вряд ли поможет).
А, и еще: "тут иниц. стека" - и где она??? :facepalm:
Короче исправляйте прогу, а там видно будет...


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Вт апр 30, 2013 19:34:46 
Держит паяльник хвостом
Аватар пользователя

Зарегистрирован: Сб янв 16, 2010 15:34:57
Сообщений: 920
Откуда: Sevsk/Moscow
Рейтинг сообщения: 0
1)То есть, получается, что фактически адрес массива загружается заного, поэтому все и работает?
На самом деле программа работает. Таблицу прерываний и иниц. стека не писал здесь, чтобы уменьшить объем кода.
Таблица выглядит так (взята из даташита):
Код:
.cseg
rjmp Reset
rjmp EXT_INT0 ; IRQ0 Handler
rjmp EXT_INT1 ; IRQ1 Handler
rjmp TIM2_COMP ; Timer2 Compare Handler
rjmp TIM2_OVF ; Timer2 Overflow Handler
rjmp TIM1_CAPT ; Timer1 Capture Handler
rjmp TIM1_COMPA ; Timer1 CompareA Handler
rjmp TIM1_COMPB ; Timer1 CompareB Handler
rjmp TIM1_OVF ; Timer1 Overflow Handler
rjmp TIM0_OVF ; Timer0 Overflow Handler
rjmp SPI_STC ; SPI Transfer Complete Handler
rjmp USART_RXC ; USART RX Complete Handler
rjmp USART_UDRE ; UDR Empty Handler
rjmp USART_TXC ; USART TX Complete Handler
rjmp ADCC ; ADC Conversion Complete Handler
rjmp EE_RDY ; EEPROM Ready Handler
rjmp ANA_COMP ; Analog Comparator Handler
rjmp TWSI ; Two-wire Serial Interface
rjmp SPM_RDY
EXT_INT0:
EXT_INT1:
;TIM2_COMP:
;TIM2_OVF:
TIM1_CAPT:
TIM1_CompA:
TIM1_CompB:
TIM1_OVF:
TIM0_OVF:
SPI_STC:
USART_RXC:
USART_UDRE:
USART_TXC:
ADCC:
EE_RDY:
ANA_COMP:
TWSI:
SPM_RDY:      
reti   
Reset:
дальше остальная программа

Так что все прерывания прописаны верно :)
Иниц. стека просто не прописана -в коде программы она, естественно, есть:
Код:
ldi temp,high(Ramend)
out SPH,temp
ldi temp,low(RamEnd)
out SPL,temp

_________________
:idea:


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Вт апр 30, 2013 19:45:05 
Друг Кота
Аватар пользователя

Карма: 32
Рейтинг сообщений: 238
Зарегистрирован: Пт янв 29, 2010 10:27:40
Сообщений: 3868
Откуда: Москва
Рейтинг сообщения: 0
Вот блин, код не приводят целиком и не говорят что он сокращен, а мы тут гадаем :facepalm:
Нет, по новой ничего не загружается. После того, как
Код:
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+

прочитает KD, следующим считанным числом будет 4, потом 1, т.е. то, что дальше идет, а кусок
Код:
ldi ZL,low(Tasks*2)
ldi ZH,high(Tasks*2)
ldi r17,0
add ZL,sch
adc ZH,r17
lpm

после 2,7,5 пойдет читать дальше флеш, т.е. код команды CLI, код команды LSL, потом коды LDI и констант table*2 и так пока ncur и sch не обнулятся (переполнятся), потом пойдет снова.


Вернуться наверх
 
Эиком - электронные компоненты и радиодетали
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Вт апр 30, 2013 19:59:58 
Держит паяльник хвостом
Аватар пользователя

Зарегистрирован: Сб янв 16, 2010 15:34:57
Сообщений: 920
Откуда: Sevsk/Moscow
Рейтинг сообщения: 0
gauss писал(а):
Таблицу прерываний и иниц. стека не писал здесь, чтобы уменьшить объем кода.

Написал сразу :)
То есть лучше будет после массива Tasks прописать jmp Reset, чтобы начать программу сначала?

_________________
:idea:


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Вт апр 30, 2013 20:02:30 
Сверлит текстолит когтями
Аватар пользователя

Карма: 4
Рейтинг сообщений: 30
Зарегистрирован: Ср янв 05, 2011 16:25:15
Сообщений: 1163
Рейтинг сообщения: 0
Engineer_Keen писал(а):
Вот блин, код не приводят целиком и не говорят что он сокращен, а мы тут гадаем
... ну да - сначала нужно угадать, что хотел сделать ТС ... а это как правило сложнее всего :))
gauss - комментарии никто не отменял


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Вт апр 30, 2013 21:51:59 
Держит паяльник хвостом
Аватар пользователя

Зарегистрирован: Сб янв 16, 2010 15:34:57
Сообщений: 920
Откуда: Sevsk/Moscow
Рейтинг сообщения: 0
Хотел сделать плавное управление RGB светодиодом. Вот код с комментами:
Код:
//называется так,потому что первая программа,
//в которой я использовал индексные переходы
//они сделаны для управления RGB сыетодиодом,
//также для этого реализован ШИМ :)
//ТО, используется многозадачность и служба таймеров => прообраз ОС
//вторая версия кода
.def temp=R16
.def ncur=R18
.def kf=R19
.def sch=R20
.cseg
//ИНИЦИАЛИЗАЦИЯ ТАБЛИЦЫ ПРЕРЫВАНИЙ - НАЧАЛО
rjmp Reset
rjmp EXT_INT0 ; IRQ0 Handler
rjmp EXT_INT1 ; IRQ1 Handler
rjmp TIM2_COMP ; Timer2 Compare Handler
rjmp TIM2_OVF ; Timer2 Overflow Handler
rjmp TIM1_CAPT ; Timer1 Capture Handler
rjmp TIM1_COMPA ; Timer1 CompareA Handler
rjmp TIM1_COMPB ; Timer1 CompareB Handler
rjmp TIM1_OVF ; Timer1 Overflow Handler
rjmp TIM0_OVF ; Timer0 Overflow Handler
rjmp SPI_STC ; SPI Transfer Complete Handler
rjmp USART_RXC ; USART RX Complete Handler
rjmp USART_UDRE ; UDR Empty Handler
rjmp USART_TXC ; USART TX Complete Handler
rjmp ADCC ; ADC Conversion Complete Handler
rjmp EE_RDY ; EEPROM Ready Handler
rjmp ANA_COMP ; Analog Comparator Handler
rjmp TWSI ; Two-wire Serial Interface
rjmp SPM_RDY
EXT_INT0:
EXT_INT1:
;TIM2_COMP:
;TIM2_OVF:
TIM1_CAPT:
TIM1_CompA:
TIM1_CompB:
TIM1_OVF:
TIM0_OVF:
SPI_STC:
USART_RXC:
USART_UDRE:
USART_TXC:
ADCC:
EE_RDY:
ANA_COMP:
TWSI:
SPM_RDY:      
reti   //ИНИЦИАЛИЗАЦИЯ ТАБЛИЦЫ ПРЕРЫВАНИЙ - КОНЕЦ
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 temp,high(Ramend)
out SPH,temp
ldi temp,low(RamEnd)
out SPL,temp
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
//Задачи 0-5 отвечают за вкл/выкл светодиодов.
ret
KU:       //6.Задача отвечает за повышение к-та ШИМ. При повышении до максимума загружает следующие задачи (другое переключение цвета)
inc kf
out OCR2,kf
cpi kf,254
breq SbrosU
ret
SbrosU:
rcall CurTask
rcall Load
subi sch,-3   //сделано для загрузки сделующей задачи
ret
KD:       //7.Задача отвечает за снижение к-та ШИМ. При понижении до минимума загружает следующие задачи (другое переключение цвета)
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 - таблица "операций". Это таблица существующих задач.
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   //Массив, в котором находятся номера задач в порядке выполнения.
jmp Reset
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   //переход по адресу, указанного в регистровой паре Z
ret
CurTask:   //Функция загружает в память номер задачи, и последующим инкрементом адреса (переменная sch)
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

_________________
:idea:


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Вт апр 30, 2013 23:36:10 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 106
Зарегистрирован: Ср фев 22, 2012 01:25:21
Сообщений: 882
Рейтинг сообщения: 0
А на Си не интересно?
Намного короче получается.....

Код:
#define F_CPU 9600000
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t blue=0,red=42,green=42+64,counter,dir;
int main (void)
{
    DDRB = 0xff;//линии порта на вывод
    TCCR0A = 0x02;//режим таймера - CTC
    TCCR0B = 0x02;//предделителя таймера - деление на 8
    TIMSK0 = 0x04;//счетчика по совпадению с OCR0A
    OCR0A = 120;//регистр сравнения = 120 (прерывание 10khz)
    sei ();                                        
    while
(1){
        _delay_ms (10);//скорость изминения
        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;
    }
}
ISR (TIM0_COMPA_vect)
{
    
    if 
(++counter == 64)    counter = 0;
    if ((blue & 0x3f)>=counter)    PORTB |= (1<<0);
    else PORTB &= ~(1<<0);
    if ((red & 0x3f)>=counter)    PORTB |= (1<<1);
    else PORTB &= ~(1<<1);
    if ((green & 0x3f)>=counter) PORTB |= (1<<2);
    else PORTB &= ~(1<<2);
}
 


Изображение


Вложения:
sh1.gif [39.87 KiB]
Скачиваний: 983
Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Ср май 01, 2013 00:03:05 
Держит паяльник хвостом
Аватар пользователя

Зарегистрирован: Сб янв 16, 2010 15:34:57
Сообщений: 920
Откуда: Sevsk/Moscow
Рейтинг сообщения: 0
Сомневаюсь, что по объему и скорости меньше

_________________
:idea:


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Ср май 01, 2013 00:36:24 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 106
Зарегистрирован: Ср фев 22, 2012 01:25:21
Сообщений: 882
Рейтинг сообщения: 0
Ну ясное дело что на асме короче по объему выйдет, но важен же результат и практичность, а не то что большая часть памяти пустует.....
Данный вариант Сишной реализации отжирает 440 байт (43% у тиньки 13-й).
Даже остается место для раздолья, я уже не говорю про более старшие камни.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Ср май 01, 2013 09:37:15 
Сверлит текстолит когтями
Аватар пользователя

Карма: 4
Рейтинг сообщений: 30
Зарегистрирован: Ср янв 05, 2011 16:25:15
Сообщений: 1163
Рейтинг сообщения: 0
shads писал(а):
Ну ясное дело что на асме короче по объему выйдет.....
... это смотря как писать, приведенная ТС "простыня" явно не пример для подражания.
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;
на
Код:
           
.....
void NextPWM(uint8_t *color){
        uint8_t pwm; pwm=*color;
        if (pwm++ & 0x40)     pwm -= 2;
        if (pwm == 0x40)     pwm = 0;
        if (pwm == 0x3f)     pwm = 0x7f;
        *color=pwm;
}
.....
            NextPWM(&blue);   
            NextPWM(&green);
            NextPWM(&red);


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Управление RGB светодиодом
СообщениеДобавлено: Вс май 05, 2013 21:26:23 
Друг Кота
Аватар пользователя

Карма: 32
Рейтинг сообщений: 238
Зарегистрирован: Пт янв 29, 2010 10:27:40
Сообщений: 3868
Откуда: Москва
Рейтинг сообщения: 0
gauss писал(а):
То есть лучше будет после массива Tasks прописать jmp Reset, чтобы начать программу сначала?

Не получится так. LPM считает код команды JMP в регистр (по 1 байту из 2), потом код адреса метки reset (тоже по 1 байту). Выполнять он его с чего будет? Выполняется только тот код, который находится по адресу в PC (счетчик команд). Вот если после LPM сделать сравнение регистра Z например с меткой в следующей после tasks строчке, то можно и jmp на сброс поставить, а можно просто обнулить счетчики которые к Z прибавляются.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 12 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 18


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y