Embedded HandbookПриложения
Все разделы › V. Отладка и качество
STM32F103 · уровень базовый · 16 мин чтения
Открыть в интерактивном справочнике

36а. Приборы на столе: мультиметр, осциллограф, логический анализатор

Раздел 36 закончился советом «осциллограф на линию»: отладчик видит регистры, но не видит провод. Этот раздел — о самих приборах: что каждый из них умеет, где он врёт и как заметить, что врёт. Приборы обманывают не как попало, а по физике: шунт мультиметра роняет питание, земляной провод щупа звенит, узкая полоса растягивает фронт, редкая выборка теряет биты. Всё это считается заранее.

Числа раздела проверены: фронты и пороги выводов — таблицы даташита STM32F103 (пак Keil.STM32F1xx_DFP), звон и компенсация щупа — модели в ngspice, разбор записей анализатора — прогон в _verify/bench36a.

Как это называется в документации

Оригинал Перевод
DMM, digital multimeter цифровой мультиметр
burden voltage падение на токовом шунте мультиметра
probe, 1×/10× attenuation щуп; деление 1:1 / 1:10
probe compensation компенсация щупа
bandwidth полоса пропускания
sample rate частота выборки
trigger: edge, level, single запуск: по фронту, уровень, однократный
pre-trigger запись до момента запуска
logic analyzer логический анализатор
logic threshold порог логического уровня
protocol decoder разборщик протокола
CC / CV, constant current / voltage ограничение тока / стабилизация напряжения

36а.1 Мультиметр: что он умеет и о чём молчит

Мультиметр — прибор установившихся величин: несколько отсчётов в секунду, каждый — среднее за окно измерения. Этого хватает на три четверти настольных вопросов:

С током — главная ловушка. Амперметр измеряет падение на своём шунте, и шунт остаётся в цепи: на миллиамперном диапазоне это единицы ом, на микроамперном — сотни. Пока прибор спит на 5 мкА, шунт 100 Ом роняет 0,5 мВ — незаметно. Но прибор просыпается, и всплеск 30 мА на том же шунте — уже 3 В: от питания 3,3 В на приборе остаётся 0,3 В — ниже порога сброса PDR (типовые 1,88 В по таблице 11 даташита).

⚠️ Прибор перезапускается, как только мультиметр переключили на микроамперы — это не совпадение, это шунт. Прибор просыпается, шунт роняет питание, супервизор сбрасывает, потребление падает, питание возвращается — и так по кругу. Средний ток сна измеряют конденсатором рядом с прибором плюс диапазоном с малым шунтом, либо отдельным измерителем тока (раздел 101 — как это делает INA219).

Чего мультиметр не покажет совсем: короткий всплеск (окно усреднения длиннее в тысячи раз), звон и выбросы на фронтах, пульсации преобразователя. На ШИМ в режиме постоянного напряжения он покажет среднее — 1,65 В при меандре 3,3 В со скважностью 1/2 — и это правильное среднее, но о форме сигнала оно не говорит ничего. Всё, что меняется быстрее долей секунды, — к осциллографу.


36а.2 Щуп: деление, компенсация, земляной провод

Осциллограф начинается не с экрана, а со щупа. Обычный пассивный щуп имеет два положения переключателя:

1:1 1:10
сигнал на входе прибора как есть ослаблен в 10 раз
вход со стороны острия ~1 МОм и ~100 пФ кабеля ~10 МОм и 10–15 пФ
когда брать милливольтовые медленные сигналы по умолчанию — всегда

Ёмкость — главное различие. Вход самого осциллографа — 1 МОм и ~20 пФ, плюс ёмкость кабеля щупа, итого порядка сотни пикофарад. Для сравнения: ёмкость вывода F103 — 5 пФ (таблица 35 даташита). Повесить на линию 100 пФ в режиме 1:1 — значит нагрузить её сильнее, чем всё, что на ней стоит; шина I²C с подтяжкой 4,7 кОм от такой добавки заметно затянет фронты (постоянная времени — раздел 17.3). Щуп 1:10 делит сигнал резистором 9 МОм в наконечнике и подводит к линии лишь 10–15 пФ — поэтому он и есть положение по умолчанию.

