Top.Mail.Ru

STM32 и семисегментный индикатор. Динамическая индикация.

Всех снова приветствую, и сегодня будет еще одна статья из цикла "по запросам трудящихся" 👍 Из названия статьи и превью уже понятно, что разговор пойдет о подключении и работе с семисегментными индикаторами. Собственно, вопросы касаются в большей степени программных аспектов, поэтому во второй части прямо по ходу написания текста статьи я реализую свой вариант библиотеки для работы с упомянутыми 7-сегментными индикаторами. Но начинаем, по устоявшейся традиции, с базовых теоретических сведений.

Принцип работы семисегментного индикатора.

Что в целом из себя представляет 7-сегментный индикатор? Идея тут проста – просто упорядоченный набор светодиодов. Причем упорядоченность касается их физического расположения друг относительно друга:

Устройство семисегментного индикатора.

Каждый из светодиодов представляет из себя отдельный сегмент, соответственно, имеем как раз 7 сегментов. При этом каждому сегменту ставится в соответствие условное буквенное обозначение – a, b, c и т. д. Поместим все это в пластиковый корпус и, наклеив наклейку, получаем законченный компонент:

7-сегментный индикатор.

Включая определенный набор диодов, можем получить наглядное отображение информации, к примеру, в виде цифры 7:

Принцип работы семисегментного индикатора.

Аналогичным образом и для любой другой цифры:

Отображение цифр.

Или для любого символа, варианты ограничены только количеством сегментов, конкретной целью и фантазией:

Произвольный символ.

Помимо этих семи сегментов почти всегда присутствует еще один, отвечающий за отображение точки:

Семисегментный индикатор.

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

Четырехразрядный индикатор.

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

Подключение семисегментного индикатора.

Электрически данная концепция реализуется также максимально просто: одним из выводов все светодиоды соединяются в одной точке, вторые же подключаются отдельно. Что в совокупности дает нам два варианта, с общим анодом:

Семисегментный индикатор с общим анодом.

И с общим катодом:

7-сегментный индикатор с общим катодом.

Управление тогда будет выглядеть следующим образом, для общего анода:

  • подаем на общий вывод (аноды) положительное напряжение
  • катоды же нужных сегментов заземляем

Для общего катода то же самое, за исключением полярности:

  • подаем на общий вывод (катоды) 0 В
  • а на аноды сегментов положительное значение напряжения

Естественно, нужно учесть параметры конкретных диодов в конкретном же используемом индикаторе. Допустим, из документации узнаем, что прямой ток диодов – 20 мА при напряжении на диоде 2 В. При осуществлении управления напрямую с вывода микроконтроллера, например STM32, напряжение будет составлять 3.3 В, что очевидно не равно требуемым 2 В. Поэтому в цепь добавляется резистор:

Подключение к микроконтроллеру.

И номинал его рассчитывается следующим образом. Напряжение на диоде должно быть равно 2 В, с порта контроллера имеем 3.3 В, значит избыточные 1.3 В должны упасть именно на резисторе.

При этом ток через диод, а вместе с ним и ток через резистор, составит 20 мА. Поэтому по закону Ома спокойно рассчитываем необходимое значение сопротивления:

R = \frac{U_R}{I_R} = \frac{1.3 \medspace В}{20 \medspace мА} = 65 \medspace Ом

На этом расчетная деятельность закончена.

Кроме того, при необходимости, управление может осуществляться, как вариант, через транзисторные ключи. Собственно, все это не влияет на идею, которая заключается в том, что зажигание диода производится подачей положительного напряжения между его анодом и катодом.

Динамическая индикация.

Постепенно начинаем перемещаться к практическим нюансам. И первым, что приходит на ум, является тот факт, что для управления одним разрядом потребуется целых девять выводов микроконтроллера. Будем для наглядности рассматривать схему с общим катодом, никаких ограничений это не накладывает. Тогда получаем эти самые девять требуемых сигналов:

  • катод диодов – 1 штука
  • сегменты для отображения цифры/символа – 7 штук
  • сегмент десятичной точки – 1 штука

Нехитрые манипуляции в виде суммирования дают именно девять сигналов для полноценного управления. И это только для одного разряда. Если разрядов будет 4, то это уже 36 выводов микроконтроллера, что, мягко говоря, чуть больше, чем очень много.

Решение же данной проблемы заключается в использовании динамической индикации. Принцип заключается в том, что в каждый момент времени светится только одна цифра. Допустим, нам нужно вывести на индикатор число "1971", действуем так:

  • Зажигаем "1" на месте первого разряда.
  • Ожидаем некоторое время, пусть 1 миллисекунду. В этом временном интервале у нас горит "1", остальные же три разряда выключены полностью.
  • Гасим "1" в первом разряде и зажигаем "9" на второй позиции.
  • Снова ожидаем в таком состоянии миллисекунду.
  • Повторяем аналогичные действия для оставшихся цифр "7" и "1".

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

Динамическая индикация.

И теперь нам требуется не 36, а только 12 выводов для управления 4-х разрядным индикатором. Рассмотрим более подробно на конкретном примере такого индикатора:

Вариант семисегментного индикатора.

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

Распиновка семисегментного индикатора.

Здесь у нас вариант с общим анодом. Суммарно этот семисегментный индикатор содержит в себе 4 разряда, по 8 сегментов каждый (7 + 1 для точки) и 12 выводов для управления всем хозяйством. Восемь сегментов каждого из разрядов соединены анодами и каждый из них, в свою очередь, выведен на выходной разъем. В данном случае это пины с номерами 12, 9, 8 и 6. Сегменты же разных разрядов соединены катодами между собой. Так точка 1-го разряда, соединена с точками 2-го, 3-го и 4-го разрядов, и этот сигнал выходит на 3-й контакт разъема:

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

  • Подаем на 12-й вывод положительное напряжение, 9-й, 8-й, 6-й заземляем. Таким образом, мы "активируем" только первый разряд.
  • Для того, чтобы зажечь единицу нужно подать на катоды диодов b и c 0 В (выводы 7 и 4). На остальные же катоды подаем то же напряжение, что и на анод. В итоге гореть будут только светодиоды b и c первого разряда.
  • Ожидаем некоторое непродолжительное время.
  • Далее наша задача вывести "9" на второй позиции, потушив все остальные разряды. Для этого по той же схеме – подаем на 9-й вывод положительное напряжение, 12-й, 8-й, 6-й заземляем.
  • Теперь у нас "активирован" второй разряд и только он.
  • Для отображения "9" подаем на катоды диодов a, b, c, d, f, g - 0 В, на катод диода e – то же напряжение, что и на его анод, дабы он оставался в покое.
  • Все, в дальнейшем те же действия для 3-го и 4-го разрядов и все это повторяем циклично. Результатом будет отображение нужного числа.

В итоге, управление осуществляется 12-ю выводами микроконтроллера, что тоже немало, но, как минимум, меньше 36-ти. Есть, конечно же, в продаже и 7-сегментные индикаторы, в которых на разъем выведены все 36 сигналов, соответственно, они не закорочены между собой внутри. Вот, например:

36-выводный индикатор.

Поэтому при выборе следует исходить, в первую очередь, из конкретной задачи и требований. Более наглядно мы все описанное увидим в программной части статьи, к которой и переходим.

Работа с 7-сегментным индикатором на STM32.

Я набросал по-быстрому библиотеку для работы с семисегментными индикаторами для STM32, разберем, как ее конфигурировать и использовать.

Первый делом, настроим необходимую периферию, что в данном случае заключается исключительно в инициализации портов GPIO. У меня под рукой оказался следующий индикатор:

Библиотека для STM32.

То есть именно такой, который мы среди прочих рассматривали в первой части статьи. Соответственно, необходимо 12 портов ввода-вывода, так и подключаем:

Подключение семисегментного индикатора к STM32.

Какие именно брать порты роли никакой не играет, настраиваем просто в качестве обычных выходов:

STM32CubeMx.

С этим все понятно, генерируем код и добавляем в проект файлы библиотеки:

  • segment_lcd.c
  • segment_lcd.h

Вся связь с HAL сосредоточена только в одном месте, а именно в функции:

static void SetOutput(McuPin output, uint8_t state)
{
  HAL_GPIO_WritePin(output.port, output.pin, (GPIO_PinState)state);
}

Таким образом, максимально просто можно перейти и к варианту без HAL. Функции, которые я реализовал для использования вне драйвера:

  • SEG_LCD_Process();
  • SEG_LCD_Result SEG_LCD_WriteNumber(float number);
  • SEG_LCD_Result SEG_LCD_WriteString(char* str);

В целом, их назначение ясно из их же названия, тем не менее на примере посмотрим более подробно. Вторая и третья из перечисленных возвращают результат выполнения операции, и здесь два варианта:

  • SEG_LCD_OK
  • SEG_LCD_ERROR

