DogPawlowa 0 2 апреля, 2009 Опубликовано 2 апреля, 2009 · Жалоба N 16 каналов F Частота 400 Гц n Количество градаций 1000 f Частота микроконтроллера 72 MHz p Ресурсы времени на обслуживание ШИМ 50% T Период прерывания обслуживания ШИМ = (1/(F*n)) = 1/(400*1000) = 2,5 мкс Время прерывания 2,5 *50/100 = 1,25 мкс. Допустимое количество команд 72*1,25= 90 Делаем тупо 16 раз: if (count==pwm[NUM]) PORT->BSRR=PIN На каждый канал тратится шесть команд, итого 96 команд плюс инкремент-пролог-эпилог. Много. Плюс джиттер - отдельный вопрос. Переделываем на предварительное формирование слова для записи в порт, и потом три записи этих байтов 4 команды на канал итого 64 плюс чистка и запись в три порта 11 команд всего 75. Чуть лучше. Какие еще варианты могут быть? (кроме снижения требований, конечно ) Сдвиговый регистр на SPI с записью по DMA? Что-то еще? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
etoja 0 2 апреля, 2009 Опубликовано 2 апреля, 2009 · Жалоба В LPC2138 формирование ШИМ происходит аппаратно, но 16 каналов там не будет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 2 апреля, 2009 Опубликовано 2 апреля, 2009 · Жалоба Попробуй нечто в таком духе: typedef struct { int count; unsigned mask; } pwmchan_t; pwmchan_t pwm_array[2][17]; int current_array; int count; unsigned mask; // прерывание // Вывести (приготовленную на прошлом заходе) маску в порт // Это минимизация джиттера PORT = mask; if( ++count == PERIOD) { count = 0; mask = 0; pwmptr = pwm_array[current_array]; } else { while( count == pwmptr->count ) { // тут было правильно, но ГЛУПО mask |= pwmptr->mask; // видать, послобеденная полудрёма не дала ++pwmptr; // нормально добавить обработку нескольких одинаковых } } В массиве содержатся отсортированные по возрастанию count записи, при изменении скважности какого-от канала массив пересортировывается во второй копии и делается замена индекса current_array с 0 на 1 и назад При желании можно замену current_array привязывать к окончанию периода - менять current_array_next, а в обработчике прерывания по достижению PERIOD делать current_array = current_array_next Главное, чтобы обработчик успевал при самом худшем раскладе - когда все каналы станут на одну скважность - уложиться в период (а не в половину). Ну а загрузка процессора будет низкая, гораздо ниже половины (основная масса прерываний будет отрабатывать быстро). Да, совсем забыл. записей в массиве 17 для того, чтобы в последней записи держать такое значение .count, что оно не будет достигнуто счётчиком. Это чтобы if( count == pwmptr->count ) и аналогичное в while работало и как ограничитель инкремента указателя Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 2 апреля, 2009 Опубликовано 2 апреля, 2009 · Жалоба Попробуй нечто в таком духе: Спасибо, идею понял. Общее высвобождение ресурсов на порядок, но с худшим случаем нужно разбираться в симуляторе детально, что же там получается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 2 апреля, 2009 Опубликовано 2 апреля, 2009 · Жалоба Что-то еще? Взять какую-нибудь тиню2313, в ней реализовать ШИМы на asm'е. (50 тактов на период, возможно хватит, на 8 каналов так точно хватит). Передавать ей параметры ШИМа с частотой 400Гц, и пусть генерит с 99% ресурсом под ШИМ. расширять будет легко, вдруг понадобится не 16, а 64-128 каналов, подключите еще n тинь и готово. А STM пусть отдыхает :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KRS 1 2 апреля, 2009 Опубликовано 2 апреля, 2009 · Жалоба у LPC29xx есть четрые 6 канальных PWM Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 2 апреля, 2009 Опубликовано 2 апреля, 2009 · Жалоба А я не понял, заранее заготовленную колбасу размером 2000 байт (1000 полуслов) уже некуда положить? Зато времени свободного будет валом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 2 апреля, 2009 Опубликовано 2 апреля, 2009 · Жалоба Тьху, ну да. А можно и не всю колбасу, а только несколько нужных кусочков - т.е., как у меня, только после сортировки слить .mask с одинаковым .count и туда же добавить предыдущее .mask, укоротив рабочую часть массива и записать ограничитель в следующем элементе в .count. Максимальная длина будет такая, что влезет в данный массив, а (в исправленном) while(count == pwmptr->count) заменить назад на if без while - тело обработчика будет выполняться ощутимо дольше, чем для 2000-байтовой колбасы, но "худшего случая" просто не будет, тело будет всё равно достаточно быстрым. Ну и будет не mask |= pwmptr->mask а mask = pwmptr->mask (см. про "добавить предыдущее"), ещё может малость сэкономит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться