Семисегментный LED-индикатор. Эффекты анимации
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
Нет. Это я когда то баловался с эффектами. BAM.
- Реклама
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
Мой вариант эффектов. . Эффекты конструировал с помощью программы LEDx8. Архив с проектом прикрепил. МК ATMEGA8535. Частота кварца 16 МГц. Таблица с эффектами в файле proc_device.c. Обработчик индикатров в файле seven_segm_led_ind.c
Re: Семисегментный LED-индикатор. Эффекты анимации
[uquote="BlackKilkennyCat",url="/forum/viewtopic.php?p=3882839#p3882839"]Просто у всех разные среды и мк, да и ещё и разные стили.[/uquote]
Вот по этому-то и не получается толком покурить.
Ещё и столько понавыкладывали. ) Нельзя на каком-то варианте чуть по-подробнее?
Вот по этому-то и не получается толком покурить.
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
В этой теме вам и словами раскидали и примеров накидали, хоть анусом жуй. Абсолютно без разницы на каком языке вы пишете, каким стилем. Любой проект начинается с ТЗ, с постановки задачи. Берете бумажку и начинаете. Сверху вниз. От устройства к функционалу. И когда вы на бумаге будете видеть хотя бы размытые очертания того, что вы хотите, только тогда у вас дело сдвинется.
В моих примерах сделано на таблицах. Кадры, которые по таймеру выплевываются в буфер дисплея. Оттуда также по таймеру выводится на индикаторы. Структура таблицы временные параметры и что выводим в текущем кадре.
Алгоритмы, бумага и карандаш вам в помощь.
Лично я уже давно во многих случаях даже и этим не пользуюсь. Всё в уме проворачиваю.
В моих примерах сделано на таблицах. Кадры, которые по таймеру выплевываются в буфер дисплея. Оттуда также по таймеру выводится на индикаторы. Структура таблицы временные параметры и что выводим в текущем кадре.
Алгоритмы, бумага и карандаш вам в помощь.
Лично я уже давно во многих случаях даже и этим не пользуюсь. Всё в уме проворачиваю.
- Serzh2000
- Опытный кот
- Сообщения: 867
- Зарегистрирован: Пт фев 27, 2015 12:00:53
- Откуда: Рязанская область
Re: Семисегментный LED-индикатор. Эффекты анимации
C эффектами все отлично! а с яркостью на каждом сегменте чтоб своя, как сделать?
#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 6
#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(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[SCR_SZ] = {
pn(D,0),
pn(D,1),
pn(D,2),
pn(D,3),
pn(D,4),
pn(D,5)
};
#define COM_CAT ((PIND & _BV(7)) == 0)
extern uint8_t data[SCR_SZ];
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 = 0;
}
}
int main(void){
DDRB = 255;
DDRC = 255;
DDRD = 0x7F;
PORTD = 0x80;
TCCR0 = 4;
TIMSK = _BV(TOIE0);
sei();
while(1){
const FLASH char effect_1[][SCR_SZ]={
{F+E, 0, 0, 0, 0, 0},
{F+E+B+C, 0, 0, 0, 0, 0},
{F+E+B+C, F+E, 0, 0, 0, 0},
{F+E+B+C, F+E+B+C, 0, 0, 0, 0},
{F+E+B+C, F+E+B+C, F+E, 0, 0, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, 0, 0, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E, 0, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, 0, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C},
};
unsigned int sizeArray;
sizeArray = sizeof(effect_1)/(sizeof(char)*SCR_SZ);
clr();
_delay_ms(200);
//for(int8_t a=0; a < 5; a++) // число повторов
for(int8_t i=0; i < sizeArray; i++){
scr[0] = effect_1[0];
scr[1] = effect_1[1];
scr[2] = effect_1[2];
scr[3] = effect_1[3];
scr[4] = effect_1[4];
scr[5] = effect_1[5];
_delay_ms(2500);
}
}
}

