Семисегментный LED-индикатор. Эффекты анимации
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
Я когда-то задавался вопросом, можно ли выводить на порты по индексу. Я не знаю, когда добавили эту плюшку, но в то время мне говорили, что это на AVR невозможно. Я попробую ваш пример. Что из того получится.
ARV, Reflector кто там еще. Предлагаю добить. Задачи: Произвольные порты, выбор активного уровня. Вы мне тут показали, что вроде как можно по индексу на порты вывести. Покажите макросы и добиваем совместными усилиями. Результат выложим тут.
Этот топик на этом форуме впервые за долгое время очень информативен и плодотворен.
ARV, Reflector кто там еще. Предлагаю добить. Задачи: Произвольные порты, выбор активного уровня. Вы мне тут показали, что вроде как можно по индексу на порты вывести. Покажите макросы и добиваем совместными усилиями. Результат выложим тут.
Этот топик на этом форуме впервые за долгое время очень информативен и плодотворен.
Последний раз редактировалось Demiurg Пн авг 24, 2020 16:36:01, всего редактировалось 1 раз.
- Реклама
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
меньше надо глупости слушать.Demiurg писал(а):мне говорили, что это на AVR невозможно
со времен WinAVR это работает, поскольку у AVR порты ввода-вывода отображены на адреса ОЗУ, и нет таких портов, к которым не разрешен доступ командами lds-sts, (наоборот - есть: бывают порты, к которым нельзя обратиться командами in-out).
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
ARV, не могу понять, где в вашем примере условие, по которому заканчивается цикл for? Заработало, теперь осталось сделать на основе вашего примера выбор активного уровня. Если честно, такой (как у вас) способ впервые вижу...
Re: Семисегментный LED-индикатор. Эффекты анимации
[uquote="Demiurg",url="/forum/viewtopic.php?p=3883190#p3883190"]Предлагаю добить. Задачи: Произвольные порты, выбор активного уровня. Вы мне тут показали, что вроде как можно по индексу на порты вывести. Покажите макросы и добиваем совместными усилиями.[/uquote]
Шаблоны так не работают... Допустим есть такой список пинов:
Фактически pins - это тип, на данном этапе он никакого реального кода не генерит. Теперь вызовем метод write():
В этот момент создает экземпляр класса и в первую очередь внутри него из первоначального списка формируются индексированный список, т.е. пины нумеруются, потому что потом они будут из списков удаляться, а индекс будет нужен. Кроме того списки могут вместо пинов принимать другие списки, но в индексированном списке уже все разворачивается до одних пинов. Также создается список портов присутствующих в списке, проверяется наличие дубликатов пинов и вычисляет размер развернутого списка. Все эти дополнительные списки существуют чисто виртуально на этапе компиляции. Но основные расчеты начинаются когда дело доходит непосредственно до write(), там компилятор сортирует пины по портам и для каждого порта ищет последовательности пинов которые можно было бы получить за один заход по вычисленной маске. В данном случае для порта PA будет получена маска 0x16(для PA4, PA2, PA1), 0x40(для PA6) и еще одна специфическая маска для портов STM32. Для AVR, насколько помню, получилось бы что-то типа такого:
Естественно это эффективнее, чем:
А препроцессор просто подменяет один ничего для него не значащий текст на другой, потому никакими макросами шаблоны не заменишь.
Шаблоны так не работают... Допустим есть такой список пинов:
Код: Выделить всё
using pins = PinList<PA6, PA4, PB3, PA2, PA1>;Код: Выделить всё
pins:write(val);Код: Выделить всё
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-индикатор. Эффекты анимации
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-индикатор. Эффекты анимации
это, в принципе, не факт. во всяком случае, совсем не очевидно: сдвиги компенсируют наличие условных переходов, так что будет ли выигрыш - вопрос.Reflector писал(а):Естественно это эффективнее
как это где? где ему и положено быть: на втором месте в теле оператора for:Demiurg писал(а):где в вашем примере условие, по которому заканчивается цикл for?
специльно выделилARV писал(а):for(uint8_t i=0, m=1; m; i++, m<<=1)
как я уже говорил, не такая уж и большая расплата: у вас былоDemiurg писал(а):Но расплата - разворот в дизасме.
по моим оценкам у меня ровно посредине между вашими результатами: порядка 300 тактов. так что вполне приемлемо, имхо. но по восприятию кода - и сравнивать не возьмусьDemiurg писал(а):133 такта, 8.31 мкс при тактовой частоте 16 мгц.
При втором методе 545 тактов и 34 мкс
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
Самсусамыч
Re: Семисегментный LED-индикатор. Эффекты анимации
[uquote="ARV",url="/forum/viewtopic.php?p=3883183#p3883183"]по листингу у меня вышло около 235 тактов на вывод символа, не считая пролога-эпилога обработчика прерывания.[/uquote]
Значит и мой вариант вполне себе ничего…
у меня тоже вышло 235 тактов на вывод цифры, начиная с момента вызова прерывания и выхода из него. 
Значит и мой вариант вполне себе ничего…
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
у меня без учета этого.Самсусамыч писал(а):начиная с момента вызова прерывания и выхода из него
я уже неоднократно свою позицию говорил: если нет острой необходимости, то для чего экономить такты/байты? гораздо правильнее, имхо, облегчить свою участь, т.е. написать просто, легко, понятно и быстро, а уж будет оно 5 мкС или 10 мкС исполняться - не важно. и вот как раз в этом случае есть смысл делать универсальные библиотеки - лишь бы все просто и легко.
а когда нужда заставляет - тогда в руки ассемблер, и вперед! но у меня нужды давно не возникало в этом...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
[uquote="ARV",url="/forum/viewtopic.php?p=3883235#p3883235"]...[/uquote]
Я на сегодня закончил. Что у меня получилось с вашим примером. IAR, максимальная оптимизация balanced. Более 300 тактов. И это только вывод сегментов. А у вас в примере только он и есть. Вывода общих выводов нет. Кстати, получилось сделать выбор активного сигнала.
Завтра ещё поэкспериментирую, сделаю вывод общих выводов. Отпишусь.
Я на сегодня закончил. Что у меня получилось с вашим примером. IAR, максимальная оптимизация balanced. Более 300 тактов. И это только вывод сегментов. А у вас в примере только он и есть. Вывода общих выводов нет. Кстати, получилось сделать выбор активного сигнала.
Завтра ещё поэкспериментирую, сделаю вывод общих выводов. Отпишусь.
Последний раз редактировалось Demiurg Пн авг 24, 2020 19:43:20, всего редактировалось 1 раз.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
и чо?Demiurg писал(а):А у вас в примере только он и есть
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Семисегментный LED-индикатор. Эффекты анимации
[uquote="ARV",url="/forum/viewtopic.php?p=3883235#p3883235"]это, в принципе, не факт. во всяком случае, совсем не очевидно: сдвиги компенсируют наличие условных переходов, так что будет ли выигрыш - вопрос.[/uquote]
Да ладно... В первом случае одно чтение из регистра, одна запись, 5 бинарных операций и 3 сдвига(может и 2), итого ~10 тактов.
Во-втором случае одно чтение/запись, 5 бинарных операций, 4 двухтактовых перехода и потом еще опционально 3+3+3+3, итого минимум 15 тактов, максимум - 27, в среднем - 21.
Да ладно... В первом случае одно чтение из регистра, одна запись, 5 бинарных операций и 3 сдвига(может и 2), итого ~10 тактов.
Во-втором случае одно чтение/запись, 5 бинарных операций, 4 двухтактовых перехода и потом еще опционально 3+3+3+3, итого минимум 15 тактов, максимум - 27, в среднем - 21.
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
[uquote="ARV",url="/forum/viewtopic.php?p=3883254#p3883254"]и чо?[/uquote]
Чо по китайский (_._).
Конечно, спасибо за пример. В будущем пригодится, давно искал вывод в порты по индексу.
Но, но... Расплата высока. Проще в лоб. По первому способу. Да, писанины порядочно. Но выхлоп эффективен.
У вас легко, просто, выхлоп же... А диалог разгорелся про эффективность.
Там "легко, просто", там. В итоге набирается по тактам при таком подходе.
Так что, диалог про эффективность считаю закрытым.
Краткость кода, "легко и просто" - не равно эффективность.
Чо по китайский (_._).
Но, но... Расплата высока. Проще в лоб. По первому способу. Да, писанины порядочно. Но выхлоп эффективен.
У вас легко, просто, выхлоп же... А диалог разгорелся про эффективность.
Там "легко, просто", там. В итоге набирается по тактам при таком подходе.
Так что, диалог про эффективность считаю закрытым.
Краткость кода, "легко и просто" - не равно эффективность.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
у меня абсолютно ничего не разгоралось. для меня важна эффективность моего труда, а микроконтроллер - он кремниевый, не потеет и не устаёт, ему до лампочки, что делать: в главном цикле nop-ы исполнять или расчеты сегментов делать.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Serzh2000
- Опытный кот
- Сообщения: 867
- Зарегистрирован: Пт фев 27, 2015 12:00:53
- Откуда: Рязанская область
Re: Семисегментный LED-индикатор. Эффекты анимации
у меня тоже получилось нарисовать эффект (какой автор в начале рисовал) и циферки
даже в протеусе работает
#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 -=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
даже в протеусе работает
Спойлер
/*****************************************************#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-индикатор. Эффекты анимации
[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]
Видео в студию.
Про микроконтроллер абсолютно согласен. Про эффективность мы опять пришли в тупик. Вы о своём, я о своём. На этом закончим. Тем более, что я ещё не закончил эксперименты.
Добавлено after 3 minutes 38 seconds:
[uquote="Serzh2000",url="/forum/viewtopic.php?p=3883267#p3883267"]...[/uquote]
Видео в студию.
- Serzh2000
- Опытный кот
- Сообщения: 867
- Зарегистрирован: Пт фев 27, 2015 12:00:53
- Откуда: Рязанская область
Re: Семисегментный LED-индикатор. Эффекты анимации
любую фигуру можно нарисовать
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
В бегущем червячке на вертикальных участках сегменты надо зажигать через один, чтобы сохранить пунктирность 
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
Я закончил с экспериментами. Выкладываю окончательный вариант. Реализовано: произвольный выбор портов и пинов. Выбор логики управления сегментами и разрядами. За идею обращения к портам по индексу ARV отдельная благодарность.
Проект проверен на отладочной плате STK-500.
*.h
*.c
Архив с проектом. МК ATMEGA8535. Тактовая частота 16 МГц. В архиве файл для симуляции в AVR-Studio.
Проект проверен на отладочной плате 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
//==================
Спойлер
Код: Выделить всё
//==================
#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;
}
}
}
//==================
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
лучше бы о том, сколько там тактов на что и т.п. "писькомерные" параметры сообщили быDemiurg писал(а):Реализовано
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
В текущей версии проекта прогон вывода сегментов и разрядов занимает 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;
}
}
}


