Вот код для формирования 256-точечного 24-канального ШИМа. Рабочая частота шим 3906 Гц. Здесь применено прерывание не от переполнения таймера0, а прерывание по совпадению.
t0comp: rjmp pwmisr ;таймер0 по совпадению
pwmisr: ld temp,x+ ;обновление
out port1,temp ;порта 1
ld temp,x+ ;обновление
out port2,temp ;порта 2
ld temp,x+ ;обновление
out port3,temp ;порта 3
ld temp,x+ ;новая уставка
out OCR0,temp ;для сравнения
reti
Всего 18 машинных циклов (МЦ).
Принцип работы проще всего понять на простом примере. Представим себе, что есть буфер на 24 уставки, и в регистр сравнения таймера0 занесена первая уставка. Счетчик считает от 0 до 255. При совпадении содержимого счетчика TCNT0 и регистра сравнения OCR0 возникнет прерывание t0comp (см. выше), которое запишет новую уставку и выйдет из прерывания. При совпадении снова возникнет прерывание и т.д.
В нашем случае регистр Х указывает на буфер, состоящий из 24 записей по 4 байта каждая, первый байт – это новая уставка, остальные три байта – это образы портов 1, 2 и 3. Таким образом после каждого прерывания уставка и состояние портов периодически обновляются.
Когда содержимое счетчика TCNT0 равно 255, возникает прерывание таймера0 по переполнению t0ovf, все порты обнуляются и в регистр сравнения OCR0 записывается значение первой уставки нового периода шим. Разумеется, что уставки никогда не должны быть установлены на 255.
t0ovf: rjmp eopwm ;таймер0 по переполнению
eopwm: ldi temp,0 ;обнуление
out port1,temp ;порта 1
out port2,temp ;порта 2
out port3,temp ;порта 3
lds xl,xaddress ;адрес текущего буфера уставок
ld temp,x+ ;первая уставка
out OCR0,temp ;нового периода шим
reti
Всего 15МЦ.
Прежде чем перейти к описанию процесса подготовки буфера уставок и состояний, подсчитаем суммарное время, потраченное на прерывания, формирующие 24-канальный шим, и фоновое время.
Очевидно, что в течение периода шим может возникнуть не более 24 переходов из 0 в 1, следовательно суммарное время не может быть больше 24*18+15=447 МЦ. Если взять период прерывания с небольшим запасом, скажем 20 МЦ, то минимальный период шима займет 20*256=5120 МЦ. Отсюда вытекает, что остается незанятым 5120-447=4673 МЦ (более 90% процессорного времени).
Как следует готовить буфер уставок. Нужно иметь два буфера на входные данные, один из которых используется для подготовки текущего буфера уставок (24*4=96 байт), а во второй пишутся входные данные для следующего периода шим.
Буфер входных данных представляет из себя массив 24*2 байт, в который последовательно пишется номер канала (1-24) и время (0-254). Предполагается, что входной буфер наполняется для каждого периода шим. Идеальным было бы получение упорядоченного буфера, т.е. такого, где время расположено в монотонном возрастающем порядке. Если это не так, то придется сортировать по получению, используя 91% свободного процессорного времени.
Известно много способов сортировки, но я бы сделал по рабоче-крестьянски. Из таблицы берется первое время и предполагается минимальным. Осуществляется поиск по таблице и находится действительно минимальное число. Если необходимо, то меняем их местами, заодно и ассоциированные номера каналов. Переходим ко второму времени в таблице и точно также ищем минимум, опять переставляем, ну и так далее, вплоть до предпоследнего номера.
В упорядоченной таблице заменяем номера каналов на 3-х байтовые образы портов и получаем рабочую тпблицу уставок и состояний портов. Последующие образы должны логически складываться с предыдущими (командой OR).
По моим прикидкам, время потребное для сортировки, составляет порядка 2700 МЦ, причем я не спец по сортировке и не оптимизировал, стыдно даже программу выкладывать, мне надо бы немного самообразоваться в данной области(:-(.
Вот всё. Передаю свои чистые мысли в ваши благородные руки(:-).