О том, как я построил работу с экраном, я досконально рассказывать не буду. В случае возникновения вопросов, буду рад пояснить любые нюансы в комментариях или на форуме 👍

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

static McuPin digitPins[DIGITS_NUM] = { {GPIOB, GPIO_PIN_3}, {GPIOB, GPIO_PIN_4},
                                        {GPIOB, GPIO_PIN_5}, {GPIOB, GPIO_PIN_6} };

static McuPin segmentPins[SEGMENTS_NUM] = { {GPIOA, GPIO_PIN_11}, {GPIOA, GPIO_PIN_10},
                                            {GPIOA, GPIO_PIN_9}, {GPIOA, GPIO_PIN_8},
                                            {GPIOB, GPIO_PIN_15}, {GPIOB, GPIO_PIN_14},
                                            {GPIOB, GPIO_PIN_13} };

static McuPin dotPin = {GPIOB, GPIO_PIN_12};

Как видите, я задал все как на схеме выше. DIGITS_NUM определяет количество разрядов, у меня:

#define DIGITS_NUM                                                          4

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

static uint8_t charactersTable[DIGIT_CHARACTERS_NUM + EXTRA_CHARACTERS_NUM] =
               {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x40, 0x00};

Каждый символ - один байт, 7 младших битов которого определяют, должен ли гореть конкретный сегмент. Первые 10 элементов массива - это цифры от 0 до 9, именно в такой последовательности, за ними же следуют дополнительные символы, список которых можно пополнить своими. Рассматриваем на примере, возьмем, третий элемент массива, то есть цифру 2, значение равно 0x5B, либо в двоичном виде 0b01011011.

Старший бит всегда нулевой, потому что сегментов 7, а битов 8, ничего неожиданного. Последующие же биты (от 6-го до 0-го) задают состояние сегментов (от g до a). Итак, цифра 2:

Пример кодирования сегментов.

Должны гореть сегменты a, b, d, e, g, что и кодируется этими битами. С этим разобрались, теперь дополнительные символы. Я добавил пробел и минус, то есть два символа, это количество задано в segment_lcd.h:

#define EXTRA_CHARACTERS_NUM                                                2

Далее их ASCII коды:

#define ASCII_MINUS_CODE                                                    0x2D
#define ASCII_SPACE_CODE                                                    0x20

В хэдере на этом все пока, идем обратно в segment_lcd.c и находим массив дополнительных символов:

static SEG_LCD_ExtraCharacter extraCharacters[EXTRA_CHARACTERS_NUM] = { {ASCII_MINUS_CODE, DIGIT_CHARACTERS_NUM},
                                                                        {ASCII_SPACE_CODE, DIGIT_CHARACTERS_NUM + 1} };

Первое поле структуры задает ASCII код, второе - позицию символа в массиве кодов charactersTable[]. DIGIT_CHARACTERS_NUM - число цифр, то есть 10. Таким образом, в данном случае имеем символ минуса (ASCII_MINUS_CODE) и его позицию: DIGIT_CHARACTERS_NUM (10). Смотрим на 10-й элемент массива, а там у нас значение 0x40:

static uint8_t charactersTable[DIGIT_CHARACTERS_NUM + EXTRA_CHARACTERS_NUM] =
               {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x40, 0x00};

И снова иллюстрация:

Добавление произвольного символа.

Все четко, получаем символ минуса!

Упустил из виду "полярность" управления сегментами. Итак, у нас либо общий анод, либо общий катод, задается тут, для общего анода:

#define SEGMENT_PIN_ACTIVE                                                  0

Для общего катода:

#define SEGMENT_PIN_ACTIVE                                                  1

Ну и, пожалуй, конфигурация завершена на этом, суммарно вышло три этапа:

  • задаем порты - обязательный этап
  • добавляем дополнительные символы - в случае необходимости, на свой вкус, в зависимости от задачи
  • задаем тип подключения 7-сегментного индикатора, общий анод или общий катод - обязательный этап

Для функционирования библиотеки достаточно добавить периодический вызов SEG_LCD_Process(). В этой функции в том числе осуществляется переключение разрядов для динамической индикации, поэтому между вызовами следует сделать небольшую задержку:

while (1)
{
	/* USER CODE END WHILE */

	/* USER CODE BEGIN 3 */
	SEG_LCD_Process();
	HAL_Delay(1);
}
/* USER CODE END 3 */

