Программная реализация нескольких каналов ШИМ на микроконтроллере. Теория

Для того, чтобы понять, каким образом можно реализовать несколько каналов ШИМ на одном контроллере, давайте сначала вспомним, — что вообще такое ШИМ и с чем это едят.

ШИМ расшифровывается как широтно-импульсная модуляция. Это такой режим работы, когда коэффициент заполнения импульсов может регулироваться микросхемой управления (нашим контроллером) по каким-либо правилам (другими словами говорят, что коэффициент заполнения промодулирован чем-то или в зависимости от чего-то). То есть, переключения из высокого уровня сигнала в низкий и наоборот выполняются в строго определённые какими-то правилами моменты времени.

так выглядит ШИМ-сигнал

Таким образом, для одного канала ШИМ нам нужно знать правила, которыми определяется коэффициент заполнения (с этим проблем нет, мы их сами устанавливаем), и, кроме того, отсчитывать два момента времени от начала импульса: во-первых, сколько сигнал находится в состоянии высокого уровня и во-вторых, общее время импульса. Отлично, значит всё, что нам нужно для реализации одного ШИМ — это два счётчика. Алгоритм получится такой: запускаем оба счётчика, переключаем выход в "1". По прерыванию от первого счётчика (время высокого уровня) переключаем выход в "0", выключаем счётчик и ждём прерывание от второго счётчика. По прерыванию от второго счётчика (общее время импульса) — повторяем всё с начала.

Соответственно, для трёх каналов ШИМ нам нужно 3*2=6 счётчиков. Но, допустим у PIC12F629, есть только 2 счётчика, что же делать? Во-первых, сделаем одинаковым общее время импульса для всех каналов ШИМ (пусть все три канала работают с одной частотой), это уже минус два счётчика. Осталось только отсчитывать время высокого уровня для каждого из каналов ШИМ. Итого, осталось 4 счётчика. Не намного, но легче.

Теперь давайте вспомним, что контроллер, это не аналоговая микросхема, а цифровая, и моменты времени он отсчитывает дискретно. Все три времени высокого уровня (для каждого из каналов ШИМ) будут кратны какому-то общему кванту времени. Длительность этого кванта определяется разрядностью ШИМ и частотой импульсов. В случае, когда все каналы работают на одной частоте и имеют одинаковую разрядность, этот квант времени будет равен: T1=1/(f*(2n-1)), где n-разрядность ШИМ, f — частота импульсов.

Если ШИМ 8-ми битный и работает на частоте 100 Гц, то длительность кванта равна (1/100)/(28-1)=39 мкс — общее время импульса (1/f), делённое на число возможных моментов переключения (2n) минус 1 (если на прямой поставить N точек, то они образуют N-1 интервалов).

3 программных канала ШИМ, иллюстрация работы

То есть, нам достаточно одного аппаратного счётчика, который будет отсчитывать интервалы T1. Далее, создаем программный счётчик, который будет подсчитывать количество таких интервалов, и задаём четыре уставки. Одна уставка определяет, — сколько нужно отсчётов программного счётчика чтобы отсчитать время высокого уровня для первого канала ШИМ, вторая — тоже самое для второго канала, третья — для третьего, четвертая соответствует общему времени импульса, а операции сравнения, переключения, увеличения или обнуления программного счётчика будем
делать по прерыванию от аппаратного счётчика.

Основной недостаток такого метода в том, что вместо (n+1) прерываний за период, мы будем обрабатывать (2n-1) прерываний.

Давайте прикинем, какой может быть максимальная частота ШИМ при такой реализации? Очевидно, что при максимальной частоте, времени у контроллера хватает только на обработку прерывания. То есть, весь квант времени Т1 контроллер занят обработкой прерывания, как только он выходит из прерывания — тут же происходит ещё одно.

Если обозначить максимальное число машинных циклов, за которое выполняется подпрограмма, Nmax — то, с учётом выражения для T1, получаем уравнение: Nmax*4/fosc=1/(fmax*(2n-1)). Отсюда, максимальная частота ШИМ: fmax=fosc/(4*Nmax*(2n-1)). Естественно, полученная формула просто оценочная, потому что мы допускали, что подпрограмма занимает всё время T1, но если после выполнения подпрограммы останется время для выполнения 2-х, 3-х команд, то это в общем-то тоже не сильно нас устроит. Что можно сделать в 3 команды? По нормальному, если мы хотим ещё что-то делать, например, обмениваться инфой с компом, то подсчитанное значение частоты нужно поделить ещё минимум вдвое.

От чего зависит максимальное время выполнения подпрограммы прерывания? Ну, во-первых конечно, от степени криворукости программиста, и во-вторых — от количества каналов ШИМ, которые мы хотим реализовать.

Для того, чтобы было понятно, о каких величинах идёт речь, рассчитаем конкретный пример: пусть контроллер работает на частоте fosc=4 МГц, мы написали подпрограмму, которая выполняется максимум за 40 машинных циклов и хотим получить разрядность ШИМ 8 бит. Тогда максимальная частота ШИМ будет равна 4000000/(4*40*255)=98 Гц. Как видите, при таком способе реализации, всё достаточно ограничено, но для RGB хватит. Между прочим, при 8-ми битах на цвет мы получим общее количество цветов, равное 28*28*28=16 млн и вообще стоит подумать — надо ли нам столько?

При разрядности 2 бита на канал и той же тактовой частоте можно получить максимальную частоту ШИМ, равную 4000000/(4*40*3)=8,3 кГц, при этом будет 22*22*22=64 различных сочетания коэффициентов заполнения (в случае с RGB это 64 цвета). Такую частоту уже можно юзать не только для RGB.

Ну вот, на этом с теорией всё.

Практическая реализация изложенного метода в программе управления RGB-светодиодом.

Добавить комментарий