Перейти к содержанию
    

Самодельный игрушечный осциллограф

Естественно смещение 0 может быть любым. Конечно предварительно его вычесть надо.

Команды LDM на кучу регистров и SSUB16 в комплекте с ORRS/ANDS творят чудеса. B)

Предварительно - это когда? Сигнал влетает слово за словом, и по нему надо синхронизироваться. А найдя (программно, если вы так уверенно гарантируете), нужно запустить таймер, отсчитывающий количество выборок в захваченном кадре (или части кадра, от положения момента синхронизации зависит). Это еще несколько тактов нужно иметь. Набегает намного больше, чем 6.

 

На STM32F303 многое можно сделать аппаратно. Я сделал. Открыть реализацию не считаю возможным. Имеющему интерес рекомендую изучить datasheet вдоль и поперек, там есть волшебные возможности.

 

Еще один момент. Частоту дискретизации (развертку) желаете разную иметь? То есть, задавать таймером? А как тогда принимать данные с АЦП? Или прореживать непрерывно идущие данные, записывать реже? Здесь тоже есть где потерять тактов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Предварительно - это когда? Сигнал влетает слово за словом, и по нему надо синхронизироваться. А найдя (программно, если вы так уверенно гарантируете), нужно запустить таймер, отсчитывающий количество выборок в захваченном кадре (или части кадра, от положения момента синхронизации зависит). Это еще несколько тактов нужно иметь. Набегает намного больше, чем 6.

Похоже у Вас нет опыта обработки потоков данных....

Никаких "слово за словом", никаких таймеров и прочей аппаратной лабуды.

Работа идёт с потоком данных, находящимся в ОЗУ. Данные поступают в ОЗУ пакетно - блоками большой длины через DMA. В рассматриваемом случае - из внутреннего АЦП LPC4370.

Процессор просматривает поток DMA-блоков в поиске старта синхронизации (откуда начинать захватывать кадр для показа на экране).

Все времянки (отступы, размеры кадра и пр.) конечно задаются в сэмплах, так как частота их известна.

А теперь открываем описание системы команд Cortex-M4 и пишем обработчик DMA-блоков данных, который ищет момент перехода через "0":

               PUBLIC   AdcExec
;extern "C" void AdcExec(u32 *data, s32 sign, u32 zero);
;R0 - указатель на блок сэмплов для обработки (упакованы в 32-битные слова - по 2 сэмпла в каждом в битах 0...11 и 16...27 - в таком формате их выдаёт АЦП LPC4370)
;R1 - знак предыдущего значения сигнала
;R2 - текущее смещение нуля (в мл. 16 битах, остальные биты ==0)
;в блоке сэмплов [R0] находится 20*N*M сэмплов принятых в очередном блоке DMA
;каждый сэмпл - 12-битный беззнаковый, так что 0 - при мин. значении напряжения, 0xFFF - при макс, 0 шкалы АЦП == 0x800
histerezis     EQU      10            ;если желаем гистерезис
M              EQU      ...
AdcExec:       PUSH     {R4-R11, LR}
              LSLS     R3, R1, #1
              BMI      AdcExec_01
              SUBS     R2, R2, #histerezis
              IT       MI
              MOVSMI   R2, #0
              B        AdcExec_02
AdcExec_01:    ADDS     R2, R2, #histerezis
              LSRS     R3, R2, #12
              IT       NE
              MOVNE    R2, #0FFFh
AdcExec_02:    ORRS     LR, R2, R2, LSL #16
              MOVS     R2, #M        ;количество повторов 20*N для обработки всего блока сэмплов
              LSLS     R3, R1, #1
              BMI      AdcExec_21
              ;поиск <0