Если паузу сделать слишком большой, то соответственно, будет видно, что цифры загораются по очереди, а не горят постоянно. И финишируем небольшим демо-проектом, в котором будем менять значение переменной от -10 до 10 с шагом 0.01, производя инкрементирование каждые 10 мс. Результат прокинем на индикатор. Все манипуляции теперь только в main.c, подключаем библиотеку для семисегментных индикаторов:

/* USER CODE BEGIN Includes */
#include "segment_lcd.h"

/* USER CODE END Includes */

Объявляем переменные:

/* USER CODE BEGIN PV */
float outputValue = -10;
float outputStep = 0.01;
float outputLimit = 10;
uint32_t outputPeriod = 10;

/* USER CODE END PV */

Ну и решение поставленной задачи:

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  uint32_t previousTime = HAL_GetTick();
  uint32_t currentTime = HAL_GetTick();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    SEG_LCD_Process();
    HAL_Delay(1);

    currentTime = HAL_GetTick();
    if ((currentTime - previousTime) >= outputPeriod)
    {
      outputValue += outputStep;

      if (outputValue >= outputLimit)
      {
        outputValue = (-1) * outputLimit;
      }

      SEG_LCD_WriteNumber(outputValue);
      previousTime = currentTime;
    }
  }
  /* USER CODE END 3 */
}

Вся суть в двух функциях:

  • SEG_LCD_Process()
  • SEG_LCD_WriteNumber(outputValue)

Результат работы программы таков:

И на этом заканчиваем на сегодня, библиотека писалась быстро и на коленке, параллельно с процессом написания текста статьи, так что если что пишите )

Исходный код файлов библиотеки:

/**
  ******************************************************************************
  * @file           : segment_lcd.c
  * @brief          : 7-segment LCD driver.
  * @author         : MicroTechnics (microtechnics.ru)
  ******************************************************************************
  */



/* Includes ------------------------------------------------------------------*/

#include "segment_lcd.h"
#include <stdio.h>



/* Declarations and definitions ----------------------------------------------*/

static McuPin digitPins[DIGITS_NUM] = { {GPIOB, GPIO_PIN_3}, {GPIOB, GPIO_PIN_4},
                                        {GPIOB, GPIO_PIN_5}, {GPIOB, GPIO_PIN_6} };

static McuPin segmentPins[SEGMENTS_NUM] = { {GPIOA, GPIO_PIN_11}, {GPIOA, GPIO_PIN_10},
                                            {GPIOA, GPIO_PIN_9}, {GPIOA, GPIO_PIN_8},
                                            {GPIOB, GPIO_PIN_15}, {GPIOB, GPIO_PIN_14},
                                            {GPIOB, GPIO_PIN_13} };

static McuPin dotPin = {GPIOB, GPIO_PIN_12};

static uint8_t charactersTable[DIGIT_CHARACTERS_NUM + EXTRA_CHARACTERS_NUM] =
               {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x40, 0x00};

static SEG_LCD_ExtraCharacter extraCharacters[EXTRA_CHARACTERS_NUM] = { {ASCII_MINUS_CODE, DIGIT_CHARACTERS_NUM},
                                                                        {ASCII_SPACE_CODE, DIGIT_CHARACTERS_NUM + 1} };

static uint8_t currentCharacters[DIGITS_NUM] = {0x00, 0x00, 0x00, 0x00};
static uint8_t currentDots[DIGITS_NUM] = {0, 0, 0, 0};
static uint8_t currentDigitIndex = 0;




