Народ, просветите мою темную голову, как на attiny13 сделать 4х канальный ШИМ для управления 4мя светодиодами ? Там же на 1й ноге только можно включить ШИМ генератор, а как задействовать еще 3 ?
Спасибо !
_________________ Главная заповедь электронщика:- Не крути две ручки сразу
У ATtiny13 2 канала аппаратной ШИМ. Если надо больше - только программно, но частота/разрешение такой ШИМ будут низкими. В прерывании таймера делаем инкремент программных счетчиков, если величина больше установленного значения, выход выключаем, иначе - включаем.
Самую эффективную реализацию программной ШИМ, которую я видел, приводил на Телесистемах уважаемый 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
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 мкс) вместе со входом при приеме номера канала
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 ГЦ.
Открыта удобная площадка с выгодными ценами, поставляющая весь ассортимент продукции, производимой компанией MEAN WELL – от завоевавших популярность и известных на рынке изделий до новинок. MEAN WELL.Market предоставляет гарантийную и сервисную поддержку, удобный подбор продукции, оперативную доставку по России.
На сайте интернет-магазина посетители смогут найти обзоры, интересные статьи о применении, максимальный объем технических сведений.
т.е. только программно ? Я както делал програмный ШИМ на Си вот его код:
Код:
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); }
}
НО бок в том, что нормально работает только тогда когда, светодиод загорается быстро. Когда увеличиваешь задержки яркость меняется очень медленно, а тут получается заметное моргание !
_________________ Главная заповедь электронщика:- Не крути две ручки сразу
Продукция MOSO предназначена в основном для индустриальных приложений, использует инновационные решения на основе более 200 собственных патентов для силовой электроники и соответствует международным стандартам. LED-драйверы MOSO применяются в системах наружного освещения разных отраслей, включая промышленность, сельское хозяйство, транспорт и железную дорогу. В ряде серий реализована возможность дистанционного контроля и программирования работы по заданному сценарию. Разберем решения MOSO
подробнее>>
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[i].bright > 0) В конце функции мы ее инкрементировали зачем-то. И еще, если нужен просто диммер, то от candles[i].period можно отказаться, правильно? И еще совсем нубский вопрос, а с каким периодом срабатывает этот таймер? ПС просьба не пинать если что не так, я пока что только-только начал Си изучать, еще недели не прошло.
ARV Если она в начале функции определена, то ее видимость распространяется только на эту функцию, я как понимаю. Т.е. в начале прерывания мы ее определили, она равна 0, во время перебора всех свечей и сравнение будет происходить с нулем, т.е. if(candles[i].bright > 0) В конце функции мы ее инкрементировали зачем-то.
Вы частично правильно понимаете. Только не заметили STATIC. Нулем она будет только при первом ее использовании (инициализации). При выходе из функции, она не изменится (так и останется инкрементированной). При повторном входе в функцию, она остается такой же, как при выходе из нее.
mask - это вспомогательная переменная, отвечающая за бит в порту. чтобы не было джиттера каналов, т.е. они все одновременно меняли свое состояние, я ввожу вспомогательный байт output в котором устанавливаю биты, если соответствующий канал ШИМ включен, а потом вывожу этот байт в порт - и состояние всех каналов меняется одновременно.
в принципе, я надеялся, что комментарии достаточно полно раскрывают суть происходящего
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
я не знаю точно, какая там частота ШИМ получается... думаю, что где-то около 150 Гц для 6 каналов - считать лень главное, надо настраивать таймер так, чтобы обработчик его прерывания успевал полностью закончить свою работу до наступления слдеующего прерывания. в принципе, вы можете настроить таймер на срабатывание через 1 тик (режим СТС), при этом будет получена максимально возможная для данной конфигурации частота ШИМ, но вот кроме ШИМа больше почти ничего сделать будет нельзя
моя программа занимается тем, что меняет скважность всех каналов хаотически через хаотические интервалы, поэтому если вам нуже только диммер, вам нужно иметь только нужное число каналов ШИМ и больше ничего, т.е. массив становится простейшим.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Можете посмотреть, как реализуется программный шим для шаговиков. Здесь http://electronix.ru/forum/index.php?sh ... t&p=856063 Этот код очень легко настраивается на практически любой авр. Если захотите, можете выдрать себе шим оттуда, выбросив два лишних канала. Это мой живой код для электронного щитка приборов автомобиля. Вытянут только шим но предварительно проверен на работоспособность на железе.
PS Забыл добавить, немножко придется подшаманить с принципом формирования выходного сигнала, поскольку здесь используются три состояния выхода. В Вашем случае нужно только два(0 и 1). Но, думаю, при желании разберетесь.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения