Обсуждаем контроллеры компании Atmel.
Ответить

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

Ср авг 26, 2020 13:30:21

Demiurg писал(а):Вот обсуждение, в топике ссылки. Ссылка 1, Ссылка 2.
посмотрел... оказалось, я даже участвовал в той теме... с 2008 года позабыл.

признаю свою неправоту, на тот момент проблема была, сомневаться в словах ReAl-а у меня нет никаких оснований. но в моей практике никогда ничего подобного не было, хотя программный ШИМ на attiny13 я делал именно выводом в порт сразу. правда, при этом между выводами было больше нескольких десятков тактов...

тем не менее, к засветке индикаторов упомянутый эффект явно никакого отношения не имел.

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

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

Ср авг 26, 2020 13:52:57

Demiurg писал(а):Убрал засветку.
Тяжелый случай.
Спойлер
Код:
void handle_commons_clr (void) {
   u08 *p;

   for (u08 i = 0; i < MAX_LED_INDS; i++)
     {
      p = commons_pins [i] .port;
      *p &= (~commons_pins [i] .mask);
      }
}


      case 2:
         if (handle_soft_timer (ST_PROC_7_SEGM_IND))
         {
            //handle_commons ();
            //handle_segments ();
            handle_commons_clr();
            handle_segments ();
            handle_commons ();

            if (++cnt_commons >= MAX_LED_INDS) cnt_commons = 0;
         }
         break;

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

Ср авг 26, 2020 14:09:42

ARV, с засветкой вопрос решён.
Dimon456. Я пример дал, что докопался? Может где то и есть чёрновой вариант. Проект выложил. Проверил на железе. Доводи до ума сам.

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

Ср авг 26, 2020 22:02:00

В текущей версии проекта прогон вывода сегментов и разрядов занимает 566 тактов. 35.38 мкс. Когда я чуток изменил логику, получилось - 507 тактов. 31.69 мкс. При тактовой частоте 16 МГц.

немного поборол лень и накропал такой вариант:
Спойлер
Код:
#include <avr/io.h>
#include <avr/interrupt.h>

typedef struct{
   volatile uint8_t * port;
   uint8_t            and;
   uint8_t            or;
} seg_pin_t;

#define pn(p,b) {&PORT ## p, ~_BV(b), _BV(b)}

#define A   _BV(0)
#define B   _BV(1)
#define C   _BV(2)
#define D   _BV(3)
#define E   _BV(4)
#define F   _BV(5)
#define G   _BV(6)
#define H   _BV(7)

#define DIG0   (A+B+C+D+E+F)
#define DIG1   (B+C)
#define DIG2   (A+B+G+E+D)
#define DIG3   (A+B+C+D+G)
#define DIG4   (B+F+G+C)
#define DIG5   (A+F+G+C+D)
#define DIG6   (A+C+D+E+F+G)
#define DIG7   (A+B+C)
#define DIG8   (A+B+C+D+E+F+G)
#define DIG9   (A+B+C+D+F+G)

#define FLASH

const __flash uint8_t digs[10] = {DIG0, DIG1, DIG2, DIG3, DIG4, DIG5, DIG6, DIG7, DIG8, DIG9};

const FLASH seg_pin_t pins[8] = {
  pn(B,0),
  pn(C,0),
  pn(D,0),
  pn(B,2),
  pn(C,2),
  pn(D,2),
  pn(B,4),
  pn(C,4)
};

const FLASH seg_pin_t commons[4] = {
  pn(D,1),
  pn(D,4),
  pn(B,1),
  pn(C,1)
};

#define COM_CAT      ((PIND & _BV(7)) == 0)

extern uint8_t data[4];
uint8_t scr[4] = {DIG5,DIG2,DIG3,DIG4};

ISR(TIMER0_OVF_vect){
   static uint8_t com;

   const FLASH seg_pin_t *p = commons+com;

   if(COM_CAT)
      *p->port |= p->or;
   else
      *p->port &= p->and;

   if(++com >= 4) com = 0;

   uint8_t d = scr[com];
   if(!COM_CAT) d = ~d;

   p = pins;
   for(uint8_t i=0; i<8; i++, d>>=1){
      *p->port = (*p->port & p->and) | (d & 1 ? p->or : 0);
      p++;
   }

   p = commons+com;
   if(COM_CAT)
      *p->port &= p->and;
   else
      *p->port |= p->or;
}

int main(void){
   DDRB = 255;
   DDRC = 255;
   DDRD = 0x7F;
   PORTD = 0x80;

   TCCR0 = 4;
   TIMSK = _BV(TOIE0);
   sei();
   while(1);
}

все в одном файле, без наворотов, с магическими числами, ибо лень.

константа FLASH позволяет переместить таблицу "распиновки" сегментов и общих катодов/анодов в память программ, если определить ей значение __flash

так вот, от певого push в обработчике прерываний до reti при тактовой 16 МГц проходит 25 мкС (если таблицы в памяти программ) или 24 мкС (если таблицы в ОЗУ). тип индикатора можно переключать на лету:


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

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

Ср авг 26, 2020 23:07:43

Я как раз занимаюсь именно оптимизацией. И именно как у вас. Сразу готовые маски в таблицах. Вообще я этим проектом занялся из поиска баланса. Эффективности.
В данный момент делаю три варианта проекта. В лоб. If-а ми. Массивы функций, и по вашему способу. Это я делаю чисто для себя. Никакого писькомеряния. Эксперимент с индексным обращением к портам и поиск баланса.
За макрос pn(p,b) благодарствую. Вы показали хороший способ сэкономить время на писанине.

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

Чт авг 27, 2020 20:27:00

все в одном файле, без наворотов, с магическими числами

это очень хорошо, один файл и попроще!
без комментариев сложно для меня разобраться, но я пытаюсь.
Спойлер#include <avr/io.h>
#include <avr/interrupt.h>

typedef struct{
volatile uint8_t * port;
uint8_t and;
uint8_t or;
} seg_pin_t;

#define pn(p,b) {&PORT ## p, ~_BV(b), _BV(b)}

#define A _BV(0)
#define B _BV(1)
#define C _BV(2)
#define D _BV(3)
#define E _BV(4)
#define F _BV(5)
#define G _BV(6)
#define H _BV(7)

#define DIG0 (A+B+C+D+E+F)
#define DIG1 (B+C)
#define DIG2 (A+B+G+E+D)
#define DIG3 (A+B+C+D+G)
#define DIG4 (B+F+G+C)
#define DIG5 (A+F+G+C+D)
#define DIG6 (A+C+D+E+F+G)
#define DIG7 (A+B+C)
#define DIG8 (A+B+C+D+E+F+G)
#define DIG9 (A+B+C+D+F+G)
#define DIGH (B+C+E+F+G)
#define DIGE (A+D+E+F+G)


#define FLASH

const __flash uint8_t digs[12] = {DIG0, DIG1, DIG2, DIG3, DIG4, DIG5, DIG6, DIG7, DIG8, DIG9, DIGH, DIGE};

const FLASH seg_pin_t pins[8] = {
pn(B,0),
pn(B,1),
pn(B,2),
pn(B,3),
pn(B,4),
pn(B,5),
pn(B,6),
pn(B,7)
};

const FLASH seg_pin_t commons[5] = {
pn(D,0),
pn(D,1),
pn(D,2),
pn(D,3),
pn(D,4)
};

#define COM_CAT ((PIND & _BV(7)) == 0)

extern uint8_t data[10];
uint8_t scr[10] = { DIGH,DIGE,DIG1,DIG1,DIG0, DIG9,DIG2,DIG3,DIG4,DIG5};


ISR(TIMER0_OVF_vect){
static uint8_t com;

const FLASH seg_pin_t *p = commons+com;

// if(COM_CAT)
*p->port |= p->or;
// else
// *p->port &= p->and;

if(++com >= 5) com = 0;

uint8_t d = scr[com];
//if(!COM_CAT) d = ~d;

p = pins;
for(uint8_t i=0; i<8; i++, d>>=1){
*p->port = (*p->port & p->and) | (d & 1 ? p->or : 0);
p++;
}

p = commons+com;
// if(COM_CAT)
*p->port &= p->and;
// else
// *p->port |= p->or;
}

int main(void){
DDRB = 255;
// DDRC = 255;
DDRD = 0x7F;
PORTD = 0x80;

TCCR0 = 4;
TIMSK = _BV(TOIE0);
sei();
while(1);
}


хорошо с "движком" боле менее понял. а дальше ? как эффекты делать? тема называется эффекты анимации, прошу объясните дальше.
к примеру чтобы "HELLO" уползло влево и выползло "FIK" или цифры неважно...


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

Чт авг 27, 2020 21:30:24

Serzh2000, в же делали скрипты эффектов DIGISCRIPT, с его примитивным языком, неужели на Си, с его богатыми возможностями, не можете ничего придумать?!

знакогенератор с буквами мне писать лень, но вот вам тупейший "эффект" катающегося колобка:
Спойлер
Код:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

typedef struct{
   volatile uint8_t * port;
   uint8_t            and;
   uint8_t            or;
} seg_pin_t;

#define SCR_SZ   4

#define pn(p,b) {&PORT ## p, ~_BV(b), _BV(b)}

#define A   _BV(0)
#define B   _BV(1)
#define C   _BV(2)
#define D   _BV(3)
#define E   _BV(4)
#define F   _BV(5)
#define G   _BV(6)
#define H   _BV(7)

#define DIG0   (A+B+C+D+E+F)
#define DIG1   (B+C)
#define DIG2   (A+B+G+E+D)
#define DIG3   (A+B+C+D+G)
#define DIG4   (B+F+G+C)
#define DIG5   (A+F+G+C+D)
#define DIG6   (A+C+D+E+F+G)
#define DIG7   (A+B+C)
#define DIG8   (A+B+C+D+E+F+G)
#define DIG9   (A+B+C+D+F+G)

#define SYM1   (A+B+F+G)
#define SYM2   (C+D+E+G)

#define FLASH

const __flash uint8_t digs[10] = {DIG0, DIG1, DIG2, DIG3, DIG4, DIG5, DIG6, DIG7, DIG8, DIG9};

const FLASH seg_pin_t pins[8] = {
  pn(B,0),
  pn(C,0),
  pn(D,0),
  pn(B,2),
  pn(C,2),
  pn(D,2),
  pn(B,4),
  pn(C,4)
};

const FLASH seg_pin_t commons[SCR_SZ] = {
  pn(D,1),
  pn(D,4),
  pn(B,1),
  pn(C,1)
};

#define COM_CAT      ((PIND & _BV(7)) == 0)

extern uint8_t data[4];
uint8_t scr[SCR_SZ] = {DIG5,DIG2,DIG3,DIG4};

ISR(TIMER0_OVF_vect){
   static uint8_t com;

   const FLASH seg_pin_t *p = commons+com;

   if(COM_CAT)
      *p->port |= p->or;
   else
      *p->port &= p->and;

   if(++com >= SCR_SZ) com = 0;

   uint8_t d = scr[com];
   if(!COM_CAT) d = ~d;

   p = pins;
   for(uint8_t i=0; i<8; i++, d>>=1){
      *p->port = (*p->port & p->and) | (d & 1 ? p->or : 0);
      p++;
   }

   p = commons+com;
   if(COM_CAT)
      *p->port &= p->and;
   else
      *p->port |= p->or;
}

static void clr(void){
   for(uint8_t i=0; i<SCR_SZ; i++){
      scr[i] = 0;
   }
}

int main(void){
   DDRB = 255;
   DDRC = 255;
   DDRD = 0x7F;
   PORTD = 0x80;

   TCCR0 = 4;
   TIMSK = _BV(TOIE0);
   sei();
   while(1){
      for(uint8_t i=0; i<SCR_SZ; i++){
         clr();
         scr[i] = SYM1;
         _delay_ms(200);
      }
      for(int8_t i=SCR_SZ-1; i >= 0; i--){
         clr();
         scr[i] = SYM2;
         _delay_ms(200);
      }
   }
}
собственно, весь эффект вот тут, в главном цикле:
Код:
   while(1){
      for(uint8_t i=0; i<SCR_SZ; i++){
         clr();
         scr[i] = SYM1;
         _delay_ms(200);
      }
      for(int8_t i=SCR_SZ-1; i >= 0; i--){
         clr();
         scr[i] = SYM2;
         _delay_ms(200);
      }
   }
сначала слева направо поочередно рисуем колобка в верхней части дисплея, а потом справа налево в нижней.

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

Добавлено after 13 minutes 15 seconds:
если вы вывели на дисплей, предположим, 1234, то при помощи вот этого кода вы сможете "прокручивать" это число:
Код:
uint8_t tmp = scr[0];
scr[0]=scr[1];
scr[1]=scr[2];
scr[2]=scr[3];
scr[3]=tmp;
_delay_ms(200);
ну а дальше сами :)

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

Чт авг 27, 2020 22:06:40

в же делали скрипты эффектов DIGISCRIPT, с его примитивным языком, неужели на Си, с его богатыми возможностями, не можете ничего придумать?!

спасибо большое буду изучать и пробовать.

в DIGISCRIPT там все просто, Вы за нас придумали все, я только придумывал эффект, брал команду, красил шарик и направлял в нужную сторону.

я писать пробовал в CodeVisionAVR и в ардуине, а Вы все в других программах пишите, вот нашел Atmel Studio
которая понимает Ваши программы, но я ее не понимаю... пока не понимаю.

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

Чт авг 27, 2020 23:38:29