Спойлер
#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 6
#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(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[SCR_SZ] = {
pn(D,0),
pn(D,1),
pn(D,2),
pn(D,3),
pn(D,4),
pn(D,5)
};
#define COM_CAT ((PIND & _BV(7)) == 0)
extern uint8_t data[SCR_SZ];
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 = 0;
}
}
int main(void){
DDRB = 255;
DDRC = 255;
DDRD = 0x7F;
PORTD = 0x80;
TCCR0 = 4;
TIMSK = _BV(TOIE0);
sei();
while(1){
const FLASH char effect_1[][SCR_SZ]={
{F+E, 0, 0, 0, 0, 0},
{F+E+B+C, 0, 0, 0, 0, 0},
{F+E+B+C, F+E, 0, 0, 0, 0},
{F+E+B+C, F+E+B+C, 0, 0, 0, 0},
{F+E+B+C, F+E+B+C, F+E, 0, 0, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, 0, 0, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E, 0, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, 0, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, 0},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E},
{F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C, F+E+B+C},
};
unsigned int sizeArray;
sizeArray = sizeof(effect_1)/(sizeof(char)*SCR_SZ);
clr();
_delay_ms(200);
//for(int8_t a=0; a < 5; a++) // число повторов
for(int8_t i=0; i < sizeArray; i++){
scr[0] = effect_1[0];
scr[1] = effect_1[1];
scr[2] = effect_1[2];
scr[3] = effect_1[3];
scr[4] = effect_1[4];
scr[5] = effect_1[5];
_delay_ms(2500);
}
}
}
- Реклама
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
Меньше прерываниями увлекаться. Это уже программный шим. А значит, убрать все долгие обработчик прерываний и переползать в основной цикл. Либо переходить на статический режим и сдвиговые регистры. Тут анализировать нужно, как оптимальнее. Перед коммутацией индикаторов приготовить данные, значения шима. А когда коммутация, вывести.
- Serzh2000
- Опытный кот
- Сообщения: 867
- Зарегистрирован: Пт фев 27, 2015 12:00:53
- Откуда: Рязанская область
Re: Семисегментный LED-индикатор. Эффекты анимации
Вот общую яркость забацал. а по разрядам чет не соображу.
#include <delay.h>
unsigned char digit_out[5], // буфер экрана (нумерация от 0 до 4 разрядa)
cur_dig; // тек.высвечиваемый символ (позиция)
unsigned int z=500, // ms для паузы после эффекта
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,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,
123,124,125,126,127};
// ---------------- Timer 2 overflow interrupt service routine -----------------------------
interrupt [TIM2_OVF] void timer2_ovf_isr(void){
PORTC&=0b00000000; // потушить все (разряды - off)
PORTB=~digits[digit_out[cur_dig]];
PORTC |= (1<<cur_dig); // засветить нужный разряд (бит знакоместа - on)
cur_dig++; if (cur_dig >= 5) {
cur_dig = 0;
OCR2 = yarkost;
}
}// ----------------------------------------------------------------------------------------
// ------------------ Timer2 output compare interrupt service routine ----------------------
interrupt [TIM2_COMP] void timer2_comp_isr(void){
PORTC&=0b00000000;
}// ----------------------------------------------------------------------------------------
//=================== main ==========
//основаня функция
void main(void){
digit_out[0]=0; // очистить экран
digit_out[1]=0;
digit_out[2]=0;
digit_out[3]=0;
digit_out[4]=0;
//настройка портов
PORTB=0b00000000;
DDRB=0b11111111;
PORTC=0b00000000;
DDRC=0b00111111;
PORTD=0b00000000;
DDRD=0b00000000;
TCCR2=0x04;
TIMSK=0b11000000;
// 0b11000001
// || | |
// || | Timer0
// || Timer1
// |Timer2
//
#asm("sei") // Глобальные прерывания включения
// -------------------------------- рабочая часть ------------------------------------------
while (1) {
yarkost=255;
digit_out[0] = 118; //H
digit_out[1] = 121; //E
digit_out[2] = 56; //L
digit_out[3] = 56; //L
digit_out[4] = 63; //O
while(yarkost>0)
{
yarkost-=5;
delay_ms(3);
}
delay_ms(z);
}; // ----------------------------- рабочая часть (end) ------------------------------------
} // ================= end main ======
//
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- The End -=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
чтоб например каждый разряд (буква) светилась своей яркостью
Спойлер
#include <mega8.h>#include <delay.h>
unsigned char digit_out[5], // буфер экрана (нумерация от 0 до 4 разрядa)
cur_dig; // тек.высвечиваемый символ (позиция)
unsigned int z=500, // ms для паузы после эффекта
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,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,
123,124,125,126,127};
// ---------------- Timer 2 overflow interrupt service routine -----------------------------
interrupt [TIM2_OVF] void timer2_ovf_isr(void){
PORTC&=0b00000000; // потушить все (разряды - off)
PORTB=~digits[digit_out[cur_dig]];
PORTC |= (1<<cur_dig); // засветить нужный разряд (бит знакоместа - on)
cur_dig++; if (cur_dig >= 5) {
cur_dig = 0;
OCR2 = yarkost;
}
}// ----------------------------------------------------------------------------------------
// ------------------ Timer2 output compare interrupt service routine ----------------------
interrupt [TIM2_COMP] void timer2_comp_isr(void){
PORTC&=0b00000000;
}// ----------------------------------------------------------------------------------------
//=================== main ==========
//основаня функция
void main(void){
digit_out[0]=0; // очистить экран
digit_out[1]=0;
digit_out[2]=0;
digit_out[3]=0;
digit_out[4]=0;
//настройка портов
PORTB=0b00000000;
DDRB=0b11111111;
PORTC=0b00000000;
DDRC=0b00111111;
PORTD=0b00000000;
DDRD=0b00000000;
TCCR2=0x04;
TIMSK=0b11000000;
// 0b11000001
// || | |
// || | Timer0
// || Timer1
// |Timer2
//
#asm("sei") // Глобальные прерывания включения
// -------------------------------- рабочая часть ------------------------------------------
while (1) {
yarkost=255;
digit_out[0] = 118; //H
digit_out[1] = 121; //E
digit_out[2] = 56; //L
digit_out[3] = 56; //L
digit_out[4] = 63; //O
while(yarkost>0)
{
yarkost-=5;
delay_ms(3);
}
delay_ms(z);
}; // ----------------------------- рабочая часть (end) ------------------------------------
} // ================= end main ======
//
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- The End -=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
- Вложения
-
- ZveZda (1).zip
- (980.2 КБ) 158 скачиваний
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
давным давно предлагал такой способ: http://arv.radioliga.com/content/view/101/49/Serzh2000 писал(а):чтоб например каждый разряд (буква) светилась своей яркостью
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Ivanoff-iv
- Друг Кота
- Сообщения: 7077
- Зарегистрирован: Пт ноя 11, 2016 05:48:09
- Откуда: Сердце Пармы
Re: Семисегментный LED-индикатор. Эффекты анимации
индивидуальная яркость делается легко:
в прерывании по переполнению:
{обновляем сегменты из массива буфера экрана;
включаем требуемый общий электрод разряда
заносим в регистр сравнения параметр яркости из массива яркостей;
сдвигаем счётчик отображаемого разряда;}
в прерывании по совпадению:
{забираем данные с приэкранной клавиатуры; (если она есть)
отключаем все общие разрядные электроды;}
в прерывании по переполнению:
{обновляем сегменты из массива буфера экрана;
включаем требуемый общий электрод разряда
заносим в регистр сравнения параметр яркости из массива яркостей;
сдвигаем счётчик отображаемого разряда;}
в прерывании по совпадению:
{забираем данные с приэкранной клавиатуры; (если она есть)
отключаем все общие разрядные электроды;}
Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
- Serzh2000
- Опытный кот
- Сообщения: 867
- Зарегистрирован: Пт фев 27, 2015 12:00:53
- Откуда: Рязанская область
Re: Семисегментный LED-индикатор. Эффекты анимации
Да действительно просто!!!
Пример можно глянуть
Пример можно глянуть
- Ivanoff-iv
- Друг Кота
- Сообщения: 7077
- Зарегистрирован: Пт ноя 11, 2016 05:48:09
- Откуда: Сердце Пармы
Re: Семисегментный LED-индикатор. Эффекты анимации
Да, пожалуйста:
описание сегментов (от ARV)
зажигание происходит в прерывыании совпадения т.к. счетчик работает в СТС режиме (подстраивал частоту хода, тут это не принципиально) инкремент счетчика сделан после вывода из-за того, что эта операция может занимать разное количество времени - так она не повлияет на яркость экрана (далее, в коде, этот нюанс учтен)
описание сегментов (от ARV)
Спойлер
Код: Выделить всё
//#define CatMSC (0x0F<<2) //4 пина по порядку со 2го
//Описание цифр семисегментного индикатора
//соответствие сегмента и номера ноги порта
#define N_A 0
#define N_B 2
#define N_C 4
#define N_D 6
#define N_E 7
#define N_F 1
#define N_G 3
#define N_DP 5
//расстановка единиц в маске
#define _A (1<<N_A)
#define _B (1<<N_B)
#define _C (1<<N_C)
#define _D (1<<N_D)
#define _E (1<<N_E)
#define _F (1<<N_F)
#define _G (1<<N_G)
#define _DP (1<<N_DP)
//знакогенератор
#define _0 ~(_A|_B|_C|_D|_E|_F )
#define _1 ~( _B|_C )
#define _2 ~(_A|_B| _D|_E| _G)
#define _3 ~(_A|_B|_C|_D| _G)
#define _4 ~( _B|_C| _F|_G)
#define _5 ~(_A| _C|_D| _F|_G)
#define _6 ~(_A| _C|_D|_E|_F|_G)
#define _7 ~(_A|_B|_C )
#define _8 ~(_A|_B|_C|_D|_E|_F|_G)
#define _9 ~(_A|_B|_C|_D| _F|_G)
#define _a ~(_A|_B|_C| _E|_F|_G)
#define _b ~( _C|_D|_E|_F|_G)
#define _c ~(_A| _D|_E|_F| )
#define _d ~( _B|_C|_D|_E| _G)
#define _e ~(_A| _D|_E|_F|_G)
#define _f ~(_A| _E|_F|_G)
#define _Z ~(0 ) //выкюченный разряд
#define _N ~( _G) // "-"
#define _S ~(_A |_C|_D |_F|_G)
#define _T ~( _D|_E|_F|_G)
#define _O ~(_A|_B|_C|_D|_E|_F )
#define _P ~(_A|_B |_E|_F|_G)
flash unsigned char DIG[]={_0,_1,_2,_3,_4,_5,_6,_7,_8,_9};
#define _OFF PORTD&=~(CatMSC) // гасим разряды
#define _ON PORTD|=((1<<2)<<NUM) //зажигаем разряд (они идут по порядку со 2го)
#define _N_Dig PORTB=DIGS[NUM]; //включаем сегменты в разряде согласно данных в ячейке буфераСпойлер
Код: Выделить всё
#define KEY_IN (PINA&(1<<0)) //вход с клавиатуры пинА.0
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
static unsigned char NUM; //текущий высвечиваемый разряд
_N_Dig; //выводим сегменты
_ON; // зажигаем разряд
OCR0B=LIGHT[NUM]; //устанавливаем яркость для разряда
NUM=++NUM&3; //переключаем номер выводимого разряда по кругу от 0 до 3.
}
// гашение дисплея
interrupt [TIM0_COMPB] void timer0_compb_isr(void)
{
//if (KEY_IN) KeyP0|=PORTD&CatMSC; //считываем клавиатуру (накопитель сбрасывается в другом месте)
_OFF; //выключаем все разряды (среди них окажется и включенный)
}Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
Купи, скачай книги по МК AVR, и ищи там примеры работы с таймерами. Потренируйся на них, потом сам поэкспериментируй. Задание временных интервалов разной длительности, всякие генераторы. ШИМ. И так далее.
Я только что сделал так: выставили сегменты и общие выводы, я не стал заморачиваться, один таймер у меня отвечает за переключение общих выводов и сегментов, второй таймер отвечает за время свечения индикаторов. Можно на одном таймере сделать, но это зависит от: используемого МК, количества аппаратных таймеров и проекта, сколько и для чего используются таймеры.
Прошу обратить внимание, что мне пришлось в проекте объединить два способа переключения сегментов и общих выводов. В прерывании я заставил компилятор дергать пинами командами SBI CBI.

