Страница 1 из 1
attiny13 4х канальный ШИМ
Добавлено: Вс дек 12, 2010 11:47:09
artmasterpro
Народ, просветите мою темную голову, как на attiny13 сделать 4х канальный ШИМ для управления 4мя светодиодами ? Там же на 1й ноге только можно включить ШИМ генератор, а как задействовать еще 3 ?
Спасибо !
Re: attiny13 4х канальный ШИМ
Добавлено: Вс дек 12, 2010 13:28:25
Liv
У ATtiny13 2 канала аппаратной ШИМ. Если надо больше - только программно, но частота/разрешение такой ШИМ будут низкими. В прерывании таймера делаем инкремент программных счетчиков, если величина больше установленного значения, выход выключаем, иначе - включаем.
Re: attiny13 4х канальный ШИМ
Добавлено: Вс дек 12, 2010 16:22:35
ARV
Liv писал(а):В прерывании таймера делаем инкремент программных счетчиков, если величина больше установленного значения, выход выключаем, иначе - включаем.
например,
вот так: 6 каналов ШИМ на 1 тини13.
Re: attiny13 4х канальный ШИМ
Добавлено: Вс дек 12, 2010 16:39:18
Liv
Самую эффективную реализацию программной ШИМ, которую я видел, приводил на Телесистемах уважаемый MBedder:
Код: Выделить всё
Вот это - собственно 256-зубый ШИМ. Безвозвратно тратится 26 регистров из 32, R2..R25 - уставка ШИМ, R1 (tmp) - рабочий, R2 (pwm) - пила ШИМа. Таймер в режиме CTC - Clear On Compare (реинициализация и сброс флага автоматические):
;Один шаг пилы ШИМ - ISR таймера
t0isr:
in stsav,SREG ;Сохраняем статус. STSAV - общий для всех невложенных прерываний
inc pwm ;Добавляем очередной зуб к пиле ШИМ
breq reinit_PWM ;Загружаем новые значения уставок в начале каждого нового цикла ШИМ
cp r2,pwm ;Перенос=1 при Rx <= PWM ;Те же 2 такта на канал, что и у ПИКа
rol tmp ;Вдвигаем перенос в рабочий регистр ;
cp r3,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r4,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r5,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r6,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r7,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r8,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r9,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
out PORTA,tmp ;Выставляем ноги PWM 1..8
cp r10,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r11,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r12,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r13,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r14,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r15,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r16,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r17,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
out PORTB,tmp ;Выставляем ноги PWM 9..16
cp r18,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r19,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r20,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r21,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r22,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r23,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r24,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
cp r25,pwm ;Перенос=1 при Rx <= PWM
rol tmp ;Вдвигаем перенос в рабочий регистр
PWM_reti:
out PORTC,tmp ;Выставляем ноги PWM 17..24
out SREG,stsav ;Восстанавливаем статус
reti
;Загрузка новых значений уставок и обнуление ШИМ-выходов в начале каждого нового цикла ШИМ
reinit_PWM:
lds r2,PWM_array+0 ;Копируем 24 уставки из RAM в рабочие регистры ШИМ
lds r3,PWM_array+1
lds r4,PWM_array+2
lds r5,PWM_array+3
lds r6,PWM_array+4
lds r7,PWM_array+5
lds r8,PWM_array+6
lds r9,PWM_array+7
lds r10,PWM_array+8
lds r11,PWM_array+9
lds r12,PWM_array+10
lds r13,PWM_array+11
lds r14,PWM_array+12
lds r15,PWM_array+13
lds r16,PWM_array+14
lds r17,PWM_array+15
lds r18,PWM_array+16
lds r19,PWM_array+17
lds r20,PWM_array+18
lds r21,PWM_array+19
lds r22,PWM_array+20
lds r23,PWM_array+21
lds r24,PWM_array+22
lds r25,PWM_array+23
clr tmp
out PORTA,tmp ;Обнуляем ноги PWM 1-8
out PORTB,tmp ;Обнуляем ноги PWM 9-16
rjmp PWM_reti ;Обнуляем ноги PWM 17-24, используя хвост общей ISR, и выходим из ISR
;Процедура приема-разбора-раздачи уставок - ISR приема UART
;Формат команды - 2 байта (байт номера канала + байт уставки этого канала)
;Байт номера канала опознается по одновременно принятому UARTом 9-му биту (parity) = 1
;Буфер уставок (PWM_array) для удобства располагаем в самом начале RAM (с адреса 0x0100)
;или выравниваем по модулю 256
UARTrxISR:
push tmp ;Сохраняем регистр, не сохраняем статус - он не затронется
lds tmp,UCSRB0 ;Смотрим, что пришло - номер канала ШИМ или данные
sbrs UCSRB,RXB80 ;
rjmp set_data
;set_addr:
lds tmp,UDR0 ;Читаем пришедший номер канала ШИМ из UART, сбрасываем флаг приема
sts PWMchan,tmp ;Сохраняем его в ОЗУ
pop tmp ;Восстанавливаем регистр
reti ;21 такт (1.05 мкс) вместе со входом при приеме номера канала
set_data:
push xl ;Сохраняем регистр
push xh ;Сохраняем регистр
lds tmp,UDR0 ;Читаем пришедшую уставку из UART, сбрасываем флаг приема
lds xl,PWMchan ;Загружаем LSB указателя массива ШИМ
cpi xl,24 ;Проверка границ массива
brsh PWM_err ;Игнорируем команду, если номер канала больше 23
ldi xh,high(PWM_arrray) ;Загружаем MSB указателя массива ШИМ
st x,tmp ;Записываем уставку в буфер нужного канала ШИМ
PWM_err:
pop xh ;Восстанавливаем регистр
pop xl ;Восстанавливаем регистр
pop tmp ;Восстанавливаем регистр
reti ;34 такта (1.7 мкс) вместе со входом при приеме уставки канала
;Итого 21+34=55 тактов, или 2.75 мкс на канал, или 2.75*24=66 мкс на все 24 канала
1. Накладные расходы по регистрам - 26 байт: 24 рабочих ШИМ, tmp и pwm. По RAM - 25 байт (буфер уставок ШИМ PWM_array[24] для двойной буферизации - обеспечения Phase and Frequency Correct PWM, и 1 байт указателя канала - PWMchan)
2. Накладные расходы по времени (вход-выход ISR, инкремент пилы, 4 вывода в порт, сохранение-восстановление статуса) - 18 тактов, или 18/24 = +0.75 такта к каждому каналу, что дает 18+(24*2)= 66 тактов на ISR или 2.75 такта на канал. При 100% загрузке 20-МИПСового АВРа (ATMega164/324/644) ТОЛЬКО этой задачей достижимая частота каждого из 24 каналов 256-ступенчатого ШИМ составит 20 МГЦ/66*256=1183 ГЦ.
3. Если для обновления уставок использовать UART, то для передачи всех 24-х двухбайтовых команд за 1 цикл ШИМ UART должен работать со скоростью не менее 576 КБод (при Fcy=20 MHZ можно с запасом выбрать 625 КБод). Все 24 уставки будут приняты, декодированы и розданы за 24*55=1320 тактов, или 66 мкс. При 100% загрузке 20-МИПСового АВРа (ATMega164/324/644) обеими задачами достижимая частота каждого из 24 каналов 256-ступенчатого ШИМ составит 20 МГЦ/((66*256)+1320)=1098 ГЦ.
Re: attiny13 4х канальный ШИМ
Добавлено: Вс дек 12, 2010 16:47:19
artmasterpro
т.е. только программно ? Я както делал програмный ШИМ на Си вот его код:
Код: Выделить всё
for(i=0; i<=60; i++)
{
PORTB.0=1;
PORTB.4=0;
j=60-i;
while (1<=j)
{ j=j-1;;
delay_us(300);
}
PORTB.0=0;
PORTB.4=1;
j=0;
while (j<=i)
{ j=j+1;
delay_us(300);
}
}
НО бок в том, что нормально работает только тогда когда, светодиод загорается быстро. Когда увеличиваешь задержки яркость меняется очень медленно, а тут получается заметное моргание !
Re: attiny13 4х канальный ШИМ
Добавлено: Вс дек 12, 2010 21:09:04
Liv
Если Вам нужно 4 быстрых ШИМ, лучше взять ATmega48. Там их 6.
Re: attiny13 4х канальный ШИМ
Добавлено: Пн дек 13, 2010 11:22:09
artmasterpro
не мне нужно сделать чтобы светодиоды очень медленно зажигались и при этом не моргали, а плавно наростал свет.
Re: attiny13 4х канальный ШИМ
Добавлено: Чт янв 13, 2011 09:07:08
zvyagaaa
Господа, а кто-нибудь может перевести код, который привел уважаемый
Liv на Си? А то в асме совсем плохо соображаю

