Семисегментный LED-индикатор. Эффекты анимации
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Нет. Это я когда то баловался с эффектами. BAM.
- Реклама
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Мой вариант эффектов. . Эффекты конструировал с помощью программы LEDx8. Архив с проектом прикрепил. МК ATMEGA8535. Частота кварца 16 МГц. Таблица с эффектами в файле proc_device.c. Обработчик индикатров в файле seven_segm_led_ind.c
[uquote="BlackKilkennyCat",url="/forum/viewtopic.php?p=3882839#p3882839"]Просто у всех разные среды и мк, да и ещё и разные стили.[/uquote]
Вот по этому-то и не получается толком покурить.
Ещё и столько понавыкладывали. ) Нельзя на каком-то варианте чуть по-подробнее?
Вот по этому-то и не получается толком покурить.
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
В этой теме вам и словами раскидали и примеров накидали, хоть анусом жуй. Абсолютно без разницы на каком языке вы пишете, каким стилем. Любой проект начинается с ТЗ, с постановки задачи. Берете бумажку и начинаете. Сверху вниз. От устройства к функционалу. И когда вы на бумаге будете видеть хотя бы размытые очертания того, что вы хотите, только тогда у вас дело сдвинется.
В моих примерах сделано на таблицах. Кадры, которые по таймеру выплевываются в буфер дисплея. Оттуда также по таймеру выводится на индикаторы. Структура таблицы временные параметры и что выводим в текущем кадре.
Алгоритмы, бумага и карандаш вам в помощь.
Лично я уже давно во многих случаях даже и этим не пользуюсь. Всё в уме проворачиваю.
В моих примерах сделано на таблицах. Кадры, которые по таймеру выплевываются в буфер дисплея. Оттуда также по таймеру выводится на индикаторы. Структура таблицы временные параметры и что выводим в текущем кадре.
Алгоритмы, бумага и карандаш вам в помощь.
Лично я уже давно во многих случаях даже и этим не пользуюсь. Всё в уме проворачиваю.
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);
}
}
}
- Реклама
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Меньше прерываниями увлекаться. Это уже программный шим. А значит, убрать все долгие обработчик прерываний и переползать в основной цикл. Либо переходить на статический режим и сдвиговые регистры. Тут анализировать нужно, как оптимальнее. Перед коммутацией индикаторов приготовить данные, значения шима. А когда коммутация, вывести.
Вот общую яркость забацал. а по разрядам чет не соображу.
#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 КБ) 160 скачиваний
давным давно предлагал такой способ: http://arv.radioliga.com/content/view/101/49/Serzh2000 писал(а):чтоб например каждый разряд (буква) светилась своей яркостью
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
индивидуальная яркость делается легко:
в прерывании по переполнению:
{обновляем сегменты из массива буфера экрана;
включаем требуемый общий электрод разряда
заносим в регистр сравнения параметр яркости из массива яркостей;
сдвигаем счётчик отображаемого разряда;}
в прерывании по совпадению:
{забираем данные с приэкранной клавиатуры; (если она есть)
отключаем все общие разрядные электроды;}
в прерывании по переполнению:
{обновляем сегменты из массива буфера экрана;
включаем требуемый общий электрод разряда
заносим в регистр сравнения параметр яркости из массива яркостей;
сдвигаем счётчик отображаемого разряда;}
в прерывании по совпадению:
{забираем данные с приэкранной клавиатуры; (если она есть)
отключаем все общие разрядные электроды;}
Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Да, пожалуйста:
описание сегментов (от 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; //выключаем все разряды (среди них окажется и включенный)
}Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Купи, скачай книги по МК 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 раза.
У меня была прожка на ассемблере - 4 позиционник с раздельной регулировкой яркости на каждой позиции.
Или с применением регистр-расширителей - 4 строки у каждой из которых своя яркость.
База - Т1 со всеми добавками. Правда в проекте схемки нету...
А уж формирование эффектов и самих данных - это задачка дополнительная и не зависимая от обработчика вывода на дисплей.

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

Итогом имеем как бы два независимо идущих процесса - собственно регенерация индикатора и программа пользователя.
Минус - потеря одного таймера и высшего приоритета в прерываниях.
Как то на "чистом СИ" должно выглядеть - то уж не мне судить.
В адуринке тандем внешнего прерывания и tone для "псевдопараллельного процесса" можно использовать (это ежли только средства "референса", не забираясь "в глубины" делать).
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Выше подправил свое сообщение.
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
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);
}- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Косячок-с... Я ж недаром написал, из прерывания дёргаю пинами командами sbi cbi. Поясняю. В основном цикле модифицируем порт. Считали, в этот момент прерывание. И там тоже модификация порта. Мне продолжать?
спасибо!
братцы, я на месяц с головой переваривать инфу

не знаю, пока у меня в голове все в кучу, надо подумать что да какИ там тоже модификация порта. Мне продолжать?
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54


