Семисегментный LED-индикатор. Эффекты анимации

Обсуждаем контроллеры компании Atmel.
BlackKilkennyCat
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BlackKilkennyCat »

Так зачем тогда отвечать, раз параллельно? И параллельно - это что-то из геометрии вроде, причём тут мнение?
Реклама
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Dimon456 »

Demiurg, код хороший, просто отличный, только не подумайте плохого, я у себя в папочке сохранил, на будущее.
Но что бы его прочитать, как вы там где-то выразились, "нечитаемый код", потребуется компилятор типа eclipse CoIDE, ни знаю, может еще какой, который умеет строить зависимость (ни знаю как правильно назвать).
К сожалению IAR(не помню, по моему он не умеет, я его всего раз ставил, только отладчик там просто отличный), Авр студия, cvavr, winavr, Keil, notepad не умеют строить эту зависимость.
Реклама
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

[uquote="BlackKilkennyCat",url="/forum/viewtopic.php?p=3882550#p3882550"]...[/uquote]
Мне действительно параллельно. Но я решил пойти дальше. Захотел услышать конструктив. Полезный мне и другим участникам форума.

Добавлено after 2 minutes 40 seconds:
Dimon456 я по моему вам уже писал. Сишные проекты я пишу только в IAR. В студии очень редко и самые примитивные проекты, где не требуется работа с Flash и EEPROM.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Reflector »

[uquote="Demiurg",url="/forum/viewtopic.php?p=3882476#p3882476"]В качестве примера.[/uquote]
Хотя семисегментники не очень люблю, набросал сейчас простенький класс на C++, сравни хотя бы чисто по объему :)
Спойлер

Код: Выделить всё

template<Pins digits, Pins segs, bool CommonCatode = true>
class Semiseg
{
public:
	static void init()
	{
		PinList<segs, digits>::template mode<PinMode::PushPull>();
	}

	static void write(uint32_t digit, uint32_t value)
	{
		if constexpr (CommonCatode)
		{
			digits::write(~(1 << digit));
			segs::write(comCatodeTbl[value]);
		}
		else
		{
			digits::write(1 << digit);
			segs::write(comAnodeTbl[value]);
		}
	}
	
private:
	static constexpr uint8_t comAnodeTbl[16]  = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E };   // 0..F
	static constexpr uint8_t comCatodeTbl[16] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71 };
};
Тогда простейшую динамическую индикацию можно реализовать следующим образом:
Спойлер

Код: Выделить всё

using segs = PinList<PC2, PC3, PB4, PB6, PB8, PA1, PD9>;
using digits = PinList<PB9, PC13, PC12>;
Semiseg<digits, segs, false> semiseg;

semiseg.init();

uint32_t value = 150, cnt = 0;

while (true)
{
	uint32_t digit = cnt++ % 3;
	semiseg.write(2 - digit, value / Math::pow(10, digit) % 10);
	delay_ms(1);
	if(!(cnt % 1000)) value++;
}
Это без нескольких строк вся программа, нужно еще порты включить(на AVR не нужно) и таймер для паузы настроить...
Реклама
Эиком - электронные компоненты и радиодетали
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Не впечатлен.
Краткость не всегда полезна. Прежде чем плеваться на мой пример, изучите его как следует.
В файле *.h у меня прописано все. Если мне нужно изменить что либо, это делается в одном месте, а не по всей программе. Дефайном у меня определено какая логика вывода. Какой активный уровень. Идём дальше, в программе я пишу, print_buf (2, "ERROR"), где 2 это знакоместо. Также я могу в одном месте переназначить на любой пин мк. Отсюда массив функций.
Повторяю. Краткость не всегда полезна. И прежде чем плеваться, посмотрите, по какой причине написано именно так.
И самое главное, комплекс принятых мер позволяет мне реализовать динамическую индикацию в основном цикле. Надеюсь, мне вам не нужно писать, что обработчики прерываний должны быть максимально короткими и быстрыми. При этом нет никакого мигания, мерцания индикаторов. Что зачастую неизбежно, так как при обычной реализации при выполнении основного цикла времянки гуляют.
Реклама
BlackKilkennyCat
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BlackKilkennyCat »

