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

Обсуждаем контроллеры компании Atmel.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

Я когда-то задавался вопросом, можно ли выводить на порты по индексу. Я не знаю, когда добавили эту плюшку, но в то время мне говорили, что это на AVR невозможно. Я попробую ваш пример. Что из того получится.
ARV, Reflector кто там еще. Предлагаю добить. Задачи: Произвольные порты, выбор активного уровня. Вы мне тут показали, что вроде как можно по индексу на порты вывести. Покажите макросы и добиваем совместными усилиями. Результат выложим тут.
Этот топик на этом форуме впервые за долгое время очень информативен и плодотворен.
Последний раз редактировалось Demiurg Пн авг 24, 2020 16:36:01, всего редактировалось 1 раз.
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

Demiurg писал(а):мне говорили, что это на AVR невозможно
меньше надо глупости слушать.
со времен WinAVR это работает, поскольку у AVR порты ввода-вывода отображены на адреса ОЗУ, и нет таких портов, к которым не разрешен доступ командами lds-sts, (наоборот - есть: бывают порты, к которым нельзя обратиться командами in-out).
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

ARV, не могу понять, где в вашем примере условие, по которому заканчивается цикл for? Заработало, теперь осталось сделать на основе вашего примера выбор активного уровня. Если честно, такой (как у вас) способ впервые вижу...
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

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

Сообщение Reflector »

[uquote="Demiurg",url="/forum/viewtopic.php?p=3883190#p3883190"]Предлагаю добить. Задачи: Произвольные порты, выбор активного уровня. Вы мне тут показали, что вроде как можно по индексу на порты вывести. Покажите макросы и добиваем совместными усилиями.[/uquote]
Шаблоны так не работают... Допустим есть такой список пинов:

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

using pins = PinList<PA6, PA4, PB3, PA2, PA1>;
Фактически pins - это тип, на данном этапе он никакого реального кода не генерит. Теперь вызовем метод write():

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

pins:write(val);
В этот момент создает экземпляр класса и в первую очередь внутри него из первоначального списка формируются индексированный список, т.е. пины нумеруются, потому что потом они будут из списков удаляться, а индекс будет нужен. Кроме того списки могут вместо пинов принимать другие списки, но в индексированном списке уже все разворачивается до одних пинов. Также создается список портов присутствующих в списке, проверяется наличие дубликатов пинов и вычисляет размер развернутого списка. Все эти дополнительные списки существуют чисто виртуально на этапе компиляции. Но основные расчеты начинаются когда дело доходит непосредственно до write(), там компилятор сортирует пины по портам и для каждого порта ищет последовательности пинов которые можно было бы получить за один заход по вычисленной маске. В данном случае для порта PA будет получена маска 0x16(для PA4, PA2, PA1), 0x40(для PA6) и еще одна специфическая маска для портов STM32. Для AVR, насколько помню, получилось бы что-то типа такого:

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

PORTA = PORTA & ~(0x16 | 0x40) | ((val << 1) & 0x16) | ((val << 2) & 0x40);
Естественно это эффективнее, чем:

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

PORTA &= ~(0x16 | 0x40);
if(val & 0x01) PORTA |= (1 << 1);
if(val & 0x02) PORTA |= (1 << 2);
if(val & 0x08) PORTA |= (1 << 4);
if(val & 0x10) PORTA |= (1 << 6);
А препроцессор просто подменяет один ничего для него не значащий текст на другой, потому никакими макросами шаблоны не заменишь.
Реклама
Эиком - электронные компоненты и радиодетали
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

ARV Вроде разобрался. Ваш пример интересным вышел...

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