Я только что сделал так: выставили сегменты и общие выводы, я не стал заморачиваться, один таймер у меня отвечает за переключение общих выводов и сегментов, второй таймер отвечает за время свечения индикаторов. Можно на одном таймере сделать, но это зависит от: используемого МК, количества аппаратных таймеров и проекта, сколько и для чего используются таймеры.
Спойлер
Код: Выделить всё
static u08 light_inds [MAX_LED_INDS] = {90, 30, 15, 15, 30, 90};
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;
set_bit (SFIOR, PSR10);
TCNT0 = 0;
OCR0 = (250 / 100) * light_inds [cnt_commons]; // 250 - время между переключениями. 100 % - вся яркость. light_inds заданная яркость.
TCCR0 = ((1<<CS01) | (1<<CS00));
set_bit (TIMSK, OCIE0);
}
//==================
#pragma vector = TIMER0_COMP_vect
__interrupt void HandleIntTimerComp0 (void)
{
clr_bit (TIMSK, OCIE0);
OCR0 = 0;
TCCR0 = 0;
if (commons_level == HI)
tab_commons_low [cnt_commons] ();
else
tab_commons_hi [cnt_commons] ();
}
//==================
Последний раз редактировалось Demiurg Вт сен 01, 2020 15:36:55, всего редактировалось 2 раза.
Re: Семисегментный LED-индикатор. Эффекты анимации
У меня была прожка на ассемблере - 4 позиционник с раздельной регулировкой яркости на каждой позиции.
Или с применением регистр-расширителей - 4 строки у каждой из которых своя яркость.
База - Т1 со всеми добавками. Правда в проекте схемки нету...
А уж формирование эффектов и самих данных - это задачка дополнительная и не зависимая от обработчика вывода на дисплей.