Но делитель 9 МОм / 1 МОм правильно делит только постоянное напряжение. Параллельно 9 МОм в наконечнике стоит подстроечный конденсатор C1, и на фронтах делят уже ёмкости: C1 против ёмкости кабеля и входа. Пока C1 не подстроен, у делителя два разных коэффициента — по сопротивлению 1:10, по ёмкости какой получится. Модель в ngspice (_verify/bench36a/comp36a.cir: 9 МОм и C1 против 1 МОм и 100 пФ, меандр 3,3 В):

C1 фронт меандра установившееся на экране (×10)
5 пФ — недокомпенсация 0,159 В 0,329 В ступенька: фронт 1,6 В, полка 3,3 В
11,1 пФ — точно 0,330 В 0,330 В ровный меандр 3,3 В
22 пФ — перекомпенсация 0,593 В 0,333 В выброс до 5,9 В, потом полка 3,3 В

🔧 Рецепт. На передней панели осциллографа есть вывод калибратора — меандр около 1 кГц. Зацепить щуп, крутить подстроечный конденсатор до прямых углов меандра. Проверять после каждой смены щупа и канала: компенсация — свойство пары щуп-вход. Некомпенсированный щуп врёт в амплитуде на десятки процентов на любом сигнале с фронтами — таблица выше показывает разброс от 1,6 до 5,9 В на одном и том же меандре 3,3 В.

Третья деталь щупа — земляной провод. Сигнал возвращается к осциллографу по «крокодилу», а провод длиной 15 см — это индуктивность порядка 150 нГн (оценка ~1 нГн на миллиметр). Вместе с ёмкостью щупа 15 пФ она образует последовательный контур прямо на острие. Модель в ngspice (probe36a.cir, фронт 5 нс — вывод F103 в режиме 50 МГц, таблица 37 даташита):

земля щупа индуктивность что на экране
«крокодил» 15 см 150 нГн звон 105 МГц, пик 4,63 В — выброс 40 %
пружинка 1,5 см на стволе щупа 15 нГн пик 3,44 В — выброс 4 %, звона почти нет

Расчёт частоты сходится с моделью: 1/(2π·√(L·C)) = 106 МГц для 150 нГн и 15 пФ.

Щуп 1 к 10 — делитель с компенсацией и земляной провод как индуктивность; числа компенсации и звона из моделей ngspice

⚠️ Звон на экране — чей он? Укоротите землю: если частота звона сместилась (в модели — со 105 МГц к сотням мегагерц и почти в ноль по амплитуде) — звенел щуп, а не схема. Если не сместилась — звон настоящий, в самой линии (раздел 160). Про петлю земляного провода на импульсном преобразователе — раздел 58.9: там она не просто портит картинку, а перезапускает преобразователь.


36а.3 Полоса и частота выборки: какой фронт видно

Полоса пропускания осциллографа связана с самым коротким фронтом, который он способен показать, простым правилом:

t_фронта ≈ 0,35 / полоса        полоса ≈ 0,35 / t_фронта

Фронты вывода F103 известны из таблицы 37 даташита — и по ним видно, какая полоса нужна, чтобы смотреть на «просто GPIO»:

режим OSPEEDR (раздел 8) фронт полоса сигнала 0,35/tr
«2 МГц» 125 нс 2,8 МГц
«10 МГц» 25 нс 14 МГц
«50 МГц», 50 пФ 8 нс 43,75 МГц
«50 МГц», 30 пФ 5 нс 70 МГц

Прибор и сигнал складываются как корень из суммы квадратов: t² = tсигнала² + tприбора². Фронт 5 нс на разных осциллографах:

полоса прибора свой фронт прибора фронт 5 нс виден как
20 МГц 17,5 нс 18,2 нс — прибор показывает сам себя
100 МГц 3,5 нс 6,1 нс (+22 %)
350 МГц 1,0 нс 5,1 нс (+2 %)