AdcExec_11:    LDMIA    R0!, {R3-R12} ;грузим 20 сэмплов в регистры
              SSUB16   R3, R3, LR    ;вычтем смещение нуля из 2-х сэмплов
              SSUB16   R4, R4, LR    ;повторим для остальных 18 сэмплов
              SSUB16   R5, R5, LR
              SSUB16   R6, R6, LR
              SSUB16   R7, R7, LR
              SSUB16   R8, R8, LR
              SSUB16   R9, R9, LR
              SSUB16   R10, R10, LR
              SSUB16   R11, R11, LR
              SSUB16   R12, R12, LR
              ORRS     R3, R3, R4
              ORRS     R3, R3, R5
              ORRS     R3, R3, R6
              ORRS     R3, R3, R7
              ORRS     R3, R3, R8
              ORRS     R3, R3, R9
              ORRS     R3, R3, R10
              ORRS     R3, R3, R11
              ORRS     R3, R3, R12
              ORRS     R3, R3, R3, LSL #16
AdcExec_12:    BMI      AdcExec_14    ;переход если в предыдущих 20 сэмплах обнаружен переход через 0 вниз
              LDMIA    R0!, {R3-R12} ;грузим следующие 20 сэмплов в регистры
              ;N раз повторим команды AdcExec_01...AdcExec_02
              ;...
              SUBS     R2, R2, #1
AdcExec_13:    BNE      AdcExec_11
              ;обработали весь блок сэмплов, не нашли перехода через 0, ждём следующего блока от DMA
              POP      {R4-R11, PC}

AdcExec_14:    ;здесь получено состояние "обнаружен переход через 0 вниз" в одном из предыдущих 20 сэмплов R0[-20]...R0[-1]
              ;сделаем более точное обнаружение с точностью до сэмпла и перейдём к захвату потока сэмплов для отображения 

AdcExec_21:    ;здесь напишем аналог процедуры AdcExec_11...AdcExec_13, но для поиска перехода в >=0

Участок AdcExec_11...AdcExec_12 обрабатывающий 20 сэмплов, должен выполняться примерно за 23 такта (расположим его в самой быстрой памяти, в ОЗУ например).

Берём калькулятор и видим, что на обработку одного сэмпла нужно немного более 1 такта.

Так что о каких "намного больше, чем 6" речь? Может у Вас на STM32F303 это так, но для LPC4370 всё ГОРАЗДО быстрее.

 

Еще один момент. Частоту дискретизации (развертку) желаете разную иметь? То есть, задавать таймером? А как тогда принимать данные с АЦП? Или прореживать непрерывно идущие данные, записывать реже? Здесь тоже есть где потерять тактов.

Частота развёртки - в смысле частота сэмплирования АЦП? При чём тут таймер??? Она задаётся тактовой частотой АЦП и её не трудно установить какую нужно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Начну с конца. Что за тактовая частота АЦП? На которой работает SAR ADC? Это к делу не относится. Должна быть достаточно большой, чтобы АЦП успевал работать. Речь про частоту запуска АЦП, от десятков мегавыборок до единиц выборок в секунду. Временная база, делается на таймерах. У вас никак не делается, постоянно одна (максимальная) частота выборок? Это не осциллограф.

 

Код рассмотрю в свободное от досуга время. Что там в AdcExec_14, "более точном"? Еще тактов 20? Или вас устраивает болтание кадра на 20 выборок вправо-влево?

А для перехода не через 0 видим только "аналог" программы? Для всех 4096 уровней по "аналогу"? Или там речь про фронт и срез сигнала?

Вычитая смещение (я правильно разглядел), можно ненароком перекрутить сигнал с минуса в плюс.

 

Дальше что? Нашли переход, включаем таймер... Все нужно успеть за пачку выборок.

Пока что полного решения не вижу. Оно было?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Берём калькулятор и видим, что на обработку одного сэмпла нужно немного более 1 такта.

Так что о каких "намного больше, чем 6" речь? Может у Вас на STM32F303 это так, но для LPC4370 всё ГОРАЗДО быстрее.

 

Это же пакетная постобработка. Не так интересно.

И памяти лишней требует и претриггеринг не гарантированный.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пакет еще дождаться надо, а в коде, кроме "ждём следующего блока от DMA", ничего не показано. А это еще несколько тактов+.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Начну с конца. Что за тактовая частота АЦП? На которой работает SAR ADC? Это к делу не относится. Должна быть достаточно большой, чтобы АЦП успевал работать. Речь про частоту запуска АЦП, от десятков мегавыборок до единиц выборок в секунду. Временная база, делается на таймерах. У вас никак не делается, постоянно одна (максимальная) частота выборок? Это не осциллограф.