Или с применением регистр-расширителей - 4 строки у каждой из которых своя яркость.
База - Т1 со всеми добавками. Правда в проекте схемки нету...
А уж формирование эффектов и самих данных - это задачка дополнительная и не зависимая от обработчика вывода на дисплей.
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
Хм, только у меня переключение индикаторов в основном цикле. Ну да, непросто реализовать, шоп не мерцало, не мигало...
Re: Семисегментный LED-индикатор. Эффекты анимации
Современные МК позволяют простейший контроллер динамической индикации повесить на прерывания по таймеру.
Итогом имеем как бы два независимо идущих процесса - собственно регенерация индикатора и программа пользователя.
Минус - потеря одного таймера и высшего приоритета в прерываниях.
Как то на "чистом СИ" должно выглядеть - то уж не мне судить.
В адуринке тандем внешнего прерывания и tone для "псевдопараллельного процесса" можно использовать (это ежли только средства "референса", не забираясь "в глубины" делать).

Итогом имеем как бы два независимо идущих процесса - собственно регенерация индикатора и программа пользователя.
Минус - потеря одного таймера и высшего приоритета в прерываниях.
Как то на "чистом СИ" должно выглядеть - то уж не мне судить.
В адуринке тандем внешнего прерывания и tone для "псевдопараллельного процесса" можно использовать (это ежли только средства "референса", не забираясь "в глубины" делать).
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
Выше подправил свое сообщение.
Re: Семисегментный LED-индикатор. Эффекты анимации
Serzh2000, держи код
Спойлер
Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#define F_CPU 16000000UL
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 FLASH //__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)
uint8_t scr[4] = {DIG5,DIG2,DIG3,DIG4};
uint8_t scr_y[4];
static uint8_t com;
const FLASH seg_pin_t *p;
ISR(TIMER0_COMP_vect){
p = commons+com;
OCR0 = scr_y[com];
if(COM_CAT)
*p->port |= p->or;
else
*p->port &= p->and;
}
ISR(TIMER0_OVF_vect)
{
p = commons+com;
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;
}
void TimerInit(void)
{
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 250,000 kHz
// Mode: Fast PWM top=0xFF
// OC0 output: Disconnected
// Timer Period: 1,024 ms
TCCR0=(1<<WGM00) | (0<<COM01) | (0<<COM00) | (1<<WGM01) | (0<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (1<<OCIE0) | (1<<TOIE0);
}
int main(void){
DDRB = 255;
DDRC = 255;
DDRD = 0x7F;
PORTD = 0x80;
TimerInit();
sei();
scr_y[0]=250; // длительность свечения 1 разряда
scr_y[1]=100; // длительность свечения 2 разряда
scr_y[2]=50; // длительность свечения 3 разряда
scr_y[3]=25; // длительность свечения 0 разряда
while(1);
}-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Семисегментный LED-индикатор. Эффекты анимации
Косячок-с... Я ж недаром написал, из прерывания дёргаю пинами командами sbi cbi. Поясняю. В основном цикле модифицируем порт. Считали, в этот момент прерывание. И там тоже модификация порта. Мне продолжать?
- Serzh2000
- Опытный кот
- Сообщения: 867
- Зарегистрирован: Пт фев 27, 2015 12:00:53
- Откуда: Рязанская область
Re: Семисегментный LED-индикатор. Эффекты анимации
спасибо!
братцы, я на месяц с головой переваривать инфу

не знаю, пока у меня в голове все в кучу, надо подумать что да какИ там тоже модификация порта. Мне продолжать?
Re: Семисегментный LED-индикатор. Эффекты анимации
Да, продолжать.Demiurg писал(а):Мне продолжать?