Отсюда рабочее правило: полоса прибора — в 3–5 раз выше полосы сигнала, тогда ошибка по фронту — единицы процентов. Для линий STM32 в быстром режиме это означает «от 100 МГц», а 20-мегагерцовый прибор честно показывает только медленные режимы GPIO.

Частота выборки — второе число на шильдике, и путать его с полосой нельзя. 1 Гвыб/с на сигнале 100 МГц — 10 точек на период: форму видно. Выборка, равная полосе, дала бы одну точку на период — прибор с такими цифрами рисует красивую, но выдуманную кривую (восстановление между точками). Правило то же: выборка в несколько раз выше самой быстрой составляющей, и для одиночных событий — тем более, там усреднить повторами нельзя.


36а.4 Синхронизация: фронт, уровень, одиночный запуск

Осциллограф не «показывает сигнал» — он раз за разом ловит момент и рисует запись вокруг него. Момент задаёт синхронизация:

Пока условие попадает в один и тот же момент периода, картинка стоит. «Бегущая» картинка — сигнал несинхронен с запуском: уровень попал в шум или в звон фронта (36а.2 — звон в десятки процентов амплитуды пересекает уровень несколько раз за фронт). Уровень ставят в середину перепада, подальше от звона и от порогов логики.

Single — главный режим отладчика. Сбой раз в минуту не поймать бегущей развёрткой: ставится single с уровнем чуть выше нормального размаха — и прибор ждёт хоть час, а поймав, держит запись. Благодаря записи до момента запуска (pre-trigger) видно и что было до события — обычно интереснее всего именно это.

🔧 Рецепт: поймать редкий выброс на линии питания. Канал на питание, закрытый вход (AC), масштаб милливольты на деление, запуск normal с уровнем выше пульсаций, потом single. Утром на экране — тот единственный провал, из-за которого прибор перезагружался ночью.


36а.5 Земля осциллографа — земля розетки

«Крокодил» щупа — не отдельный провод измерения. Внутри осциллографа он соединён с корпусом, а корпус — с защитным заземлением розетки. Отсюда два следствия.

Крокодил нельзя цеплять на точку под напряжением. Подключить землю щупа к «минусу», который на самом деле не земля схемы, — значит замкнуть эту точку на розеточную землю через корпус прибора. В лучшем случае — просадка и перезагрузка, в худшем — дорожка или вход прибора.

Схема, связанная с сетью, — отдельная дисциплина. Первичная сторона импульсного источника не развязана от сети: «земля» там — выпрямленная сеть, сотни вольт относительно розеточной земли. Обычным щупом туда не ходят вовсе — это работа для развязывающего трансформатора или дифференциального щупа. И даже вторичная сторона дешёвого блока без заземляющего контакта «плавает»: делитель из двух Y-конденсаторов держит её примерно на половине сетевого — 115 В при сети 230 В. Ток крошечный (через 2,2 нФ на 50 Гц — около 79 мкА, поэтому такое питание и щиплется, а не бьёт), но в момент касания щупом весь этот потенциал разряжается в измеряемую линию.

USB добавляет ту же петлю с другой стороны: плата, запитанная от компьютера, уже соединена землёй с ним; осциллограф-приставка на том же компьютере, отладчик SWD и сетевой осциллограф связывают земли ещё раз. Кольцо земель собирает помехи и путает милливольтовые измерения. Простое правило стола: питать отлаживаемую плату от лабораторного источника (36а.8), а не от того же компьютера, где сидит анализатор.


36а.6 Логический анализатор и PulseView

Осциллограф отвечает «какой формы сигнал», логический анализатор — «что в нём сказано». Он пишет по каждому каналу только 0 и 1 относительно порога, зато каналов восемь и надолго: типичная дешёвая приставка — 8 каналов по 24 Мвыб/с, и этого хватает на UART, I²C и SPI разом. Смотрят запись в PulseView — там же живут разборщики протоколов.

