Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Максимальное разрешение многоканального программного ШИМ на STM32
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Dog Pawlowa
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
В LPC2138 формирование ШИМ происходит аппаратно, но 16 каналов там не будет.
ReAl
Попробуй нечто в таком духе:
Код
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 работало и как ограничитель инкремента указателя
Dog Pawlowa
Цитата(ReAl @ Apr 2 2009, 14:06) *
Попробуй нечто в таком духе:

Спасибо, идею понял.
Общее высвобождение ресурсов на порядок, но с худшим случаем нужно разбираться в симуляторе детально, что же там получается.
defunct
Цитата
Что-то еще?

Взять какую-нибудь тиню2313, в ней реализовать ШИМы на asm'е. (50 тактов на период, возможно хватит, на 8 каналов так точно хватит).
Передавать ей параметры ШИМа с частотой 400Гц, и пусть генерит с 99% ресурсом под ШИМ.
расширять будет легко, вдруг понадобится не 16, а 64-128 каналов, подключите еще n тинь и готово.
А STM пусть отдыхает smile.gif
KRS
у LPC29xx есть четрые 6 канальных PWM
Rst7
А я не понял, заранее заготовленную колбасу размером 2000 байт (1000 полуслов) уже некуда положить? Зато времени свободного будет валом.
ReAl
Тьху, ну да. А можно и не всю колбасу, а только несколько нужных кусочков - т.е., как у меня, только после сортировки слить .mask с одинаковым [i].count[/i] и туда же добавить предыдущее .mask, укоротив рабочую часть массива и записать ограничитель в следующем элементе в .count. Максимальная длина будет такая, что влезет в данный массив, а (в исправленном) while(count == pwmptr->count) заменить назад на if без while - тело обработчика будет выполняться ощутимо дольше, чем для 2000-байтовой колбасы, но "худшего случая" просто не будет, тело будет всё равно достаточно быстрым.
Ну и будет не mask |= pwmptr->mask а mask = pwmptr->mask (см. про "добавить предыдущее"), ещё может малость сэкономит.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.