Имелась в виду частота сэмплирования АЦП.

Я осциллограф не делаю. Делает ТС. У него в ТЗ указана только одна частота выборок. Нужность реализации других частот - его дело.

И "у меня" тоже делается. Вам код инициализации АЦП LPC4370 привести? Сами юзермануал прочитайте.

Для тактирования АЦП LPC4370 можно использовать отдельный PLL с пачкой опциональных делителей после него - никаких таймеров не нужно.

 

Код рассмотрю в свободное от досуга время. Что там в AdcExec_14, "более точном"? Еще тактов 20? Или вас устраивает болтание кадра на 20 выборок вправо-влево?

В смысле??? Вы смысл кода вообще поняли?

Какое болтание и какая разница сколько тактов будет в AdcExec_14???

В точке AdcExec_14 уже найдено, что в последних 20 сэмплах точно есть переход. А значит этот участок выполняется 1 раз на одно срабатывание синхронизатора.

Т.е. - 1 раз на один отображаемый кадр. Т.е. - не более чем 50 раз в секунду. И какая разница сколько там тактов? Да хоть 200 хоть 2000.

 

А для перехода не через 0 видим только "аналог" программы? Для всех 4096 уровней по "аналогу"? Или там речь про фронт и срез сигнала?

Не понял о чём речь :wacko:

Возьмите учебник по командам Cortex-M и разберитесь в коде.

Этот код ищет момент перехода через "0". Это самая ресурсозатратная часть алгоритма. О чём писал AlexandrY и утверждал что её невозможно сделать на Cortex-M для данной частоты. Всё остальное - ерунда.

 

Вычитая смещение (я правильно разглядел), можно ненароком перекрутить сигнал с минуса в плюс.

Нет, неправильно. До вычитания данные беззнаковые, после вычитания получаются знаковые данные, дальше анализируется их знак.

 

Дальше что? Нашли переход, включаем таймер... Все нужно успеть за пачку выборок.

Какой таймер??? Вы опять за своё. Похоже что ничего не поняли.....

 

 

Это же пакетная постобработка. Не так интересно.

И памяти лишней требует и претриггеринг не гарантированный.

Почему неинтересно? Именно так и работает любая обработка потоков данных.

Именно так и можно сделать поиск точки синхронизации для осциллографа - вполне рабочий вариант.

И почему не гарантированный?

 

Пакет еще дождаться надо, а в коде, кроме "ждём следующего блока от DMA", ничего не показано. А это еще несколько тактов+.

Какая разница сколько тактов?

Ещё раз - Вы не поняли ничего в работе этого кода.

Этот код должен запускаться на каждый принятый блок сэмплов от DMA. Размер такого блока должен быть достаточно большим (там приведено условие 20*N*M чем больше N и M - тем меньше загрузка CPU - эффективнее обработка).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

О чём писал AlexandrY и утверждал что её невозможно сделать на Cortex-M для данной частоты. Всё остальное - ерунда.

 

Эй, вы еще ничего не доказали. У вас есть всего три такта на ваших 204 МГц для каждого отсчета даже на постобработке.

Полное решение в студию!

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Эй, вы еще ничего не доказали. У вас есть всего три такта на ваших 204 МГц для каждого отсчета даже на постобработке.

Полное решение в студию!

В том коде что я привёл - полное доказательство.

Знающий асм для Cortex-M может это увидеть.

Не 3 такта, Слесарь хотел вообще-то 32MS/s. Берём калькулятор и считаем: 204/32 = 6.375

Но и на бОльших частотах должно хватить быстродействия.

 

PS: Для непонявших:

Приведённый код только ищет точку синхронизации (перехода через "0") сигнала.

Это самая ресурсоёмкая часть работы которую должен выполнять процессор в осциллографе.

Больше этот код ничего не делает. Остальная работа - по отображению картинки это уже ерунда по требуемой вычислительной мощности. Остальная работа тривиальна.

 

И памяти лишней требует

В LPC4370 282КБ внутреннего ОЗУ - за глаза хватит.