Порог. Прибор сравнивает вход с фиксированным уровнем — обычно около 1,5 В. Пороги входов F103 (таблица 35 даташита): ноль — до 0,35·VDD = 1,15 В, единица — от 0,65·VDD = 2,15 В при питании 3,3 В. Порог 1,5 В лежит между ними — для 3,3-вольтовой логики годится. Для 1,8-вольтовой единица 1,8 В всего на 0,3 В выше порога — нужен прибор с настраиваемым порогом.

Частота выборки. Анализатор не осциллограф: между выборками он слеп, и вопрос «сколько выборок на бит» решает всё. Опыт (_verify/bench36a/la36a.py: посылка 4F 4B 0D 0A на 115200, разбор при 20 разных фазах выборки; второй столбец — передатчик со скоростью на 2 % выше, как позволяет себе UART от RC-генератора, раздел 16):

выборка выборок на бит точная скорость передатчик +2 %
1 Мвыб/с 8,7 20 из 20 фаз верно 20 из 20
250 квыб/с 2,2 20 из 20 16 из 20
200 квыб/с 1,7 15 из 20 5 из 20

На идеальной записи двух выборок на бит ещё хватает, но стоит скорости передатчика уехать на допустимые 2 % — разбор сыплется через раз. Отсюда правило: не меньше четырёх-пяти выборок на бит, а лучше десять. Для SPI то же самое считается мгновенно: 24 Мвыб/с на SCK 8 МГц — 3 выборки на период, уже мало.

Разборщики протоколов превращают запись в текст обмена. Та же запись I²C 100 кГц (запись 0xAF в регистр 0x00 ведомого 0x3C) после разборщика:

START
адрес 0x3C запись ACK
данные 0x00 ACK
данные 0xAF ACK
STOP

А это SPI режима 0: команда 0x9F — чтение JEDEC ID флеш-памяти (раздел 41), в ответе три байта идентификатора:

MOSI: 9F 00 00 00
MISO: 00 EF 40 18

Видно то, чего не даёт отладчик: обе стороны обмена и время между ними. NACK вместо ACK — ведомый не ответил (адрес? подтяжки? — раздел 17); байты в MISO сдвинуты на такт — фаза CPHA (раздел 18); пауза в миллисекунду между байтами UART — кто-то держит процессор.

Бит UART и выборки анализатора: восемь выборок на бит читают посылку надёжно, меньше двух — теряют биты


36а.7 Вывод-метка в коде: время участка и дрожание

Приборы смотрят не только на интерфейсы. Один свободный вывод превращает осциллограф в измеритель времени внутри прошивки — это та самая первая строка таблицы «чем измерять» из раздела 73.1:

void mark_init(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;         /* такт порта A */
    GPIOA->CRH = (GPIOA->CRH & ~(GPIO_CRH_CNF8 | GPIO_CRH_MODE8))
               | GPIO_CRH_MODE8;                /* PA8: выход push-pull, 50 МГц */
}

static inline void mark_up(void)   { GPIOA->BSRR = GPIO_BSRR_BS8; }
static inline void mark_down(void) { GPIOA->BSRR = GPIO_BSRR_BR8; }

Вокруг измеряемого участка:

uint32_t measured(uint32_t x)
{
    mark_up();                                  /* фронт вверх — старт */
    x = work(x);
    mark_down();                                /* фронт вниз — конец */
    return x;
}

Ширина импульса на экране — время участка. Записи в BSRR почти ничего не стоят (раздел 73.1), измерение не искажает измеряемое — в отличие от точки останова, которая останавливает всё (раздел 35).

Два приёма сверх простого замера:

Тот же замер без осциллографа — счётчиком тактов через SWO — собран в рецепте 21.9.


36а.8 Лабораторный источник с ограничением тока

Последний прибор — не измерительный, но именно он чаще всего спасает плату. Лабораторный источник держит либо заданное напряжение (режим CV), либо, когда нагрузка требует больше выставленного тока, — заданный ток (режим CC), просаживая напряжение. Переход в CC — это и защита, и индикатор.