ARV. Хвалю. Очень интересное решение получилось. Особенно понравился перескок переключения общих выводов. Что значительно решило проблему засветку. У вас с указателями, я попробовал, но IAR закапризничал, выдал что то непонятное. Поэтому сделал пока с прямым обращением к данным. Уже поздно, завтра займусь.
Что у меня пока получилось. 370 тактов. 23.13 мкс. 16 МГц. На этом варианте я останавливаюсь. Меня вполне устраивает.
Спойлер
Код:
            volatile u08 *p;

            // Отключение общего вывода.
            p = commons_pins [cnt_commons] .port;

            if (commons_level == HI)
               *p &= commons_pins [cnt_commons] .and;
            else
               *p |= commons_pins [cnt_commons] .or;

            if (++cnt_commons >= MAX_LED_INDS) cnt_commons = 0;

            u08 a;

            if (status == STATUS_EFFECTS)
               a = dsp_buf [cnt_commons];
            else
               a = table_7_segm_char [dsp_buf [cnt_commons]];

            if (segments_level != HI) a = ~a;

            for (u08 i = 0; i < 8; i++, a >>= 1)
            {
               p = segments_pins [i] .port;

               if (a & (1<<0))
                  *p |= segments_pins [i] .or;
               else
                  *p &= segments_pins [i] .and;
            }

            // Включение общего вывода.
            p = commons_pins [cnt_commons] .port;

            if (commons_level == HI)
               *p |= commons_pins [cnt_commons] .or;
            else
               *p &= commons_pins [cnt_commons] .and;


SEVEN_SEGM_PROJECT_INDEX.rar
(460.85 KiB) Скачиваний: 132


Видео

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

Пт авг 28, 2020 08:02:18

Demiurg писал(а):Что значительно решило проблему засветку
проблема засветки никак не связана с общими катодами или анодами, она связана с очередностью переключений пинов.
Demiurg писал(а):23.13 мкс
IAR традиционно генерирует более оптимальный код.

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

Пт авг 28, 2020 08:36:48

ARV, зачем volatile в структуре?
Кстати, делал индикацию на Тини26. Весь порт занят сегментами - бага не заметил. Или это всё в прошлом?

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

Пт авг 28, 2020 09:22:38

volatile - потому что обращение к портам. Потому, прибиваем гвоздями, чтобы компилятор даже помыслить не мог что-то наоптимизировать.

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

Пт авг 28, 2020 12:20:35

Serzh2000, вот вам один эффект
Спойлер
Код:
const FLASH char effect_1[][SCR_SZ]=
{ {A, 0, 0, 0},
  {A, A, 0, 0},
  {A, A, A, 0},
  {A, A, A, A},
  {0, A, A, A+B},
  {0, 0, A, A+B+C},
  {0, 0, 0, A+B+C+D},
  {0, 0, D, B+C+D},
  {0, D, D, C+D},
  {D, D, D, D},
  {E+D, D, D, 0},
  {F+E+D, D, 0, 0},
  {F+E+D, 0, 0, 0},
  {F+E, 0, 0, 0},
  {F, 0, 0, 0},
};

unsigned int sizeArray;


   sizeArray = sizeof(effect_1)/(sizeof(char)*SCR_SZ);
   clr();
   for(int8_t a=0; a < 5; a++)   // число повторов
   for(int8_t i=0; i < sizeArray; i++){

      scr[0] = effect_1[i][0];
      scr[1] = effect_1[i][1];
      scr[2] = effect_1[i][2];
      scr[3] = effect_1[i][3];

      _delay_ms(500);
   }

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

Пт авг 28, 2020 12:37:34

тема анимации на 7 сегментниках не раскрыта! :))) :))) :))) :beer:
Спойлер

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

Пт авг 28, 2020 12:51:26

Раскрыта на все 100. Как на словах, так и на примерах.

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

Пт авг 28, 2020 12:57:13

volatile - потому что обращение к портам. Потому, прибиваем гвоздями, чтобы компилятор даже помыслить не мог что-то наоптимизировать.

А какие причины "помыслить"?

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

Пт авг 28, 2020 13:25:11

OKF писал(а):А какие причины "помыслить"?
обычные: PORTx объявлен, как volatile uint8_t, соответственно и указатель на него должен быть volatile uint8_t *.

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

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

Пт авг 28, 2020 22:56:25

Dimon456. Спасибо за пример "бегущего червячка" пр кругу
я разобрался как писать эффекты, спасибо Всем. :beer:

теперь другая дилемма, куда бы семисегментный LED-индикатор с эффектами анимации пристроить, чего бы этакого сделать?

кроме часов на ум ни чего не приходит, но часы не хочется.
новогоднюю звездочку на макушку елки я сделал, гирлянда (DIGISCRIPT) есть.
может вместо семисегментника взять отдельные светики и сделать снежинку к новому году?
восемь лучей (разрядов) в каждом до 14 светиков :roll: и клепай эффекты :solder:
надо подумать :tea:

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

Пт авг 28, 2020 23:05:48

BAM.
Последний раз редактировалось Demiurg Пт авг 28, 2020 23:31:01, всего редактировалось 2 раз(а).

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

Пт авг 28, 2020 23:15:43

это для машины на заднее стекло? :shock: круто! :beer: но у меня машины пока нет :cry: да и прав тоже нет, пока :wink:
Ответить