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

Как вывести многозначное число на семисегментный индикатор?

Обновлено Редакция GAW

Индикатор показывает цифры, а в программе лежит двоичное число. Перевести одно в другое значит разложить число на десятичные цифры — по сути, получить его в двоично-десятичном коде, как это делает Microchip в AN557, переводя результат АЦП в три цифры BCD.

Разложение и гашение нулей

// Common-cathode segment codes, bit order DP G F E D C B A
const uint8_t SEG[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
uint8_t digits[4];                       // digits[0] is the rightmost one

void showNumber(uint16_t n) {            // 0..9999
  for (uint8_t i = 0; i < 4; i++) {
    digits[i] = SEG[n % 10];             // lowest decimal digit
    n /= 10;
  }
  for (uint8_t i = 3; i > 0 && digits[i] == SEG[0]; i--) {
    digits[i] = 0x00;                    // blank leading zeros, keep the last digit
  }
}

Массив digits потом выводит динамическая индикация — по одному разряду за раз, как описано в статье «Семисегментный индикатор». Коды для общего анода — инверсия кодов общего катода; готовый массив для любого порядка битов сгенерирует калькулятор кодов индикатора.

ЧислоЦифры после разложенияНа индикаторе из 4 разрядов
70, 0, 0, 7 7
3050, 3, 0, 5 305 — ноль внутри числа остаётся
20262, 0, 2, 62026

MAX7219: режим Code B

У MAX7219 есть встроенный дешифратор Code B. Запись 0xFF в регистр Decode Mode (адрес 0x09) включает его для всех восьми разрядов. После этого в регистр разряда пишут саму цифру 0–9, а символы задают кодами: 0x0A — минус, 0x0F — пустой разряд, бит D7 — точка (табл. 5 даташита).

// max7219Write(address, data): your SPI helper sending one 16-bit word
max7219Write(0x09, 0xFF);                // Code B for digits 0..7
max7219Write(0x01, 5);                   // digit 0 shows "5"
max7219Write(0x04, 0x0F);                // digit 3 blank (leading zero)

Гасить ведущие нули через регистр Scan Limit Maxim прямо не советует: яркость зависит от числа сканируемых разрядов, и индикатор станет ярче при коротких числах. Остальные регистры и подключение — на странице MAX7219. Похожий принцип у CD4511: ему подают цифру четырьмя битами BCD, а сегменты он зажигает сам.

Похожие вопросы

Как вывести отрицательное число?

Отдельно запомнить знак, разложить на цифры модуль числа и в старший свободный разряд записать «минус» — у индикатора это один сегмент G. В Code B у MAX7219 для минуса есть готовый код 0x0A.

Как показать десятичную точку, например 23.5?

Хранить число в десятых — 235 — и включить точку у второго разряда справа. В коде сегментов это восьмой бит DP; у MAX7219 в любом режиме точку включает бит D7 в регистре разряда.

Не проще ли использовать sprintf?

Можно: sprintf(buf, "%4d", n) даст строку с ведущими пробелами вместо нулей, и останется перевести символы в коды. Но тогда в прошивку попадёт форматный вывод vfprintf из avr-libc, а цикл деления на 10 обходится без него.

Источники

  1. Maxim Integrated (Analog Devices). MAX7219/MAX7221 Serially Interfaced, 8-Digit LED Display Drivers (19-4452, Rev 6, 8/21) — табл. 2: адреса — No-Op 0xX0, Digit 0…7 — 0xX1…0xX8, Decode Mode 0xX9, Intensity 0xXA, Scan Limit 0xXB, Shutdown 0xXC, Display Test 0xXF; табл. 4: Decode Mode 0xFF — Code B для всех разрядов, 0x00 — без декодирования; табл. 5, Code B: 0–9, «-» 0x0A, E 0x0B, H 0x0C, L 0x0D, P 0x0E, пусто 0x0F, точка — бит D7; Scan-Limit Register: яркость зависит от числа сканируемых разрядов, поэтому регистр не следует использовать для гашения части индикатора, например ведущих нулей
  2. Microchip. AN557: Four-Channel Digital Voltmeter with Display and Keyboard (DS00557D) — результат АЦП переводится из 8-битного двоичного числа в три десятичные цифры BCD и выводится на семисегментные индикаторы; счётчик времени хранит цифры полубайтами BCD, при обновлении каждого разряда соответствующий полубайт декодируется в код сегментов

Нашли ошибку?