🔧 Рецепт первого включения. Напряжение 3,3 В, ограничение тока — чуть выше ожидаемого потребления: для платы, которая должна есть 30 мА, — 50 мА. Короткое замыкание или перевёрнутая деталь не горят: источник уходит в CC, на индикаторе вместо 3,3 В — просевшее напряжение, и это видно раньше запаха. Работает — поднять ограничение до рабочего с запасом.

Показания тока на источнике — второй мультиметр, всегда включённый в питание: потребление платы видно постоянно, без шунта в разрыве. Скачок тока после прошивки новой версии — повод искать, что перестало засыпать (раздел 10), рост на десятки миллиампер — что включилось лишнее.

USB-порт компьютера всем этим не обладает: ток он ограничивает поздно и грубо, потребление не показывает, а землю связывает с компьютером (36а.5). Питание со стола — от источника; USB — для того, что отлаживается по USB.


36а.9 Грабли

Звон ~100 МГц на каждом фронте. Сначала укоротить землю щупа (36а.2): сместился — звенел щуп. Пятнадцать сантиметров «крокодила» — 150 нГн и выброс 40 % на ровном фронте. На импульсном преобразователе петля земляного провода добавляет своё — раздел 58.9.

Меандр калибратора со ступенькой или выбросом. Щуп не скомпенсирован: амплитуды врут на десятки процентов — от 1,6 до 5,9 В на меандре 3,3 В в модели 36а.2. Компенсация — свойство пары щуп-вход: проверять после каждой перестановки.

Все фронты «18 нс». Полоса 20 МГц: свой фронт прибора 17,5 нс, и быстрее он не покажет ничего (36а.3). Прибор показывает сам себя.

Мультиметр на микроамперах — прибор перезапускается. Шунт роняет питание на всплеске потребления: 30 мА на 100 Ом — минус 3 В (36а.1).

Анализатор читает мусор вместо UART. Мало выборок на бит или скорость передатчика уехала: 1,7 выборки на бит с ошибкой скорости 2 % — верен один разбор из четырёх (36а.6). Выборку — от четырёх на бит, скорость — сверить.

«Минус» под напряжением встретился с крокодилом. Просадка, перезагрузка, в худшем случае — сгоревшая дорожка или вход прибора: земля щупа соединена с розеточной (36а.5). На схемах, связанных с сетью, — только развязка или дифференциальный щуп.

Плата ест ноль — и не работает. Ограничение тока источника осталось на 20 мА с первого включения: источник в CC, напряжение просело, прибор в цикле сброса. Взгляд на индикатор CC — раньше всех осциллографов (36а.8).


36а.10 Итоги

Полные исходники

tag36a.c — вывод-метка вокруг измеряемого участка кода.

/* 36а.7: вывод-метка вокруг измеряемого участка кода (F103, PA8).
 * Сборка: armclang --target=arm-arm-none-eabi -mcpu=cortex-m3 -DSTM32F10X_MD
 *         -include stm32f10x.h -O2 -Wall -Wextra -c tag36a.c
 */

void mark_init(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;         /* такт порта A */
    GPIOA->CRH = (GPIOA->CRH & ~(GPIO_CRH_CNF8 | GPIO_CRH_MODE8))
               | GPIO_CRH_MODE8;                /* PA8: выход push-pull, 50 МГц */
}

static inline void mark_up(void)   { GPIOA->BSRR = GPIO_BSRR_BS8; }
static inline void mark_down(void) { GPIOA->BSRR = GPIO_BSRR_BR8; }

uint32_t work(uint32_t x);                      /* измеряемый участок */

uint32_t measured(uint32_t x)
{
    mark_up();                                  /* фронт вверх — старт */
    x = work(x);
    mark_down();                                /* фронт вниз — конец */
    return x;
}

Дальше: раздел 36б «Самопроверка во время работы: ядро, ОЗУ, флеш, частота» — прибор сам проверяет ядро, ОЗУ, флеш-память и частоту, без человека рядом.

Открыть в интерактивном справочнике