Да нет никаких причин. Куча лишних вызовов. Впечатление, что про параметры вообще неизвестно. Лишний вызов - лишние ресурсы. Мигания, мерцания и проч. нет и без такого количества буков. Задача на уровне детского садика, а затрачено ресурсов охрененно неоправданное количество, да и функция, где всего лишь один вызов другой функции - это просто переименовать функцию.

Код Reflectorа - это максимум, чего должно быть.

Вариант с загоном в сдвиговый регистр. Без этого было б ещё короче.

Код: Выделить всё

#include <io7foxFxKx.h>
#include <stdlib.h>

unsigned char const led_table[] = {0x06,0x9f,0xa2,0x92,0x1b,0x52,0x42,0x9e,0x02,0x12};
unsigned char dot = 0x00;
unsigned char const dig_n[] = {0xf7,0xfd,0xfb,0xfe};
unsigned char x;

void d(unsigned char c)
{
	for (x = 0; x < 8; x++)
	{
		PADR &= 0xFB;//clck 0		
		if (c & 0x01) PADR |= 0x02;	else PADR &= 0xFD;
		c >>= 1;
		PADR |= 0x04;//clck 1		
	}
}

void dig(unsigned char d1, unsigned char d2) {
	PADR &= 0xF7; //shift 0	
	d(d1);
	d(d2);
	PADR |= 0x08; //shift 1
}

main()
{
	PADDR = 0xFF;	
	PAOR = 0xFF;	
	PADR = 0xFF;
	
	while (1)
	{
		dig(dig_n[0],led_table[8]);
		dig(dig_n[1],led_table[9]);
		dig(dig_n[2],led_table[6]);
		dig(dig_n[3],led_table[7]);
	}
}
Реклама
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Что то я вижу примерчики на уровне детского сада. Магические числа. Для следующего проекта вы будете переписывать ВСЕ. А мне только *.h чуток подправить. А то что вызовы у меня идут. Так и не тиньки в своих проектах использую.
Так что, хгаспада... Не впечатлили.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Reflector »

Ладно, разберем конкретный фрагмент программы:

Код: Выделить всё

void all_indications_off (void)
{
   set_seven_segm_ind_1_off ();
   set_seven_segm_ind_2_off ();
   set_seven_segm_ind_3_off ();
   set_seven_segm_ind_4_off ();
   set_seven_segm_ind_5_off ();
   set_seven_segm_ind_6_off ();
   set_seven_segm_ind_7_off ();
   set_seven_segm_ind_8_off ();

   set_bit (LEDS_IND_PORT, LEDS_IND);
}
Такого рода функций там три, плюс к ним идет больше сотни строк дефайнов и каждый пин тут инитится или сбрасывается/устанавливается отдельно, хотя в данный момент 8 из 9 пинов относятся к одному порту.
Теперь посмотрим что будет у меня задай я такие же пины:

Код: Выделить всё

using pins1 = PinList<PA7, PA6, PA5, PA4, PA3, PA2, PA1, PA0>;
using pins2 = PinList<PC7>;

PinList<pins1, pins2>::set();
И для STM32 получаем:

Код: Выделить всё

movs r3, #160
movs r1, #128
lsls r3, r3, #23 
adds r2, #248
str r2, [r3, #24] 
ldr r2, [pc, #432]
str r1, [r2, #24] 
Как видно записи в порты всего две, потому что самих порта два. Ладно, а что с записью?

Код: Выделить всё

volatile uint32_t val = 1234;
using pins1 = PinList<PA7, PA6, PA5, PA4, PA3, PA2, PA1, PA0>;
pins1::write(val);

// movs r3, #160      
// ldrh r2, [r5, #0]  
// lsls r3, r3, #23   
// uxtb r2, r2        
// strb r2, [r3, #20] 
Это нормально для максимально короткого и быстрого обработчика прерываний? Либа не только видит, что все пины с одного порта, она даже понимает, что в данном случае эффективнее к порту(у STM32 они 16-ти битные) обращаться побайтно. Таким образом то что я демонстрирую - это не краткость в ущерб производительности, мой код и короче и быстрее. Сами пины тоже не меняются по всей программе, они задаются там, где инициализируются, т.е. наоборот все в одном месте.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Стесняюсь спросить. Мы в каком разделе? Если соизволили сунуться, давайте говорить предметно и по делу.
BlackKilkennyCat
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BlackKilkennyCat »

Понятно. "Не тиньки". Ну-ну. Для хеловорд десяток классов и интерфейсов, а гвозди микроскопом забивать.
void set_seven_segm_ind_6_on (void)
{
set_bit (SEVEN_SEGM_IND_6_PORT, SEVEN_SEGM_IND_6);
}
и так аж 8. а потом ещё других. Месье знает толк в извращениях.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Я пояснил, почему написано так а не иначе. От вас достойного варианта я не увидел. Когда сегменты на одном порту, а общие выводы на другом, код очень прост.
Спойлер

Код: Выделить всё

//==================
#ifndef SEVEN_SEGM_LED_IND_H

#define SEVEN_SEGM_LED_IND_H

#include "seven_segm_led_ind.h"
//==================

//==================
#include "main_def_func.h"
//==================

//==================
#define ANODS_PORT         PORTA
#define ANODS_PIN          PINA
#define ANODS_DDR          DDRA

//#define ANODS_2_PORT       PORTA
//#define ANODS_2_PIN        PINA
//#define ANODS_2_DDR        DDRA

#define KATODS_PORT        PORTC
#define KATODS_PIN         PINC
#define KATODS_DDR         DDRC
//==================

//==================
#define ANOD_1             1<<2
#define ANOD_2             1<<3
#define ANOD_3             1<<4
#define ANOD_4             1<<5
#define ANOD_5             1<<6
#define ANOD_6             1<<7
//------------------------------------------------------------------------
#define A                  1<<6
#define B                  1<<7 //     A
#define C                  1<<3 //   F   B
#define D                  1<<2 //     G
#define E                  1<<1 //   E   C
#define F                  1<<5 //     D
#define G                  1<<4
#define H                  1<<0
//------------------------------------------------------------------------
#define ZERO               (A | B | C | D | E | F)
#define ONE                (B | C)
#define TWO                (A | B | D | E | G)
#define THREE              (A | B | C | D | G)
#define FOUR               (B | C | F | G)
#define FIVE               (A | C | D | F | G)
#define SIX                (A | C | D | E | F | G)
#define SEVEN              (A | B | C)
#define EIGHT              (A | B | C | D | E | F | G)
#define NINE               (A | B | C | D | F | G)
#define SPACE              0

#define CHAR_SPACE         10
//==================

//==================
#define MAX_LED_INDS       6

#define ANODS_MASK         (ANOD_1 | ANOD_2 | ANOD_3 | ANOD_4 | ANOD_5 | ANOD_6)
#define KATODS_MASK        (A | B | C | D | E | F | G)
//==================

//==================
extern u08 dsp_buf [];

void clr_dsp_buf (void);
//==================

//==================
void _print_val_xxx (u08 x, u08 a);
#define print_val_xxx(x, a) _print_val_xxx(((x)-1), (a))
//==================

//==================
typedef struct index_anods
{
   u08 i;
   u08 anod;
} index_anods;
//==================

//==================
void set_proc_7_segm_ind_on (void);
void set_proc_7_segm_ind_off (void);
void proc_7_segm_ind (void);
//==================

//==================
#endif
//==================
Спойлер

Код: Выделить всё

//==================
#include "seven_segm_led_ind.h"
//==================

//==================
struct index_anods __flash tab_index_anods [] =
{
   {0x01,   ANOD_2},
   {0x02,   ANOD_3},
   {0x03,   ANOD_4},
   {0x04,   ANOD_5},
   {0x05,   ANOD_6},
   {0x00,   ANOD_1},
};

u08 __flash table_7_segm_char [11] =
{
   ZERO,    ONE,
   TWO,     THREE,
   FOUR,    FIVE,
   SIX,     SEVEN,
   EIGHT,   NINE,
   SPACE,
};
//==================

//==================
soft_timer ST_PROC_7_SEGM_IND;
//------------------------------------------------------------------------
u08 dsp_buf [MAX_LED_INDS];
//------------------------------------------------------------------------
// Очистка буфера дисплея.

u08 dsp_buf [MAX_LED_INDS];

void clr_dsp_buf (void)
{
   for (u08 i = 0; i < MAX_LED_INDS; i++)
      dsp_buf [i] = CHAR_SPACE;
}
//==================

//==================
void _print_val_xxx (u08 x, u08 a) // Вывод числа в формате xx,x.
{
   char *ptr = num_str_buf + 7;
 
   char_to_str (a);

   dsp_buf[x] = *ptr; // Вывод сотен.
   dsp_buf[x++];
   ptr++;

   dsp_buf[x] = *ptr;
   dsp_buf[x++];
   ptr++;

   dsp_buf[x] = *ptr; // Вывод единиц.
}
//==================

//==================
static u08 _proc_7_segm_ind;

void set_proc_7_segm_ind_on (void)
{
   _proc_7_segm_ind = 1;
}

void set_proc_7_segm_ind_off (void)
{
   ANODS_DDR = 0;
   ANODS_PORT = 0;
   KATODS_DDR = 0;

   _proc_7_segm_ind = 0;
}

void proc_7_segm_ind (void)
{
   static u08 cnt_7_segm_ind;

   switch (_proc_7_segm_ind)
   {
      case 0:
         break;

      case 1:
         ANODS_DDR = 0xFF;
         cnt_7_segm_ind = 0;
         set_soft_timer (ST_PROC_7_SEGM_IND, 1, 1);
         _proc_7_segm_ind = 2;
         break;

      case 2:
         if (handle_soft_timer (ST_PROC_7_SEGM_IND))
         {
            u08 cnt = cnt_7_segm_ind;

            ANODS_PORT = 0;
            KATODS_DDR = 0;

            volatile u08 anods;
            volatile u08 katods;

            cnt_7_segm_ind = tab_index_anods [cnt].i;
            anods = tab_index_anods [cnt].anod;

            katods = table_7_segm_char [dsp_buf [cnt_7_segm_ind]];

            ANODS_PORT = anods;
            KATODS_DDR = katods;
         }
         break;

      default:
         break;
   }
}
//==================
А вот когда на разных портах, ситуация в корне меняется. Дано: AVR, произвольные порты и пины. Удивите меня.
Последний раз редактировалось Demiurg Вс авг 23, 2020 00:53:27, всего редактировалось 1 раз.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Reflector »

[uquote="Demiurg",url="/forum/viewtopic.php?p=3882624#p3882624"]Я пояснил, почему написано так а не иначе. От вас достойного варианта я не увидел. Когда сегменты на одном порту, а общие выводы на другом,[/uquote]
Чем мой вариант не угодил, там пины могут быть какие угодно, а таблица одна на все случаи, потому в классе и находится...
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Дополнил свое сообщение.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Reflector »

У меня есть мк с 7-ю портами по 16 пинов, соответственно можно составить такой список пинов для сегментов, где будут задействованы все эти порты, а можно взять 8-ми разрядный семисегментник и тогда в списке пинов разрядов тоже могут быть 7 портов. Это будет работать и задается теми же двумя строками, естественно работать будет не очень быстро, но чем меньше портов и больше удачно сгруппированных пинов, которые совсем не обязательно должны идти подряд, тем эффективнее. Опять же будет одна строка для инициализации всех пинов и одна строка для записи, т.е. кода самый минимум, а дальше уже нужно стараться подбирать пины так чтобы не пришлось писать в порт по одному биту... Но работать будет в любом случае, а у тебя я вижу ANODS_PORT и KATODS_PORT - это всего два порта, причем раздельно. В таком случае конечно можно сделать таблицы под конкретные пины, просто мне это особо не нужно, т.к., во-первых, STM32 пошустрее, во-вторых, там прерывания с приоритетами, в третьих, если либа работает с любыми пинами, то заниматься таблицами нужно только в случае реально наблюдаемых тормозов, с которыми мне пока сталкиваться не приходилось. Однако чисто технически можно взять список пинов и на основании его автоматически получить нужные массивы, я тебе даже в теме про меню говорил, что можно взять структуру хоть из флеша, поменять ее и новая структура будет лежать во флеше вместо старой. Или из относительно недавнего я делал форматированный вывод, там при компиляции проверялся формат строки форматирования, соответствие количества аргументов, автоматически определяются типы(можно написать "{}") и потом сама строка подменялась другой, которую уже в рантайме можно парсить более эффективно.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Мне тут за эффективность сказали. Зря. Я всегда просчитываю, сколько времени выполняется тот или иной кусок кода. И если я где то поступился, значит на то были причины.
Дальше. Я вижу от вас доводы за STM, но не AVR. Как мы можем реализовать произвольный пин мк. Табличный метод. Это массив указателей на функции. Никак иначе. Перебор. Или тот же Switch-case. И тут мы возвращаемся к эффективности, на которую мне тут показали. Вызов функций видите ли не понравился. Так как у меня Mega, на стек мне плевать. ОЗУ хватает. Скорость? Так перебором даже дольше выходит.
Так что с AVR не выйдет красиво и лаконично. Так что возвращаемся: мне параллельно на мнения. Удивите. А там поговорим. И, практику STM не надо. Мы в разделе AVR.
Практика показывает, что красиво, лаконично - далеко не всегда равно эффективность. За дефайны скажу один раз. Я уже давно завёл себе правило. Пусть я буду делать самый простой проект. И я задефайню все что можно. Числа, порты, пины. У меня всегда будут стоять внятные и понятные определения. Да, писанины это добавляет. Но это для меня всегда окупается. Мне не надо по всей программе, если что лазить и править. Делается это все в одном месте. И что самое важное, такой подход минимизирует ошибки. Долго запрягаем, быстро едем.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15558
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BOB51 »

Ну и понаворотили...
Может проще - отдельно саму индикацию с изменяемой раздельно по каждому разряду яркостью (шим, но гораздо более256 градаций).
Как-то под ассемблером на таком принципе 4х-позиционку для тиньки2313 делал... Правда в основе полное использование ресурсов Т1...
А эффекты - отдельная задача.
8)
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение ARV »

BlackKilkennyCat писал(а):Код Reflectorа - это максимум, чего должно быть.
с этим не могу согласиться: для С++, возможно, и максимум, но для Си максимум чуток поболее.

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

Мой уютный бложик... заходите!
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15558
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BOB51 »

Знакогенератор это уже функционал обработчика данных, а не контроллера вывода на дисплей.
Явно функция излишняя.
Задача контроллера всего лишь вывод содержимого буфера отображаемых данных (видеопамяти) на индикацию да ещё захват кодовой комбинации с ЛВК(если совмещённый со сканером кнопок).
Данные готовятся отдельно - программа контроллера только перекидывает их из буфера переподготовки в буфер отображения (и то часто эта функция принадлежит той части программы, что данные для буфера предподготовки обрабатывает).
:roll:
Последний раз редактировалось BOB51 Вс авг 23, 2020 18:58:25, всего редактировалось 1 раз.
Аватара пользователя
ChipCard
Открыл глаза
Сообщения: 42
Зарегистрирован: Чт июл 23, 2020 20:59:01
Откуда: СевКавТВ

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение ChipCard »

Ммдя ... сложноватые примеры, да ещё и синтаксис мне не знаком. :roll: Это C++? Можно более простой пример?
BlackKilkennyCat
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BlackKilkennyCat »

Просто у всех разные среды и мк, да и ещё и разные стили.
Ответить

Вернуться в «AVR»