Re: attiny13 4х канальный ШИМ
Добавлено: Чт янв 13, 2011 09:59:14
ploop
не мне нужно сделать чтобы светодиоды очень медленно зажигались и при этом не моргали, а плавно наростал свет.
А какое у вас разрешение ШИМа получается?
Господа, а кто-нибудь может перевести код, который привел уважаемый Liv на Си? А то в асме совсем плохо соображаю
Что-то мне кажется, что на C такой фокус не прокатит...
Re: attiny13 4х канальный ШИМ
Добавлено: Чт янв 13, 2011 10:00:14
ARV
zvyagaaa писал(а):Господа, а кто-нибудь может перевести код, который привел уважаемый
Liv на Си? А то в асме совсем плохо соображаю

а на Си я давал ссылку.
Re: attiny13 4х канальный ШИМ
Добавлено: Чт янв 13, 2011 11:52:35
zvyagaaa
ARV
Извините,

не заметил ссылку в статье сразу, сейчас сижу вникаю, код-то не простой
Пока что накапливаю вопросы, но сразу задам пока один - вот процедура ШИМа по прерыванию
Код: Выделить всё
/** Обработчик прерывания таймера по переполнению.
* Реализует программный многоканальный ШИМ.
*/
ISR(TIM0_OVF_vect){
static uint8_t CNT = 0; // счетчик ШИМ
uint8_t output = 0, // состояние отдельных каналов
mask = 1; // маска канала
// перебираются все "свечи"
for(uint8_t i = 0; i < MAXCANDLES; i++){
// и для каждой свечи проверяется ее яркость:
// если она больше текущего значения счетчика,
if(candles[i].bright > CNT)
output |= mask; // то в ее канал записывается 1
// после чего подготавливается маска следующего канала
mask <<= 1;
}
// сразу все каналы выводятся в порт
PORTB = output;
// и увеличивается счетчик
CNT++;
}
в принципе все понятно, кроме того, что такое
mask.
И еще не совсем мне понятно наличие переменной
CNT = 0; // счетчик ШИМ.
Если она в начале функции определена, то ее видимость распространяется только на эту функцию, я как понимаю. Т.е. в начале прерывания мы ее определили, она равна 0, во время перебора всех свечей и сравнение будет происходить с нулем, т.е. if(candles
.bright > 0) В конце функции мы ее инкрементировали зачем-то.
И еще, если нужен просто диммер, то от candles.period можно отказаться, правильно? И еще совсем нубский вопрос, а с каким периодом срабатывает этот таймер?
ПС просьба не пинать если что не так, я пока что только-только начал Си изучать, еще недели не прошло.
Re: attiny13 4х канальный ШИМ
Добавлено: Чт янв 13, 2011 12:28:19
aleksey_gregul
zvyagaaa писал(а):ARV
Если она в начале функции определена, то ее видимость распространяется только на эту функцию, я как понимаю. Т.е. в начале прерывания мы ее определили, она равна 0, во время перебора всех свечей и сравнение будет происходить с нулем, т.е. if(candles.bright > 0) В конце функции мы ее инкрементировали зачем-то.
Вы частично правильно понимаете. Только не заметили STATIC. Нулем она будет только при первом ее использовании (инициализации).
При выходе из функции, она не изменится (так и останется инкрементированной). При повторном входе в функцию, она остается такой же, как при выходе из нее.
Re: attiny13 4х канальный ШИМ
Добавлено: Чт янв 13, 2011 13:41:28
zvyagaaa
а обнуляется значит когда становится счетчик шим = 255+1? Правильно я понимаю?
Дааа, совсем не прост код, как кажется.
Re: attiny13 4х канальный ШИМ
Добавлено: Чт янв 13, 2011 13:53:39
ARV
mask - это вспомогательная переменная, отвечающая за бит в порту. чтобы не было джиттера каналов, т.е. они все одновременно меняли свое состояние, я ввожу вспомогательный байт output в котором устанавливаю биты, если соответствующий канал ШИМ включен, а потом вывожу этот байт в порт - и состояние всех каналов меняется одновременно.
в принципе, я надеялся, что комментарии достаточно полно раскрывают суть происходящего
Re: attiny13 4х канальный ШИМ
Добавлено: Чт янв 13, 2011 13:58:27
zvyagaaa
ARV спасибо за комментарий.
а что по остальным вопросам? особенно меня интересует вопрос частоты прерывания.
Re: attiny13 4х канальный ШИМ
Добавлено: Чт янв 13, 2011 14:22:32
radio-kot
ARV писал(а):6 каналов ШИМ на attiny13.
Классно и стоит недорого - attiny13 40 рублей и светодиод 3 рубля - отличная конструкция.
Re: attiny13 4х канальный ШИМ
Добавлено: Чт янв 13, 2011 14:41:50
ARV
я не знаю точно, какая там частота ШИМ получается... думаю, что где-то около 150 Гц для 6 каналов - считать лень