void handle_segments_2 (void)
{
   u08 data = table_7_segm_char [dsp_buf [cnt_commons]];
   volatile u08 *p;

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

/*
      if (segments_level == HI)
         *p = (*p & (~segments_pins[i].mask)) | (data & m ? segments_pins[i].mask : 0);
      else
         *p = (*p & (~segments_pins[i].mask)) | (data & m ? 0 : segments_pins[i].mask);
*/

      *p = (*p & (~segments_pins[i].mask));

      if (segments_level == HI)
         *p |= (data & m ? segments_pins[i].mask : 0);
      else
         *p |= (data & m ? 0 : segments_pins[i].mask);
   }
}
А теперь господа об эффективности. Код короче. Спору нет. Но расплата - разворот в дизасме. Эффектно в коде, неэффективно в дизасме.
Я знал об этом, но мне интересно было, как реализовать доступ к портам и пинам по индексу.
Как бы то ни было, считаю этот топик успешным.
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

Reflector писал(а):Естественно это эффективнее
это, в принципе, не факт. во всяком случае, совсем не очевидно: сдвиги компенсируют наличие условных переходов, так что будет ли выигрыш - вопрос.
Demiurg писал(а):где в вашем примере условие, по которому заканчивается цикл for?
как это где? где ему и положено быть: на втором месте в теле оператора for:
ARV писал(а):for(uint8_t i=0, m=1; m; i++, m<<=1)
специльно выделил
Demiurg писал(а):Но расплата - разворот в дизасме.
как я уже говорил, не такая уж и большая расплата: у вас было
Demiurg писал(а):133 такта, 8.31 мкс при тактовой частоте 16 мгц.
При втором методе 545 тактов и 34 мкс
по моим оценкам у меня ровно посредине между вашими результатами: порядка 300 тактов. так что вполне приемлемо, имхо. но по восприятию кода - и сравнивать не возьмусь :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Самсусамыч

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

Сообщение Самсусамыч »

[uquote="ARV",url="/forum/viewtopic.php?p=3883183#p3883183"]по листингу у меня вышло около 235 тактов на вывод символа, не считая пролога-эпилога обработчика прерывания.[/uquote]
Значит и мой вариант вполне себе ничего… :) у меня тоже вышло 235 тактов на вывод цифры, начиная с момента вызова прерывания и выхода из него. :))
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

Самсусамыч писал(а):начиная с момента вызова прерывания и выхода из него
у меня без учета этого.

я уже неоднократно свою позицию говорил: если нет острой необходимости, то для чего экономить такты/байты? гораздо правильнее, имхо, облегчить свою участь, т.е. написать просто, легко, понятно и быстро, а уж будет оно 5 мкС или 10 мкС исполняться - не важно. и вот как раз в этом случае есть смысл делать универсальные библиотеки - лишь бы все просто и легко.

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

Мой уютный бложик... заходите!
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

[uquote="ARV",url="/forum/viewtopic.php?p=3883235#p3883235"]...[/uquote]
Я на сегодня закончил. Что у меня получилось с вашим примером. IAR, максимальная оптимизация balanced. Более 300 тактов. И это только вывод сегментов. А у вас в примере только он и есть. Вывода общих выводов нет. Кстати, получилось сделать выбор активного сигнала.
Завтра ещё поэкспериментирую, сделаю вывод общих выводов. Отпишусь.
Последний раз редактировалось Demiurg Пн авг 24, 2020 19:43:20, всего редактировалось 1 раз.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

Demiurg писал(а):А у вас в примере только он и есть
и чо?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

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

Сообщение Reflector »

[uquote="ARV",url="/forum/viewtopic.php?p=3883235#p3883235"]это, в принципе, не факт. во всяком случае, совсем не очевидно: сдвиги компенсируют наличие условных переходов, так что будет ли выигрыш - вопрос.[/uquote]
Да ладно... В первом случае одно чтение из регистра, одна запись, 5 бинарных операций и 3 сдвига(может и 2), итого ~10 тактов.
Во-втором случае одно чтение/запись, 5 бинарных операций, 4 двухтактовых перехода и потом еще опционально 3+3+3+3, итого минимум 15 тактов, максимум - 27, в среднем - 21.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

