|
STM PWM Input, Как отцифровать на STM несколько PWM сигналов |
|
|
|
Feb 6 2015, 17:54
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Всем привет! Ковыряюсь с новым для себя семейством от STM, потому все чуднО и Чудно пока что  . Дано: 6 входных сигналов (лучше 10), период сигнала порядка 20 мСек, длительность импульса от 1 до 2 мСек. Начало сигналов близкое, но в общем случае не одновременное, длительность в интервале 1-2 мСек любая, но именно в этом интервале. Надо: Получить значение длительности каждого сигнала при этом не убив все ресурсы процессора. делаю это на stm32f3discovery. Собственно у меня есть несколько рецептов, может у кого есть лучше, посоветуйте. 1. Вариант Input PWM - вообще не вариант, так как на 1 сигнал ухлопывается целый таймер. 2. Хотел запустить таймер бежать, настроить каналы в режиме capture, на оба фронта, и по прерыванию capture сохранять начало и конец фронта. Но что-то я читаю описание, и вроде как получается что режим срабатывания по обоим фронтам идет через slave controller и как я понимаю я не могу иметь 4 независимых канала или нет? Можно конечно перенастраивать то на восходящий, а в прерывании перенастраивать на падающий, но как-то это не красиво ИМХО 3. Подать сигналы на ножки с прерывание по фронту, и запустить бежать таймер, в прерывании сохранять значение. Из плюсов что можно всего 1 таймер, Из минусов что есть нечеткость определения фронта, пока обрабатываем одни ноги, другие могут сработать и пойдут по не правильному времени. Еще я правильно понимаю что прерываний от ног всего 16, и если взяли прерывание от А0.8, то ни от B0.8 ни от С0.8 его уже не получить? 4. Тупой полинг, долбить уровень на ногах и запустить таймер, но что-то это как-то мрачно, весь ресурс уйдет на это... Посоветуйте, может я какие варианты забыл, может какое-то жесткое ДМА можно придумать в целом я себе вижу что точность в 1000 уровней на интервал будет выше крыши.
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 32)
|
Feb 6 2015, 19:30
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Golikov A. @ Feb 6 2015, 22:54)  Дано: 6 входных сигналов (лучше 10), период сигнала порядка 20 мСек, длительность импульса от 1 до 2 мСек. Сигналы управления сервомашинками? С приёмника радиоуправления? Я как-то тоже имел дело с такой задачей. Но мне повезло - нашёл на своём приёмнике ножку, на которой присутствовал дешифрованный сигнал из эфира, где последовательно появлялись все импульсы для 6 каналов. Так что обошёлся одним каналом захвата. В вашем случае сигналы начинаются одновременно, поэтому так просто не выйдет. Я за второй вариант, перестроить в прерывании захвата фронт/спад - пара команд. К тому же, вам всё равно нужно различать фронт и спад: один из них - начало импульса, один - конец. Я имею в виду, что вас интересует длительность от начала до конца, а не наоборот
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 6 2015, 20:13
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Ну да приемник, только их 2 (4 и 6 каналов), и они старого образца, у них нет режима вывода на одну ногу. И даже если бы был, задача решить для самого тупого варианта, который будет работать всегда. Так что надо цифровать 6-10 сигналов... Хоть отдельный проц на это ставь, или ПЛИС. Цитата В вашем случае сигналы начинаются одновременно, поэтому так просто не выйдет. Правильнее говорить почти одновременно, потому что иначе бы я закапчил по восходящему общее начало, и потом все спады, а тут надо отдельно каждый сигнал. Цитата Я имею в виду, что вас интересует длительность от начала до конца, а не наоборот ну в целом одна величина 1-2 мСек, а другая 18-19 мСек. Так что они различимы даже если не следить за фронтами. Цитата Я за второй вариант, перестроить в прерывании захвата фронт/спад - пара команд. Спасибо, опираясь на ваш опыт с STM, если поддерживаете решение, то значит я ничего не упустил  . Будем перенастраивать... А прерывания по ножкам действительно все так? то есть занял 8 прерывание портом А, и Б уже не подключить? Цитата Для разгрузки ЦП я бы сделал аппаратно, например на CPLD, а ЦП будет только собирать данные. (это только мое мнение) Спасибо, это основное решение на будущее, только CPLD не хватает, маленькие они, легче уже FPGA закатать, и кучу остального на нее сбросить, может даже проц в нее вогнать. Вторая итерация если будет, то именно такая. Пока для тестов мучаем проц. Может быть их станет 2 один будут рубить эту задачу, а другой дело делать
|
|
|
|
|
Feb 6 2015, 20:36
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Golikov A. @ Feb 7 2015, 01:13)  А прерывания по ножкам действительно все так? то есть занял 8 прерывание портом А, и Б уже не подключить? Если завели внешнее прерывание на 8 ножку порта A, то завести другое на 8 ножку порта B не получится. Можно: A0, A1, A2, ... A15. Нельзя: A0, B0, C0, A1, B1, C1... Но в применении внешних прерываний для замера длительности сигналов главный недостаток не этот, а потеря точности при одновременном поступлении сигналов.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 6 2015, 20:43
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата Но в применении внешних прерываний для замера длительности сигналов главный недостаток не этот, а потеря точности при одновременном поступлении сигналов. Это понятно. 1 мСек длительности это на 72 МГц - 72 000 циклов. Мне достаточно разрешения в 1000 отсчетов, то есть +- 36 циклов не критично. Зато экономиться куча таймеров, и больше разнообразие ножек (могло бы быть, если бы не дурное ограничение что ножка одного порта блокирует другой  ...) Была безумная мысль зарядить ДМА по таймеру читать состояние входа раз в микросекунду с запуском таймера по XOR входов, а потом анализировать массив, но это может оказаться еще дольше. И не факт что ДМА может читать порт, это еще не проверял... Цитата А измерять нужно каждый импульс, или можно пропускать? Нужны все импульсы группы, нельзя из первой пачки померить 1, из 2 пачки 2 и так далее... то есть если 1 канал замерили, то без 2-6 каналов измерение не имеет смысла и выпадает все целиком. ну и пропуски - это оперативность реакции на входное воздействие, если потерь много - то это тоже никому не надо...
|
|
|
|
|
Feb 6 2015, 20:50
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
Цитата(Golikov A. @ Feb 6 2015, 22:36)  на один порт? по ИЛИ что ли? Тогда первый поднявшийся сигнал замаскирует начало всех остальных.... Можно по xor конечно, но тоже будет такая каша из фронтов, что пипец.... тем более прерывание на оба перепада - это в STM отсутствует как я понял. Собственно как и выбор контроллера, если менять элементную базу, то тогда сразу ПЛИС ставить и не мучатся. Если по ходу обработки прерывания по одной ноге произойдет прерывание по другой, то обработчик запустится повторно. Обычно switch-case. Но если скажем две ноги одновременно, то обрабатывать тоже разумнее как два события за одно прерывание и сносить оба флага. Можно проверять все биты интересующих ног. Тут уже что быстрее то и лучше. Думаю с учетом всей палитры нужно просто по очереди перебрать все биты и обработать попутно снеся флаги в сработавших. EXTI_RTSR и EXTI_FTSR. Выбирайте пины хоть по спаду хоть по фронту хоть по двум событиям сразу. Просто регистры разные для каждого события.
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Feb 6 2015, 20:51
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Golikov A. @ Feb 7 2015, 01:43)  1 мСек длительности это на 72 МГц - 72 000 циклов. Мне достаточно разрешения в 1000 отсчетов, то есть +- 36 циклов не критично. Обработчик одного прерывания будет уже больше 36 циклов. А если не два, а три прерывания одновременно? Не, это не вариант, кмк. Захват таймерами десятка импульсов раз в 20 мс - это совсем небольшая нагрузка для STM-ки на 72МГц. Ну или узнайте способ кодирования ваших систем радиоуправления, и, если там PPM, то залезть внутрь приёмника и найти там сигнал всех каналов. Тогда всё будет вообще легко.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 6 2015, 20:52
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Это когда прерывания как у LPC, там весь порт каждая нога вызывает прерывание, и по флагам можно понять от кого. а в STM у них на каждую ногу свое прерывание, и группами объединены 0, 1, 2, 3, 4, 5-9, 10-15, но главная засада что задействовав ногу А0.1, уже B0.1, C0.1, D0.1 не могу давать прерывание, это немного затрудняет, но в целом не критично
|
|
|
|
|
Feb 6 2015, 20:56
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата Ну или узнайте способ кодирования ваших систем радиоуправления, и, если там PPM, то залезть внутрь приёмника и найти там сигнал всех каналов. Тогда всё будет вообще легко.  не ну это жестоко... естественно там скорее всего PPM, но курочить приемник не. Его следует считать черным ящиком.... Цитата Обработчик одного прерывания будет уже больше 36 циклов. А если не два, а три прерывания одновременно? Не, это не вариант, кмк. Захват таймерами десятка импульсов раз в 20 мс - это совсем небольшая нагрузка для STM-ки на 72МГц. одного наверное все же меньше, а вот наслоения возможно... Ок. отказываемся от идеи прерываний. Значит основной рабочей идеей принимается капчить таймер, с перестройкой фронта. Всем спасибо за участие! Цитата Если у Вас 10 сигналов, а портов 5 то заведите 5 сигналов на EXTI0 а другие 5 на EXTI1. По каждому прерыванию обработайте только 5 ног. я не понимаю как это сделать  ... Что такое завести 5 сигналов на EXTI0 как? схемно снаружи проца, или внутри как то можно? Какой схемой?
|
|
|
|
|
Feb 6 2015, 21:01
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
Цитата(Golikov A. @ Feb 6 2015, 22:52)  Это когда прерывания как у LPC, там весь порт каждая нога вызывает прерывание, и по флагам можно понять от кого. а в STM у них на каждую ногу свое прерывание, и группами объединены 0, 1, 2, 3, 4, 5-9, 10-15, но главная засада что задействовав ногу А0.1, уже B0.1, C0.1, D0.1 не могу давать прерывание, это немного затрудняет, но в целом не критично Есть такая ситуация. Пользуйте 9-15 или что там. Ошибся немножко в номерах... Кстати в жизни пробовал. Тоже интервалы милисекундные были. Кейл здорово код соптимизировал. И тоже был выбор из 8 событий по разным ногам. Смотрите. Рад был быть полезен если был конечно.
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Feb 7 2015, 12:50
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
Цитата(jcxz @ Feb 7 2015, 14:08)  Ещё вариант: Завести все сигналы на один GPIO-порт. Также объединить их (внешней логикой) по ИЛИ в один сигнал, от которого запускать DMA, считывающий этот порт с частотой 1МГц в буфер в ОЗУ. Размер DMA-передачи - 2000 отсчётов. По завершении DMA-транзакции несложно определить начало и конец каждого импульса, проксорив начало и конец полученного массива значений порта. Из плюсов: хорошая масштабируемость - не привязано к кол-ву аппаратных ресурсов (таймеров), хоть до 32 сигналов захватывайте.
PS: Хотя конечно это гораздо более тяжёлый для процессора вариант. Только видать в две страницы писать прийдется. Пока одна пишется вторая обрабатывается. Процесс такой обработки страницы это на 72 МГц что-то около 1,5-2 мС. Не так и тяжело. Но и не пропустит событий. Цитата(Golikov A. @ Feb 7 2015, 14:38)  Еще я не совсем пока уверен в ДМА, что оно умеет читать порт. Пока не проверял. Я так понимаю нужно заряжать память-память и пинать по таймеру с нужным временным разрешением. Первое значение в памяти без инкремента, второе в массив в памяти с инкременом. Хотя сам так не делал может и не правда все это. Кстати в ЦАП так выводил, но это получается наоборот.
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Feb 7 2015, 17:11
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Golikov A. @ Feb 7 2015, 18:38)  даже без сравнений это не менее 2000*6 действий, а добавив туда еще сравнения и какие-то переходы, да тот же инкремент цикла и уже получаются миллисекунды. Если будет больше 2 мСек, то легче на эти 2 мСек полингом сигналы долбить и по таймеру отмечать конец и старт, разрешение будет даже повыше Во-первых: Зачем 2000? Вы же сами написали что минимальная длина импульса 1мс и старты импульсов близки друг к другу. Так что - достаточно пройтись немного от начала полученного массива и до 1000 отсчётов от конца. Во-вторых: Откуда 6? Если уж спускаться до ассемблера, то в базовом варианте, без оптимизации, со всеми переходами и счётчиком цикла получается 7 команд (если GPIO STM32 имеет функцию маскирования при чтении как в LPC, то на команду меньше). Далее - исходя из Вашего условия, что кол-во сигналов много меньше кол-ва сэмплов в массиве, и сигналов <=8, можно провести оптимизацию алгоритма и получить в пределе до 3.5 команд на каждые 4 сэмпла (с маскированием в GPIO еще на 1 команду меньше). Это я учёл только основной цикл поиска. Ответвления от цикла при обнаружении изменения сигнала и счётчик цикла я не учёл, но они дадут небольшую прибавку если учесть вышеизложенные условия. Так что в целом, на проход 1000 сэмплов понадобится ~1000 тактов, что при 72МГц всего неск. мксек. Может что-то я не учёл, но порядок примерно такой. ЗЫ: Конечно на DSP этот поиск просто шикарно ложится, но увы - у Вас всего лишь Cortex.  Цитата(smk @ Feb 7 2015, 18:50)  Только видать в две страницы писать прийдется. Пока одна пишется вторая обрабатывается. Процесс такой обработки страницы это на 72 МГц что-то около 1,5-2 мС. ТС же указал в условии, что измерять надо только во время импульсов, между импульсами - большие паузы. И я предложил запускать DMA от логического ИЛИ всех сигналов, полученного внешней логикой. Если её нет, то да - придётся делать непрерывное чтение. Цитата(smk @ Feb 7 2015, 18:50)  Я так понимаю нужно заряжать память-память и пинать по таймеру с нужным временным разрешением. Нужно читать GPIO->ОЗУ, а синхронизацию (события для DMA) брать от таймера. Думаю - STM32 это должен уметь.
|
|
|
|
|
Feb 7 2015, 23:37
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
1000 отсчетов на 6-10 каналах будет не меньше 6000-10000 тактов, при 1 такте на семпл, а при 7 тактах это 43-70К циклов... ну в целом да получается 1-2 мСек... равносильно полингу, но более точные фронты. Цитата stm позволяет оцифровывать аппаратно pwm сигнал. Определяется сразу скважность. Таймеров в некоторых камнях порядка 9 штук, если память не изменяет. По памяти не помню, возможно ли 4 входа на таймер. Надо смотреть. аппаратно это делают далеко не все таймеры в STM там надо 2 канальный таймер с слейв контролером. Так что на 6 каналов не набирается, а на 10 тем более... надо капчить полюбому...
|
|
|
|
|
Feb 8 2015, 08:07
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Оцифровка ШИМа через АЦП - нормальный способ, надо только кондерчик с резюком, но не хочется сильно внешнюю схему городить. Пока все решается соединением дискавери проводками, а так придется платку хотя бы на слепыше паять. Аналоговых вочдогов на 6 каналов вроде не хватает... Цитата Что-то Вы недопоняли.... очевидно. вот к примеру для 3 каналов 000 010 010 011 011 111 .... конечно можно кейзом обрабатывать и по виду числа за 1 раз находить все фронты, нодля 3 уже 8 кейсов, а для 6-10?. В общем случае каждый канал надо обработать отдельно. Потому я число отсчетов умножил на число каналов для каждого из них надо сделать действие, да цикл будет общий, 6 тактов цикла на все каналы разом, но внутри еще по 6N(каналовых) действий. Тоже в целом годный вариант, если ДМА не подведет...
|
|
|
|
|
Feb 8 2015, 08:19
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Golikov A. @ Feb 8 2015, 14:07)  конечно можно кейзом обрабатывать и по виду числа за 1 раз находить все фронты, нодля 3 уже 8 кейсов, а для 6-10?. В общем случае каждый канал надо обработать отдельно. Потому я число отсчетов умножил на число каналов для каждого из них надо сделать действие, да цикл будет общий, 6 тактов цикла на все каналы разом, но внутри еще по 6N(каналовых) действий. Не так. Не case тут спасение. Вы забываете, что CPU у нас - 32-битный  Чтобы не быть голословным приведу примерный код: CODE THUMB PUSH {R4-R9} LDR R0, =table01 LDMIA R0, {R6-R8} SUBS R9, R8, #4 MOVS R4, #0 ;текущее состояние входов MOVS R5, #N ;счётчик проходов ADR R12, pp01_0 pp01: LDR R0, [R9, #4]! EORS R0, R0, R4 ANDS R0, R0, R6 ;можно убрать, если в GPIO есть соответствующая возможность маскирования (как в LPC) BNE pDetect_0 pp01_0: LDR R0, [R9, #4]! EORS R0, R0, R4 ANDS R0, R0, R6 ;можно убрать, если в GPIO есть соответствующая возможность маскирования (как в LPC) BNE pDetect_1 pp01_1: LDR R0, [R9, #4]! EORS R0, R0, R4 ANDS R0, R0, R6 ;можно убрать, если в GPIO есть соответствующая возможность маскирования (как в LPC) BNE pDetect_2 pp01_2: ;... здесь можно повторить ещё неск. раз для уменьшения влияния счётчика проходов SUBS R5, #1 BNE pp01 POP {R4-R9} BX LR
pDetect_2: ADDS R12, R12, #pp01_2 - pp01_1 pDetect_1: ADDS R12, R12, #pp01_1 - pp01_0 pDetect_0: pDetect: RBIT R1, R0 CLZ R1, R1 SUBS R3, R9, R8 ADDS R3, R3, R1, LSR #3 ANDS R2, R1, #7 ;R2 == номер изменившегося бита ;здесь: ;R2 - номер изменившегося бита в байте ;R3 - смещение [байт] от начала DMA-массива ;сохраняете это куда-нить в выходной результат LSLS R3, R7, R2 EORS R4, R4, R3 BICS R0, R0, R3 BNE pDetect ;ищем след. изменившийся бит MOV R0, R12 ADR R12, pp01_0 BX R0
LTORG DATA table01 DC32 83838383h ;R6. маска для случая использования 0,1,7 битов в порту для сигналов DC32 01010101h ;R7 DC32 dmaBuf ;R8. Указатель на начало буфера с сэмплами Может где-то есть ошибка - не отлаживал канеш. Но вобщем смысл такой. Как видите - на каждые 4 байта тратится 4 команды (для LPC можно сократить до 3-х, может и в STM тоже можно). Если блоков pp01_x сделать несколько, то эффект от лишних таков в конце цикла размажется по ним и сократится. pDetect будет выполняться сравнительно редко и не будет сильно влиять на задержку.
|
|
|
|
|
Feb 9 2015, 07:55
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
ну так я у вас и посмотрел, и отразил как бы суть происходящего. Единственное не уверен насчет такой плотной упаковки, порт 16 битный, а регистр с его значением 32 битный, возможно будет все же по слову на семпл, но это нюансы. Цитата Но если хватает ресурсов таймеров, то лучше всё-таки на их capture делать. не лучше, а проще и чуть точнее%) даже не столько проще, сколько понятнее)
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|