главное, надо настраивать таймер так, чтобы обработчик его прерывания успевал полностью закончить свою работу до наступления слдеующего прерывания. в принципе, вы можете настроить таймер на срабатывание через 1 тик (режим СТС), при этом будет получена максимально возможная для данной конфигурации частота ШИМ, но вот кроме ШИМа больше почти ничего сделать будет нельзя
моя программа занимается тем, что меняет скважность всех каналов хаотически через хаотические интервалы, поэтому если вам нуже только диммер, вам нужно иметь только нужное число каналов ШИМ и больше ничего, т.е. массив становится простейшим.
Re: attiny13 4х канальный ШИМ
Добавлено: Пт янв 14, 2011 11:31:06
aleksey_gregul
Можете посмотреть, как реализуется программный шим для шаговиков. Здесь
http://electronix.ru/forum/index.php?sh ... t&p=856063
Этот код очень легко настраивается на практически любой авр. Если захотите, можете выдрать себе шим оттуда, выбросив два лишних канала. Это мой живой код для электронного щитка приборов автомобиля. Вытянут только шим но предварительно проверен на работоспособность на железе.
PS
Забыл добавить, немножко придется подшаманить с принципом формирования выходного сигнала, поскольку здесь используются три состояния выхода.
В Вашем случае нужно только два(0 и 1). Но, думаю, при желании разберетесь.