[uquote="ARV",url="/forum/viewtopic.php?p=3883254#p3883254"]и чо?[/uquote]
Чо по китайский (_._). :) Конечно, спасибо за пример. В будущем пригодится, давно искал вывод в порты по индексу.
Но, но... Расплата высока. Проще в лоб. По первому способу. Да, писанины порядочно. Но выхлоп эффективен.
У вас легко, просто, выхлоп же... А диалог разгорелся про эффективность.
Там "легко, просто", там. В итоге набирается по тактам при таком подходе.
Так что, диалог про эффективность считаю закрытым.
Краткость кода, "легко и просто" - не равно эффективность.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

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

Мой уютный бложик... заходите!
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

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

Сообщение Serzh2000 »

у меня тоже получилось нарисовать эффект (какой автор в начале рисовал) и циферки
даже в протеусе работает :)))
Спойлер/*****************************************************


#include <mega8.h>

#include <delay.h>

unsigned char digit_out[4], // буфер экрана (нумерация от 0 до 4 разрядa)
cur_dig; // тек.высвечиваемый символ (позиция)

unsigned int ff=200, // время кадра c шим
f=500, // время кадра
h=1, // число повторов эффекта
yarkost; // яркость


static flash unsigned char digits[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,
60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,
95,96,97,98,99,100,101,102,103};






// ---------------- Timer 2 overflow interrupt service routine -----------------------------


interrupt [TIM2_OVF] void timer2_ovf_isr(void){

PORTD&=0b00000000;

PORTB=~digits[digit_out[cur_dig]];

PORTD |= (1<<cur_dig);

cur_dig++; if (cur_dig >= 4) {
cur_dig = 0;
OCR2 = yarkost;
}

}// ----------------------------------------------------------------------------------------

// ------------------ Timer2 output compare interrupt service routine ----------------------

interrupt [TIM2_COMP] void timer2_comp_isr(void){
PORTB&=0b11111111;
// PORTD=0b11111111;


}// ----------------------------------------------------------------------------------------




void view_flasher_1(void) {
int i,j;
for (j =0; j<h;++j){

for (i =0; i<17;++i){

unsigned int A[] = {0,1,1,1,1,0,0, 0, 0, 0, 0, 8,24,56,48,32, 0};
unsigned int B[] = {0,0,1,1,1,1,0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0};
unsigned int C[] = {0,0,0,1,1,1,1, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0};
unsigned int D[] = {0,0,0,0,1,3,7,15,15,14, 12,8, 0, 0, 0, 0, 0};


digit_out[0] = A;
digit_out[1] = B;
digit_out[2] = C;
digit_out[3] = D;



delay_ms(ff);
}

}
delay_ms(f);

}

//======================

void view_flasher_2(void) {
int i,j;
for (j =0; j<h;++j){

for (i =0; i<20;++i){

unsigned int A[] = {0,2,6,6,6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
unsigned int B[] = {0,0,0,1,3,67,83,91,91,91,91,91,91,91,91,91, 91, 91, 91 ,91};
unsigned int C[] = {0,0,0,0,0, 0, 0, 0, 1, 3,67,71,79,79,79,79, 79, 79, 79, 79};
unsigned int D[] = {0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0, 0,32,96,98,102,102,102,102};


digit_out[0] = A;
digit_out[1] = B;
digit_out[2] = C;
digit_out[3] = D;



delay_ms(ff);
}

}
delay_ms(f);

}




//=================== main ==========

//основаня функция
void main(void){

digit_out[0]=0; // очистить экран
digit_out[1]=0;
digit_out[2]=0;
digit_out[3]=0;



//настройка портов
PORTB=0b00000000;
DDRB=0b11111111;
PORTC=0b00000000;
DDRC=0b00000000;
PORTD=0b00000000;
DDRD=0b00001111;

TCCR2=0x04;
TIMSK=0b11000000;
// 0b11000001
// || | |
// || | Timer0
// || Timer1
// |Timer2
//
#asm("sei") // Глобальные прерывания включения

// -------------------------------- рабочая часть ------------------------------------------
while (1) {


view_flasher_1();
view_flasher_2();

}; // ----------------------------- рабочая часть (end) ------------------------------------

} // ================= end main ======

//
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- The End -=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
Вложения
EFFECT.rar
(860.88 КБ) 149 скачиваний
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

[uquote="ARV",url="/forum/viewtopic.php?p=3883259#p3883259"]для меня важна эффективность моего труда, а микроконтроллер - он кремниевый, не потеет и не устаёт, ему до лампочки, что делать: в главном цикле nop-ы исполнять или расчеты сегментов делать.[/uquote]
Про микроконтроллер абсолютно согласен. Про эффективность мы опять пришли в тупик. Вы о своём, я о своём. На этом закончим. Тем более, что я ещё не закончил эксперименты.

Добавлено after 3 minutes 38 seconds:
[uquote="Serzh2000",url="/forum/viewtopic.php?p=3883267#p3883267"]...[/uquote]
Видео в студию.
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

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

Сообщение Serzh2000 »

любую фигуру можно нарисовать :)))

Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

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

Мой уютный бложик... заходите!
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

Я закончил с экспериментами. Выкладываю окончательный вариант. Реализовано: произвольный выбор портов и пинов. Выбор логики управления сегментами и разрядами. За идею обращения к портам по индексу ARV отдельная благодарность.
Проект проверен на отладочной плате STK-500.

*.h
Спойлер

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

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

#define SEVEN_SEGM_LED_IND_H

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

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

//==================
#define SEGM_A_DDR  DDRC
#define SEGM_A_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_B_DDR  DDRC
#define SEGM_B_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_C_DDR  DDRC
#define SEGM_C_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_D_DDR  DDRC
#define SEGM_D_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_E_DDR  DDRC
#define SEGM_E_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_F_DDR  DDRC
#define SEGM_F_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_G_DDR  DDRC
#define SEGM_G_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_H_DDR  DDRC
#define SEGM_H_PORT PORTC
//==================

//==================
//----------------------------- Пины МК ----------------------------------
//-------------------------- Segments Outputs ----------------------------
#define S_A_OUT     6
#define S_B_OUT     7 //     A
#define S_C_OUT     3 //   F   B
#define S_D_OUT     2 //     G
#define S_E_OUT     1 //   E   C
#define S_F_OUT     5 //     D  H
#define S_G_OUT     4
#define S_H_OUT     0
//==================

//==================
#define COMM_1_DDR  DDRA
#define COMM_1_PORT PORTA
//------------------------------------------------------------------------
#define COMM_2_DDR  DDRA
#define COMM_2_PORT PORTA
//------------------------------------------------------------------------
#define COMM_3_DDR  DDRA
#define COMM_3_PORT PORTA
//------------------------------------------------------------------------
#define COMM_4_DDR  DDRA
#define COMM_4_PORT PORTA
//------------------------------------------------------------------------
#define COMM_5_DDR  DDRA
#define COMM_5_PORT PORTA
//------------------------------------------------------------------------
#define COMM_6_DDR  DDRA
#define COMM_6_PORT PORTA
//==================

//==================
//----------------------------- Пины МК ----------------------------------
//-------------------------- Commons Outputs -----------------------------
#define C_1_OUT    2
#define C_2_OUT    3
#define C_3_OUT    4
#define C_4_OUT    5
#define C_5_OUT    6
#define C_6_OUT    7
//------------------------------------------------------------------------
#define C_1        0
#define C_2        1
#define C_3        2
#define C_4        3
#define C_5        4
#define C_6        5
//==================

//==================
//------------------------- Segment numeric value ------------------------
#define S_A        0
#define S_B        1
#define S_C        2
#define S_D        3
#define S_E        4
#define S_F        5
#define S_G        6
#define S_H        7
//==================

//==================
#define ZERO      (_BV(S_A) | _BV(S_B) | _BV(S_C) | _BV(S_D) | _BV(S_E) | _BV(S_F))
#define ONE       (_BV(S_B) | _BV(S_C))
#define TWO       (_BV(S_A) | _BV(S_B) | _BV(S_D) | _BV(S_E) | _BV(S_G))
#define THREE     (_BV(S_A) | _BV(S_B) | _BV(S_C) | _BV(S_D) | _BV(S_G))
#define FOUR      (_BV(S_B) | _BV(S_C) | _BV(S_F) | _BV(S_G))
#define FIVE      (_BV(S_A) | _BV(S_C) | _BV(S_D) | _BV(S_F) | _BV(S_G))
#define SIX       (_BV(S_A) | _BV(S_C) | _BV(S_D) | _BV(S_E) | _BV(S_F) | _BV(S_G))
#define SEVEN     (_BV(S_A) | _BV(S_B) | _BV(S_C))
#define EIGHT     (_BV(S_A) | _BV(S_B) | _BV(S_C) | _BV(S_D) | _BV(S_E) | _BV(S_F) | _BV(S_G))
#define NINE      (_BV(S_A) | _BV(S_B) | _BV(S_C) | _BV(S_D) | _BV(S_F) | _BV(S_G))
#define SPACE      0

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

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

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

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

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

//==================
#define HI  true
#define LOW false
//==================

//==================
void Set_Commons_Level (bool level);
void Set_Segments_Level (bool level);
//==================

//==================
void handle_commons (void);
void handle_segments (void); // 306 тактов, 19,13 мкс.
//==================

//==================
typedef struct port_pin_t
{
   volatile u08 * port;
   u08            mask;
} port_pin_t;
//==================

//==================
// Прогон

//==================

//==================
#endif
//==================
*.c
Спойлер

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

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

//==================
struct port_pin_t __flash commons_pins [6] =
{
   {&COMM_1_PORT, _BV(C_1_OUT)},
   {&COMM_2_PORT, _BV(C_2_OUT)},
   {&COMM_3_PORT, _BV(C_3_OUT)},
   {&COMM_4_PORT, _BV(C_4_OUT)},
   {&COMM_5_PORT, _BV(C_5_OUT)},
   {&COMM_6_PORT, _BV(C_6_OUT)}
};
//==================

//==================
struct port_pin_t __flash segments_pins [8] =
{
   {&SEGM_A_PORT, _BV(S_A_OUT)},   // A
   {&SEGM_B_PORT, _BV(S_B_OUT)},   // B
   {&SEGM_C_PORT, _BV(S_C_OUT)},   // C
   {&SEGM_D_PORT, _BV(S_D_OUT)},   // D
   {&SEGM_E_PORT, _BV(S_E_OUT)},   // E
   {&SEGM_F_PORT, _BV(S_F_OUT)},   // F
   {&SEGM_G_PORT, _BV(S_G_OUT)},   // G
   {&SEGM_H_PORT, _BV(S_H_OUT)}    // H
};
//==================

//==================
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;
}
//==================

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


void set_proc_7_segm_ind_on (void)
{
   _proc_7_segm_ind = 1;
}

void set_proc_7_segm_ind_off (void)
{
   _proc_7_segm_ind = 0;
}

void proc_7_segm_ind (void)
{
   switch (_proc_7_segm_ind)
   {
      case 0:
         break;

      case 1:
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//--------------------------- Segments -----------------------------------
         set_bit (SEGM_A_DDR, S_A_OUT);
         set_bit (SEGM_B_DDR, S_B_OUT);
         set_bit (SEGM_C_DDR, S_C_OUT);
         set_bit (SEGM_D_DDR, S_D_OUT);
         set_bit (SEGM_E_DDR, S_E_OUT);
         set_bit (SEGM_F_DDR, S_F_OUT);
         set_bit (SEGM_G_DDR, S_G_OUT);
         set_bit (SEGM_H_DDR, S_H_OUT);
//--------------------------- Commons ------------------------------------
         set_bit (COMM_1_DDR, C_1_OUT);
         set_bit (COMM_2_DDR, C_2_OUT);
         set_bit (COMM_3_DDR, C_3_OUT);
         set_bit (COMM_4_DDR, C_4_OUT);
         set_bit (COMM_5_DDR, C_5_OUT);
         set_bit (COMM_6_DDR, C_6_OUT);

         Set_Commons_Level (HI);
         Set_Segments_Level (LOW);

         dsp_buf [0] = 1;
         dsp_buf [1] = 2;
         dsp_buf [2] = 3;
         dsp_buf [3] = 4;
         dsp_buf [4] = 5;
         dsp_buf [5] = 6;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         cnt_commons = 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))
         {
            handle_commons ();
            handle_segments ();

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

      default:
         break;
   }
}
//==================

//==================
static bool commons_level;
//------------------------------------------------------------------------
void Set_Commons_Level (bool level)
{
   commons_level = level;
}
//------------------------------------------------------------------------
void handle_commons (void)
{
   u08 a = tab_bv [cnt_commons];

   volatile u08 *p;

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

      if (commons_level == HI)
      {
         if (a & (1<<0))
            *p |= commons_pins [i] .mask;
         else
            *p &= (~commons_pins [i] .mask);
      }
      else
      {
         if (a & (1<<0))
            *p &= (~commons_pins [i] .mask);
         else
            *p |= commons_pins [i] .mask;
      }
   }
}
//==================

//==================
static bool segments_level;
//------------------------------------------------------------------------
void Set_Segments_Level (bool level)
{
   segments_level = level;
}
//------------------------------------------------------------------------
void handle_segments (void)
{
   u08 a = table_7_segm_char [dsp_buf [cnt_commons]];

   volatile u08 *p;

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

      if (segments_level == HI)
      {
         if (a & (1<<0))
            *p |= segments_pins [i] .mask;
         else
            *p &= (~segments_pins [i] .mask);
      }
      else
      {
         if (a & (1<<0))
            *p &= (~segments_pins [i] .mask);
         else
            *p |= segments_pins [i] .mask;
      }
   }
}
//==================
Архив с проектом. МК ATMEGA8535. Тактовая частота 16 МГц. В архиве файл для симуляции в AVR-Studio.
SEVEN_SEGM_PROJECT.rar
(438.8 КБ) 183 скачивания
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

Demiurg писал(а):Реализовано
лучше бы о том, сколько там тактов на что и т.п. "писькомерные" параметры сообщили бы
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

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

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

void handle_commons (void)
{
   u08 a = tab_bv [cnt_commons];

   volatile u08 *p;

   if (commons_level == HI)
   {
      for (u08 i = 0; i < MAX_LED_INDS; i++, a >>= 1)
      {
         p = commons_pins [i] .port;

         if (a & (1<<0))
            *p |= commons_pins [i] .mask;
         else
            *p &= (~commons_pins [i] .mask);
      }
   }
   else
   {
      for (u08 i = 0; i < MAX_LED_INDS; i++, a >>= 1)
      {
         p = commons_pins [i] .port;

         if (a & (1<<0))
            *p &= (~commons_pins [i] .mask);
         else
            *p |= commons_pins [i] .mask;
      }
   }
}

void handle_segments (void)
{
   u08 a = table_7_segm_char [dsp_buf [cnt_commons]];

   volatile u08 *p;

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

         if (a & (1<<0))
            *p |= segments_pins [i] .mask;
         else
            *p &= (~segments_pins [i] .mask);
      }
   }
   else
   {
      for (u08 i = 0; i < 8; i++, a >>= 1)
      {
         p = segments_pins[i].port;

         if (a & (1<<0))
            *p &= (~segments_pins [i] .mask);
         else
            *p |= segments_pins [i] .mask;
      }
   }
}
Ответить

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