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 комментариев
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии
KIR
KIR
4 месяцев назад

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

KIR
KIR
Ответ на комментарий  Aveal
4 месяцев назад

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

KIR
KIR
Ответ на комментарий  Aveal
4 месяцев назад

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

Эдуард
Ответ на комментарий  KIR
4 месяцев назад

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

Эдуард
Ответ на комментарий  KIR
4 месяцев назад

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

KIR
KIR
Ответ на комментарий  Эдуард
4 месяцев назад

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

KIR
KIR
Ответ на комментарий  KIR
4 месяцев назад

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

Эдуард
Ответ на комментарий  KIR
4 месяцев назад

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

Эдуард
Ответ на комментарий  KIR
4 месяцев назад

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

Kir
Kir
Ответ на комментарий  Эдуард
4 месяцев назад

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

Эдуард
Ответ на комментарий  Kir
4 месяцев назад

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

Эдуард
Ответ на комментарий  Aveal
4 месяцев назад

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

17
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x