/* Functions -----------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
SEG_LCD_Result SEG_LCD_WriteString(char* str)
{
  uint8_t currentDigitIndex = 0;

  for (uint8_t i = 0; i < DIGITS_NUM; i++)
  {
    currentCharacters[i] = 0x00;
    currentDots[i] = 0;
  }

  while(*str != '\0')
  {
    if (*str == ASCII_DOT_CODE)
    {
      if (currentDigitIndex > 0)
      {
        currentDots[currentDigitIndex - 1] = 1;
      }
    }
    else
    {
      if ((*str >= ASCII_NUMBER_FIRST_CODE) && (*str <= ASCII_NUMBER_LAST_CODE))
      {
        uint8_t currentCharacterIndex = (*str - ASCII_NUMBER_FIRST_CODE);
        currentCharacters[currentDigitIndex] = charactersTable[currentCharacterIndex];
        currentDigitIndex++;
      }
      else
      {
        uint8_t found = 0;

        for (uint8_t i = 0; i < EXTRA_CHARACTERS_NUM; i++)
        {
          if (*str == extraCharacters[i].asciiCode)
          {
            uint8_t currentCharacterIndex = extraCharacters[i].symbolsTableOffset;
            currentCharacters[currentDigitIndex] = charactersTable[currentCharacterIndex];
            found = 1;
            currentDigitIndex++;
            break;
          }
        }

        if (found == 0)
        {
          return SEG_LCD_ERROR;
        }
      }
    }

    if (currentDigitIndex == DIGITS_NUM)
    {
      break;
    }

    str++;
  }

  if (currentDigitIndex < DIGITS_NUM)
  {
    for (int8_t i = currentDigitIndex - 1; i >= 0; i--)
    {
      currentCharacters[i + (DIGITS_NUM - currentDigitIndex)] = currentCharacters[i];
      currentDots[i + (DIGITS_NUM - currentDigitIndex)] = currentDots[i];
    }

    for (uint8_t i = 0; i < (DIGITS_NUM - currentDigitIndex); i++)
    {
      currentCharacters[i] = 0x00;
      currentDots[i] = 0;
    }
  }

  return SEG_LCD_OK;
}



/*----------------------------------------------------------------------------*/
SEG_LCD_Result SEG_LCD_WriteNumber(float number)
{
  char temp[DIGITS_NUM + 2];
  snprintf(temp, DIGITS_NUM + 2, "%.2f", number);
  SEG_LCD_WriteString(temp);
  
  return SEG_LCD_OK;
}



/*----------------------------------------------------------------------------*/
static void SetOutput(McuPin output, uint8_t state)
{
  HAL_GPIO_WritePin(output.port, output.pin, (GPIO_PinState)state);
}



/*----------------------------------------------------------------------------*/
static void SetSegmentPins(uint8_t characterCode)
{
  for (uint8_t i = 0; i < SEGMENTS_NUM; i++)
  {
    uint8_t bit = (characterCode >> i) & 0x01;

    if (bit == 1)
    {
      SetOutput(segmentPins[i], SEGMENT_PIN_ACTIVE);
    }
    else
    {
      SetOutput(segmentPins[i], !SEGMENT_PIN_ACTIVE);
    }
  }
}



/*----------------------------------------------------------------------------*/
void SEG_LCD_Process()
{
  for (uint8_t i = 0; i < DIGITS_NUM; i++)
  {
    SetOutput(digitPins[i], !DIGIT_PIN_ACTIVE);
  }

  SetSegmentPins(currentCharacters[currentDigitIndex]);

  if (currentDots[currentDigitIndex] == 1)
  {
    SetOutput(dotPin, SEGMENT_PIN_ACTIVE);
  }
  else
  {
    SetOutput(dotPin, !SEGMENT_PIN_ACTIVE);
  }

  SetOutput(digitPins[currentDigitIndex], DIGIT_PIN_ACTIVE);

  currentDigitIndex++;
  if (currentDigitIndex == DIGITS_NUM)
  {
    currentDigitIndex = 0;
  }
}



/*----------------------------------------------------------------------------*/
/**
  ******************************************************************************
  * @file           : segment_lcd.h
  * @brief          : 7-segment LCD driver.
  * @author         : MicroTechnics (microtechnics.ru)
  ******************************************************************************
  */

#ifndef SEG_LCD_H
#define SEG_LCD_H



/* Includes ------------------------------------------------------------------*/

#include "stm32f1xx_hal.h"



/* Declarations and definitions ----------------------------------------------*/

#define DIGITS_NUM                                                          4
#define SEGMENTS_NUM                                                        7

#define SEGMENT_PIN_ACTIVE                                                  0
#define DIGIT_PIN_ACTIVE                                                    !SEGMENT_PIN_ACTIVE

#define DIGIT_CHARACTERS_NUM                                                10
#define EXTRA_CHARACTERS_NUM                                                2

#define ASCII_NUMBER_FIRST_CODE                                             0x30
#define ASCII_NUMBER_LAST_CODE                                              0x39

#define ASCII_MINUS_CODE                                                    0x2D
#define ASCII_SPACE_CODE                                                    0x20

#define ASCII_DOT_CODE                                                      0x2E



typedef enum {
  SEG_LCD_OK,
  SEG_LCD_ERROR
} SEG_LCD_Result;



typedef struct SEG_LCD_ExtraCharacter
{
  uint8_t asciiCode;
  uint8_t symbolsTableOffset;
} SEG_LCD_ExtraCharacter;



typedef struct McuPin
{
  GPIO_TypeDef *port;
  uint16_t pin;
} McuPin;



/* Functions -----------------------------------------------------------------*/

extern void SEG_LCD_Process();
extern SEG_LCD_Result SEG_LCD_WriteNumber(float number);
extern SEG_LCD_Result SEG_LCD_WriteString(char* str);




#endif // #ifndef SEG_LCD_H

Ссылка на проект: MT_SegmentLCD_Project.

Подписаться
Уведомление о
guest
17 комментариев
старее
новее
Inline Feedbacks
View all comments
KIR
KIR
24 дней назад

Очень недурственно описана теория. Однако есть что добавить. Иногда при подключении идикатора к МК резисторы вешают на общий анод (либо общий катод), (например с целью экономии места, а не на раздельные выводы сегментов а...f. В таком случаи следует при динамической индикации подавать последовательно сигналы на закороченные ножки а...f всех сегментов, а зажиганием управлять через общий анод(ну или катод) какой то из цифр... Насколько понимаю в библиотеке такое не реализовано )).

KIR
KIR
Reply to  Aveal
23 дней назад

Переключений там всего вдвое больше. Не будет, если все правильно организовать.

KIR
KIR
Reply to  Aveal
23 дней назад

Никаких проблем в этом нет, все одно частота обновления получается на порядки выше чем глаз может увидеть. Не так давно писал софт для паяльника, где как раз семисегментник стоял с 4 резисторами всего на анодах индикатора... Там вообще шла борьба серьезная с размером платы, чтобы в ручку паяльника влезла...

Эдуард
Reply to  KIR
11 дней назад

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

Эдуард
Reply to  KIR
11 дней назад

Идиотское решение.
Если зажигать 1 ток будет Х
Если зажигать 8 ток будет 4Х.
Яркость 8ки будет меньше яркости 1 в четыре раза.
А резистор один. Управлять придётся каждым сегментом отдельно. Это увеличивает частоту сканирования в 9 раз и возникают ударные токи на светодиодах. Разве только делать отсечку перед пробоем светодиода. Это усложняет програмный код многократно.
А уменьшить размер можно уменьшением размера деталей.
Резисторы 0402 и будет счастье.

KIR
KIR
Reply to  Эдуард
11 дней назад

Эдуард, во-первых, после ваших статей я о Вас лучше думал. По меньшей мере ожидал, что на личности (см выше) вы переходить не будете, а вы снизошли до прямых оскорблений. Ну и банально своим прозорливым умом попытаетесь вникнуть в глубину идеи )) Во-вторых, суть предложенного и РЕАЛИЗОВАННОГО как раз в том, что зажигается все посегментно на каждой цифре, те ток не падает независимо от отображения. Частота не сканирования, а таки обновления, действительно при прочих равных меняется. В случае если используется 4 цифры (а в паяльнике софт для которого я писал это именно так) при алгоритме выше надо зажигать 4 раза по 8 сегментов каждой цифры, в том что использовал я - 8 раз по одному сегменту всех4 цифр. Только и всего. Это работает и не имеет никакого отношения ни к "маяться дурью" ни к затратам на "покупку новогооборудования" ни к уменьшению размера деталей, кстати они там 0201...

KIR
KIR
Reply to  KIR
11 дней назад

Кстати код тоже не слишком сложный, читай практически такой же сложности

Эдуард
Reply to  KIR
9 дней назад

А нельзя как то связаться, что бы обсудить этот метод, я могу объяснить, что мне в нём не нравится.

Эдуард
Reply to  KIR
10 дней назад

Прошу прощения, что обидел.
Просто последнее время развелось много таких, что прибегут, понапишут всякого, а когда попросишь показать на пальцах куда то исчезают.
Но этот метод держит светодиоды на грани фола. И его лучше не применять. И если кто то так делает, это не значит, что нужно следовать его примеру.

Kir
Kir
Reply to  Эдуард
5 дней назад

Ну вы бы коротенечко написали в чем видется проблема... Как по мне просто решение задачи другим способом... Я кстати все время за нестандартные решения огребал )) Помню даже 4 по физике на вступительных в институт было чисто за это )))

Эдуард
Reply to  Kir
4 дней назад

Там писанины много.

Эдуард
Reply to  Aveal
10 дней назад

Устал я. Срываюсь.
Думал очередной загибатель пальцев.

17
0
Would love your thoughts, please comment.x
()
x