Скажем выберем: N=4, M=10. Тогда будем обрабатывать DMA-блоки по 20*4*10 сэмплов. И того потребуется 2 DMA-буфера по 20*4*10*2 байт. Это ни о чём при 282КБ имеющихся.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И "у меня" тоже делается. Вам код инициализации АЦП LPC4370 привести? Сами юзермануал прочитайте.

Поверю на слово - АЦП в LPC4370 может запускаться с частотой от единиц Гц до 80 МГц - подтверждаете?

 

Для тактирования АЦП LPC4370 можно использовать отдельный PLL с пачкой опциональных делителей после него - никаких таймеров не нужно.

Хоть так, хоть сяк, вам нужно ждать, пока придет весь пакет. Ждать - проверять условие. Тратить такты.

 

Какое болтание и какая разница сколько тактов будет в AdcExec_14???

В точке AdcExec_14 уже найдено, что в последних 20 сэмплах точно есть переход. А значит этот участок выполняется 1 раз на одно срабатывание синхронизатора.

И что с того, что один раз? Пока будете разбираться с этим пакетом, следующий потеряете.

 

Возьмите учебник по командам Cortex-M и разберитесь в коде.

Инкриминируете мне свои фантазии? :rolleyes: Я, не вникая в этот код, вижу его монстрообразность.

 

Этот код ищет момент перехода через "0".

В какую сторону? А в другую ищет? Вот на что намекал.

 

Какой таймер??? Вы опять за своё. Похоже что ничего не поняли.....

Вам слишком много мерещится. Когда захват останавливать будете? Надо отсчитать некое количество выборок после синхронизации. Об этом уже писал.

 

Этот код должен запускаться на каждый принятый блок сэмплов от DMA. Размер такого блока должен быть достаточно большим (там приведено условие 20*N*M

Так, конкретно, сколько было у вас? Вы рисовали на индикаторе кадр за кадром синхронизированные точно в одной выборке?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В том коде что я привёл - полное доказательство.

 

В LPC4370 внутреннего ОЗУ несколько сотен КБ - за глаза хватит.

 

Ладно, согласен.

Одобряю для применения в детском осциллограффе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

P.S. у меня STM32F303 автоматом аппаратно находит пересечение уровня (любого!). :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ладно, согласен.

Одобряю для применения в детском осциллограффе.

Конечно для детского варианта 32MS/s (и даже сколько-то больше) вполне хватит.

А о серьёзных характеристиках в сотни MS/s и не говорил никто.

 

P.S. у меня STM32F303 автоматом аппаратно находит пересечение уровня (любого!). :biggrin:

Находит где/в_чём? Во внешнем аналоговом сигнале заведённом на ногу компаратора в МК? А толку?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Находит где/в_чём? Во внешнем аналоговом сигнале заведённом на ногу компаратора в МК?

Не-а. В коде, поступающем с (внутреннего, естественно) АЦП. С точностью до LSB.

"Сами юзермануал прочитайте."

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не-а. В коде, поступающем с АЦП. С точностью до LSB.

"Сами юзермануал прочитайте."

В сэмплах в памяти МК? С помощью какой-то периферии? Я не знаком с периферией STM32F303 - не нужно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В сэмплах в памяти МК? С помощью какой-то периферии? Я не знаком с периферией STM32F303 - не нужно.

Прямо в АЦП. :rolleyes: С помощью периферии. :rolleyes: Всяк кулик хвалит свое... :laughing:

Сейчас мельком глянул в свои исходники. До 9 МВыб/с на одном АЦП получалось. При урезании разрядности. Два чередовать не получалось на высокой частоте. Сдвиг есть. Нерегулярные выборки. Причем, похоже, во всех АЦП в STM32. Когда они пишут, что можно в режиме чередования получить больше мегавыборок, это не совсем верно.

А еще у меня были развертки со случайными выборками. То есть, эквивалентную частоту дискретизации можно было получить раз в 7 больше. Для периодического сигнала, понятно. Это не рисовал, только измеренное значение сдвига между синхронизацией и выборкой наблюдал. Там уже аппаратный компаратор работал, да. Встроенный.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...