=GM= 0 13 октября, 2007 Опубликовано 13 октября, 2007 · Жалоба Ничего я не забыл. Пожертвовал я старшим битом уставки таймера. Так что шимов - 24 Прошу пардону, проглядел четвёртый оператор ld, который загружает уставку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 13 октября, 2007 Опубликовано 13 октября, 2007 · Жалоба Таймер устанавливается с максимумом 128 (должно быть два OCR в таймере), и старший бит в новом значении для таймера говорит, склеивать ли прерывания в одно. Только чуть-чуть ширина может меняться, но ее тоже можно скомпенсировать. Добавлю, таймером можно и не жертвовать. Есть два пути решения проблемы, первый - экстенсивный: переключение всего прерывания на обработку уставок до 0х7F и после 0х80, и второй - интенсивный(:-) - вместо уставки поставить флаг сцепленности двух прерываний, а саму уставку читать позднее (там возникнет ещё одна проблемка, тоже решаемая...), не буду сильно грузить, подумайте, может быть коллективный разум придумает третий, наиболее приемлемый путь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
add 0 15 октября, 2007 Опубликовано 15 октября, 2007 · Жалоба Ув. =GM=, перечитал все посты не один раз, но так и непонял сути Вашего алгоритма. Как я понял Вы заранее подготавливаете данные для вывода в порт а также константу сравнения для таймера. Но если у вас для всех 24-х каналов устанавливается длительность одновременно, как меняется значение в каждом канале? Или у Вас задан массив в котором значение для одного канала задается не в одном байте а в х-отом бите каждого байта, а текущая длительность интервала импульса шима по прерыванию либо добавляется, либо нет к интегралу всего периода? Поправьте пожалуйста, если чтото не так понял. :laughing: :rolleyes:Какое максимальное кол-во значений ступенек можно в таком случае реализовать? И на сколько МЦ затратно подготовка данных для такого шима? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 15 октября, 2007 Опубликовано 15 октября, 2007 · Жалоба Ув. =GM=, перечитал все посты не один раз, но так и непонял сути Вашего алгоритма. Как я понял Вы заранее подготавливаете данные для вывода в порт а также константу сравнения для таймера. Но если у вас для всех 24-х каналов устанавливается длительность одновременно, как меняется значение в каждом канале? Или у Вас задан массив в котором значение для одного канала задается не в одном байте а в х-отом бите каждого байта, а текущая длительность интервала импульса шима по прерыванию либо добавляется, либо нет к интегралу всего периода? Поправьте пожалуйста, если что-то не так понял. Какое максимальное кол-во значений ступенек можно в таком случае реализовать? И на сколько МЦ затратно подготовка данных для такого шима? Ну, если по-честному, то я здесь свой алгоритм и не выставлял, немудрено его не понять. Был выложен фрагмент Саше Витебскому просто для иллюстрации, как я реализовывал свой алгоритм, ничего более. Но потом народ стал спрашивать подробности, я стал отвечать, теперь вроде бы должен нести ответ(:-) Итак, приступим к выявлению момента истины...Несколько аксиом для разгона. 1) Будем использовать МК с ОЗУ не менее 1 Кбайта и тактовой частотой 20 МГц, ну и ног должно хватить по крайней мере для 24 выходных шимов. Пусть это будет атмега88. 2) Формирование выходных сигналов 24-канальной шим осуществляется в прерывании таймера0 по сравнению в Output Compare Unit (подробнее см. в doc8025а, с.98). Программа выдачи приведена в моём посте #18. Время выполнения 18 машинных циклов (можно снизить до 13). 3) За период шима может возникнуть максимум 24 прерывания (по числу сигналов шим). 4) Полное время на все прерывания не более 18*24*0.05=21.6 мкс. Как это всё работает. В начале периода шим обнуляются все 24 шим сигнала и таймер начинает работать с 0. В регистр сравнения OCR0A из текущего буфера запихивается первая уставка, т.е. таймерное время, когда некоему шиму (или нескольким, не важно) необходимо перейти из состояния 0 в состояние 1. При достижении равенства уставки и значения в таймере происходит прерывание OCF0A, начинает работать программа из поста #18, которая выставляет в порты сформированные заранее образы всех ТРЁХ портов. Затем программа записывает в OCR0A вторую уставку и засыпает до следующего прерывания. В это время фоновая программа подготавливает следующий буфер для следующего периода шим. Буфер состоит из 24 записей. Каждая запись содержит 4 байта. Общий вид таблицы таков уставка образ п.А образ п.B образ п.C .db 0x10, 0b0000000, 0b0000000, 0b00000011 .db 0x20, 0b0000000, 0b0000000, 0b00000111 .db 0x21, 0b0000000, 0b0000000, 0b00001111 .db 0x50, 0b0000000, 0b0000000, 0b00011111 . . . . . . . . . . . . . . . . . . . . . . . . . . . .db 0x8F, 0b1011111, 0b1111011, 0b00011111 .db 0xB9, 0b1111111, 0b1111111, 0b11111111 Как можно видеть, бит образа порта, перешедший из состояния 0 в состояние 1 в N-ой записи, остаётся в этом состоянии до конца таблицы. Основными задачами фоновой программы (с точки зрения формирования шим) являются приём извне (или вычисление) новых уставок для каждого канала и подготовка на их основе нового буфера. По окончанию подготовки нового буфера адрес нового буфера записывается в ячейку памяти. При нулевом времени таймера этот адрес записывается в регистр Х, как я уже говорил ранее. Далее фоновая программа принимает новые уставки и ждёт начала нового периода шим для подготовки нового буфера. Ну вот, вгрубе и всё описание. В завершение, ответы на ваши вопросы. Максимальное количество ступенек – 256, за один период шима (для 6 кГц) фоновая программа успевает учесть в подготовке все 24 уставки (подчеркну, если они будут готовы), об этом тоже писалось ранее. Например, в одном периоде можно установить все сигналы в 1, а в следующем – в 0. На выходе всех каналов будет меандр с Fшим/2. Как видите, можно легко и непринуждённо достичь частоты Найквиста(:-). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 15 октября, 2007 Опубликовано 15 октября, 2007 · Жалоба Вот моя базовая процедура, выполняется за 18 МЦ ;Процедура формирования 256-точечного 24-канального ШИМа (18МЦ) 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 TCR0,temp ;для сравнения reti =GM=, лихо у Вас такты подсчитаны, я так не умею Вот мой расчет для худшего случая: 3(джиттер при попадании прерывания на 4 тактовую команду) + 4(вход в прерывание) + 4*2(LD) + 4*1(OUT) + 4(RETI) + 4(максимальное количество тактов до начала следующего прерывания) = 27 тактов однако... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 15 октября, 2007 Опубликовано 15 октября, 2007 · Жалоба Кстати сам СИ скомпилит не очень плохо. У меня сейчас правда несколько отличная задача. В смысле ШИМ то построен также но список состояний строго ограничен. В связи с этим я всё делаю прямо в прерываниях. То есть управление двигателями размазываю по всем прерываниям. Включая разгон/торможение/управление скоростью/ подход к заданному значению. Поэтому п/п у меня несколько раздуты. Ну и конкест соответственно великоват. Но сам вывод портов - вполне адекватен. 69 // Вывод предварительно расчитанных значений портов 70 PORTE = bOport[1].E; \ 0000002C .... LDI R26, LOW(bOport) \ 0000002E .... LDI R27, (bOport) >> 8 \ 00000030 01FD MOVW R31:R30, R27:R26 \ 00000032 8103 LDD R16, Z+3 \ 00000034 B90E OUT 0x0E, R16 71 PORTA = bOport[1].A; \ 00000036 8104 LDD R16, Z+4 \ 00000038 B902 OUT 0x02, R16 72 PORTC = bOport[1].C; \ 0000003A 8105 LDD R16, Z+5 \ 0000003C B908 OUT 0x08, R16 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 15 октября, 2007 Опубликовано 15 октября, 2007 · Жалоба 3(джиттер при попадании прерывания на 4 тактовую команду) + 4(вход в прерывание) +4*2(LD) + 4*1(OUT) + 4(RETI) + 4(максимальное количество тактов до начала следующего прерывания) = 27 тактов однако... Ну, во-первых, у меня одно и двухтактные команды в фоне, четырёхтактных нет вообще, во-вторых, джиттер считать не надо, поскольку на следующем прерывании будет такой же случайный джиттер. Матожидание там равно нуло, стало быть вклад джиттера будет нулевым. В первом приближении вы правы, общее количество тактов = 4(сохранение программного счётчика в стеке) + 2(прыжок из вектора прерывания, это вы забыли, но можно опустить) + 12(тело программы) + 4(reti) + 1/2(выполнение одной команды) = 24 такта максимум. Я эту программу привёл просто как иллюстрацию Саше Витебскому, я такую не использую. С ходу могу её улучшить тактов на 5, поставив sei перед последней командой out, а вот почему так, подумайте на досуге, неплохая шарада перед сном(:-). В принципе, Rst7 (мой респект!) привёл фрагмент, практически один в один совпадающий с одной из моих ранних штатных программ, там допускается 13 тактов между двумя последовательными обновлениями портов. Раз разговор зашёл о количестве тактов и о максимальных частотах, сообщаю вам, на сегодняшний день я довёл частоту шим до 11 кГц, и пока на этом успокоился(:-). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 15 октября, 2007 Опубликовано 15 октября, 2007 · Жалоба Я думаю некоторым это пригодится. Когда-то на заре появления МК тоже любил побаловаться "вылизыванием до такта". Теперь считаю это не перспективным. Это я безусловно, не в пику вам говорю. Это так размышления у парадного подъезда электроники. Всё это уже многократно обсуждалось, но если подытожить то выглядит так: 1) Производительность процов продолжает расти семимильными шагами. Появились доступные DSP процы и многоядерные процы. 2) Стоимость кремния и процов снизились до стоимости мусора. Так где-то в 90 году стоимость однокристалки 8751 доходила до 350 рублей (читай $). Сейчас как известно стоимость опустилась до 1$ при более чем 20 кратном росте производительности. 3) Реальная стоимость $ в 90 году была несопоставима с его нынешней стоимостью. 4) Стоимость памяти упала ещё более значительно. В 93 году стоимость 1мб ОЗУ ~ 30$ ============== Подытоживая - Вы можете использовать очень мощные камни и при этом очень длинные проги писать и массу озу использовать и при этом конечная стоимость изделия вполне будет по карману рядовому покупателю. С другой стороны запросы растут. Требуются всё более умные вещи. Потребность в программах и программистах - растёт (В том числе и за счёт перекладывания большого числа ф-ий которые раньше делались аппаратно). Время написания проекта и его изготовления - катастрофически уменьшается. Всё меньше людей хотят купить проект - всё большее готовое рабочее изделие. Поэтому, на мой взгляд роль языков высокого уровня будет расти. Колличество программных инструментов - тоже. Применение ОС будет если не повсеместным, то распространённым явлением. Программы будут писаться наотмашь. То есть примерно такой подход, который развивается на компах. Где даже я сейчас конфигурационные файлы в текстовом виде делаю. А реестр винды будет занимать не один десяток мегов. :) :( Ну а из приятных моментов - применение красивых и интересных алгоритмов приветствуется на любом языке. То есть полученные знания всегда с вами и никуда не денутся. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
add 0 16 октября, 2007 Опубликовано 16 октября, 2007 · Жалоба SasaVitebsk, Вы так все хорошо подытожили.. прям даже не хотелось больше вопросов задавать :-) Ну, если по-честному, то я здесь свой алгоритм и не выставлял, немудрено его не понять. .. Значит мое предположение посте №48 оказалось верным. :-) Еще один мАААлюсенький вопросик, ну для полного блаженства :-).. Вот например если мы работаем с массивом постоянно меняющихся значений шима (.db 23,45,255,10 ....и т.п.) , то в озу необходимо подготавливать данные, а как? Ролами(rol)?, рорами(ror)? Как лучше перелопатить массив необходимую форму? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 16 октября, 2007 Опубликовано 16 октября, 2007 · Жалоба Значит мое предположение посте №48 оказалось верным. :-) Еще один мАААлюсенький вопросик, ну для полного блаженства :-).. Вот например если мы работаем с массивом постоянно меняющихся значений шима (.db 23,45,255,10 ....и т.п.) , то в озу необходимо подготавливать данные, а как? Ролами(rol)?, рорами(ror)? Как лучше перелопатить массив в необходимую форму? Ну я рад, что оно оказалось верным, только какое?(:-). Для подготовки данных я беру раттерны для каждого канала, они лежат в пзу, вид у них такой pattern: .db 0x01,0x00,0x00,0xFF ;образец для канала 1 .db 0x02,0x00,0x00,0xFF ;образец для канала 2 .db 0x04,0x00,0x00,0xFF ;образец для канала 3 и обычное OR три раза. Как-то так. Вообще, табличные методы сильно убыстряют процесс. Надо только найти подходящее табличное представление. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 16 октября, 2007 Опубликовано 16 октября, 2007 · Жалоба Раз разговор зашёл о количестве тактов и о максимальных частотах, сообщаю вам, на сегодняшний день я довёл частоту шим до 11 кГц, и пока на этом успокоился(:-). Давайте, покажите код, удивите нас ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
add 0 16 октября, 2007 Опубликовано 16 октября, 2007 · Жалоба pattern: .db 0x01,0x00,0x00,0xFF ;образец для канала 1 .db 0x02,0x00,0x00,0xFF ;образец для канала 2 .db 0x04,0x00,0x00,0xFF ;образец для канала 3 и обычное OR три раза. Как-то так. Вообще, табличные методы сильно убыстряют процесс. Надо только найти подходящее табличное представление. :crying: все, Вы меня добили! :twak: окончательно запутался. (видимо надо снова в школу идти) Попробую задать вопрос: Вот к примеру у нас массив (значения шима n-го канала): .db 11,255,20,188 и т. п. (это один канал!) ; каждое значение мы должны устанавливать через определенное время(ну например через секунду). для этого мы подготавливаем таблицу следующим образом: уставка образ п.А образ п.B образ п.C 1-канал..............................24канал .db 0x10, 0b0000000, 0b0000000, 0b00000011 7бит n-го канала .db 0x20, 0b0000000, 0b0000000, 0b00000111 6бит n-го канала .db 0x21, 0b0000000, 0b0000000, 0b00001111 5бит n-го канала .db 0x50, 0b0000000, 0b0000000, 0b00011111 4бит n-го канала ... так или нет? а если значения изменяется(приходит) из вне, нам надо преобразовать таблицу налету? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 16 октября, 2007 Опубликовано 16 октября, 2007 · Жалоба Вот к примеру у нас массив (значения шима n-го канала): .db 11,255,20,188 и т. п. (это один канал!) ; каждое значение мы должны устанавливать через определенное время(ну например через секунду) Нет, это не один канал, а все каналы. В этой строчке находятся образы всех портов на эн-ном прерывании. Например 255 равно 11111111 в двоичке, значит портА весь будет в единицах. Буфер, вид которого показан в посте #49, используется программой, показанной в посте #18, что ж тут непонятного. Таких буферов два, на каждом периоде шима один буфер используется этой программой, второй буфер готовится фоновой программой. Потенциально можно подготовить один буфер за период шима, да больше и не надо. Но можете готовить его и секунду (в фоне), если того допускают условия вашей задачи. Под готовить я понимаю не только формирование буфера, но и расчёт (или получение извне) уставок для него. а если значения изменяется(приходит) извне, нам надо преобразовать таблицу налету? Ну сказал уже, таблица готовится за один период шима. На лету это или нет? Зависит от угла зрения. Но быстрее просто не надо, незачем. Теперь стоит вопрос, как подготовить данную таблицу. Вот вы имеете все уставки, таблица из 24 записей (48 байт), первый байт - уставка, второй байт - номер канала. Таблица может быть неотсортирована, если отсортирована, то жизнь сильно упрощается. Предположим, вы её отсортировали, т.е. все времена идут строго в возрастающем, точнее, неубывающем порядке. Вопрос вам, как получить рабочую таблицу, вид которой показан в посте #49? Мой алгоритм таков. Берете первую запись, ставите туда первое время из таблицы уставок, теперь надо вставить 3 байта образа порта, по номеру канала находите в таблице паттернов нужные 3 байта и вставляете их в первую запись. Переходите ко второй записи. Перво-наперво сравниваете время второй уставки с временем из первой записи. Если они совпадают, то новую запись не создаете, а опять по номеру канала находите в таблице паттернов нужные 3 байта и делаете ИЛИ этих байтов с байтами из первой записи, и оставляете их в первой записи. Если они НЕ совпадают, делаете то же самое, но сохраняете в новой записи. И так делаете 24 раза. Долго было рассказывать, но МК тратит всего 644 МЦ. На сортировку уходит гораздо больше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 16 октября, 2007 Опубликовано 16 октября, 2007 · Жалоба Давайте, покажите код, удивите нас ;) Навеяло Больной: - Доктор, я буду жить? Доктор: - А смысл? Ну а если серьёзно, то я не готов ещё...Да и код сырой, не опробован в железе... Могу поделиться идеей, как выйти на 19 кГц программный шим, поскольку у меня не хватает времени на всё, вокруг столько интересного...Достаточно дикая идея кстати, но может стрельнуть! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 16 октября, 2007 Опубликовано 16 октября, 2007 · Жалоба Ну, во-первых, у меня одно и двухтактные команды в фоне, четырёхтактных нет вообще, во-вторых, джиттер считать не надо, поскольку на следующем прерывании будет такой же случайный джиттер. Матожидание там равно нуло, стало быть вклад джиттера будет нулевым. В среднем Вы правы, почти, в частностях нужно разбираться отдельно... джиттер нужно считать обязательно, потому что в данном случае он всегда будет в +, нуль Вы никогда не получите. Тока максимум двухтактовые команды в фоне ? О С в фоне уже речь не идет, да и на асм сильно себя ограничиваем ? В первом приближении вы правы, общее количество тактов = 4(сохранение программного счётчика в стеке) + 2(прыжок из вектора прерывания, это вы забыли, но можно опустить) + 12(тело программы) + 4(reti) + 1/2(выполнение одной команды) = 24 такта максимум. + 2(прыжок ....) конечно не забыл, просто изначально посчитал что с этим прыжком будет все совсем плохо и решил что прерывание прописано в области векторов. Я эту программу привёл просто как иллюстрацию Саше Витебскому, я такую не использую. С ходу могу её улучшить тактов на 5, поставив sei перед последней командой out, а вот почему так, подумайте на досуге, неплохая шарада перед сном(:-). Спасибо конечно за шараду, тока для меня все изначально понятно, и очень неочевидно что такой вариант даст правильный/предсказуемый вариант в ситуации возможности смены всех значений ШИМ за период ШИМ. Нарисуйте код и я покажу где будут проблемы. В принципе, Rst7 (мой респект!) привёл фрагмент, практически один в один совпадающий с одной из моих ранних штатных программ, там допускается 13 тактов между двумя последовательными обновлениями портов. Допускается, но может быть и на ~80% хуже ? (то есть дребезг будет порядка 9 тактов) Раз разговор зашёл о количестве тактов и о максимальных частотах, сообщаю вам, на сегодняшний день я довёл частоту шим до 11 кГц, и пока на этом успокоился(:-). Ну дык тогда приведите готовый код хотя бы на 6 КГц, как уже утративший свою актуальность :) , и мы его обсудим... Могу поделиться идеей, как выйти на 19 кГц программный шим, поскольку у меня не хватает времени на всё, вокруг столько интересного...Достаточно дикая идея кстати, но может стрельнуть! У меня тоже есть масса идей, но как показала практика общения с Вами, Вы ну это... слегка любите преувеличить... (надеюсь примеры не нужно приводить ?) Ваш вариант ШИМ очень неплох, тока если Вы заявляете о том что Вы достигли частоты XX, давайте разговаривать предметно..., без кода это бессмысленно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться