Ср авг 11, 2021 15:58:25
// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
switch (a) {
case 0:
Cathode_0_on ();
print (a1);
break;
case 1:
Cathode_1_on ();
print (a2);
break;
case 2:
Cathode_2_on ();
print (a3);
break;
case 3:
Cathode_3_on ();
print (a4);
break;
case 4:
Cathode_4_on ();
print (a5);
break;
case 5:
Cathode_5_on ();
print (a1);
break;
}
a++;
if (a == 6) {a = 0;}
}
// Timer2 output compare interrupt service routine
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{
all_off ();
off_segments ();
}
if (b < bright1) {зажигать} else {не зажигать}
Ср авг 11, 2021 16:56:02
Ср авг 11, 2021 17:03:12
uldemir писал(а):Если вы не можете запрячь под это дело DMA, то можете добавить просто прерывание по сравнению таймера и по прерыванию по переполнению показываете новую цифру, а по прерыванию сравнения - старую
Ср авг 11, 2021 17:15:32
А если использовать два канала сравнения? один для яркости, другой для эффекта? Или у AVR нет таймеров с несколькими каналами захвата/сравнения?*Trigger* писал(а):Такой вариант плохо совмещается с регулировкой яркости, к сожалению. Я по началу так и делал, а потом захотелось регулировать яркость, и пришлось от такого способа отказаться.
Ср авг 11, 2021 17:33:48
Ср авг 11, 2021 18:14:51
unsigned char digit1 [16] = {1, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
unsigned char t = 0;
// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
switch (a) {
case 0:
Cathode_0_on ();
print (digit [t]);
break;
case 1:
Cathode_1_on ();
print (a2);
break;
case 2:
Cathode_2_on ();
print (a3);
break;
case 3:
Cathode_3_on ();
print (a4);
break;
case 4:
Cathode_4_on ();
print (a5);
break;
case 5:
Cathode_5_on ();
print (a1);
break;
}
a++;
t++;
if (t > 15) t = 0;
if (a == 6) {a = 0;}
}
// Timer2 output compare interrupt service routine
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{
all_off ();
off_segments ();
}
Ср авг 11, 2021 18:38:30
uint8_t display_buffer_raw[DIGITS][BRIGHT_STEPS];
uint8_t digit_counter = 0;
uint8_t bright_step_counter = 0;
uint8_t digit_mask = (1 << 0);
void id1_output(uint8_t n){
if(n >= 10)
return;
n = id1_decode_table[n];
CLR_PORT(ID1_A);
CLR_PORT(ID1_B);
CLR_PORT(ID1_C);
CLR_PORT(ID1_D);
if(n & (1 << 0))
SET_PORT(ID1_A);
if(n & (1 << 1))
SET_PORT(ID1_B);
if(n & (1 << 2))
SET_PORT(ID1_C);
if(n & (1 << 3))
SET_PORT(ID1_D);
}
ISR(TIMER1_COMPA_vect){
uint8_t symbol;
if(bright_step_counter >= BRIGHT_STEPS)
return;
symbol = display_buffer_raw[digit_counter][bright_step_counter];
id1_output(symbol);
if(symbol < 10){
switch(digit_counter){
case 0:
SET_PORT(ANODE_0);
break;
case 1:
SET_PORT(ANODE_1);
break;
case 2:
SET_PORT(ANODE_2);
break;
case 3:
SET_PORT(ANODE_3);
break;
}
}
}
ISR(TIMER1_COMPB_vect){
if(++bright_step_counter == BRIGHT_STEPS_WITH_SAFE_PAUSE){
bright_step_counter = 0;
digit_mask <<= 1;
if(++digit_counter == DIGITS){
digit_counter = 0;
digit_mask = (1 << 0);
}
}
CLR_PORT(ANODE_0);
CLR_PORT(ANODE_1);
CLR_PORT(ANODE_2);
CLR_PORT(ANODE_3);
}
soft_timer_t display_change_effect_timer; //структура "программного таймера", который позволяет отсчитывать заданные интервалы времени
uint8_t display_buffer[DIGITS]; //новые (текущие) состояния разрядов
uint8_t display_buffer_old[DIGITS]; //старые состояния разрядов
//функция вызывается в основном цикле
void display_routine(void){
uint8_t i, j;
uint16_t step_duration;
uint8_t steps;
if(display_state.change_effect == NO_EFFECT ||
display_state.change_effect_step == 0){
for(i = 0; i < DIGITS; i++)
for(j = 0; j < BRIGHT_STEPS; j++){
display_buffer_raw[i][j] = display_buffer[i];
}
}
else{
switch(display_state.change_effect){
case SOFT_CHANGE: //обычная плавная смена (одновременное погасание и зажигание)
for(i = 0; i < DIGITS; i++)
for(j = 0; j < BRIGHT_STEPS; j++)
if(j < display_state.change_effect_step ||
!(display_state.change_effect_flags & (1 << i))){
display_buffer_raw[i][j] = display_buffer[i];
}
else{
display_buffer_raw[i][j] = display_buffer_old[i];
}
steps = SOFT_CHANGE_STEPS;
step_duration = SOFT_CHANGE_STEP_DURATION;
break;
case SEMI_SOFT_CHANGE: //плавное погасание, резкое зажигание
for(i = 0; i < DIGITS; i++)
for(j = 0; j < BRIGHT_STEPS; j++)
if(display_state.change_effect_flags & (1 << i)){
if(j < display_state.change_effect_step){
display_buffer_raw[i][j] = ' ';
}
else{
display_buffer_raw[i][j] = display_buffer_old[i];
}
}
else{
display_buffer_raw[i][j] = display_buffer[i];
}
steps = SEMI_SOFT_CHANGE_STEPS;
step_duration = SOFT_CHANGE_STEP_DURATION;
break;
case SOFT_OFF_ON_CHANGE: //плавное погасание, плавное зажигание
for(i = 0; i < DIGITS; i++)
for(j = 0; j < BRIGHT_STEPS; j++)
if(display_state.change_effect_flags & (1 << i)){
if(j >= display_state.change_effect_step){
display_buffer_raw[i][j] = display_buffer_old[i];
}
else if(j + SOFT_OFF_ON_CHANGE_STEPS - BRIGHT_STEPS + 1 < display_state.change_effect_step){
display_buffer_raw[i][j] = display_buffer[i];
}
else{
display_buffer_raw[i][j] = ' ';
}
}
else{
display_buffer_raw[i][j] = display_buffer[i];
}
steps = SOFT_OFF_ON_CHANGE_STEPS;
step_duration = SOFT_OFF_ON_CHANGE_STEP_DURATION;
break;
case ROTATE_CHANGE: //смена с прокруткой, без каких-либо плавностей
for(i = 0; i < DIGITS; i++)
for(j = 0; j < BRIGHT_STEPS; j++)
if(display_state.change_effect_flags & (1 << i)){
display_buffer_raw[i][j] = (display_buffer_old[i] + display_state.change_effect_step) % 10;
}
else{
display_buffer_raw[i][j] = display_buffer[i];
}
steps = ROTATE_CHANGE_STEPS;
step_duration = ROTATE_CHANGE_STEP_DURATION;
break;
default:
break;
}
//по истечении интервала времени - следующий шаг смены цифр
if(soft_timer_finished(&display_change_effect_timer)){
if(++display_state.change_effect_step == steps + 1){
display_state.change_effect_step = 0;
for(i = 0; i < DIGITS; i++)
display_buffer_old[i] = display_buffer[i];
display_state.change_effect_flags = 0;
}
else{
soft_timer_start(&display_change_effect_timer, step_duration); //перезапуск программного таймера
}
}
}
}
Ср авг 11, 2021 18:52:39
// Прерывание таймера 1 по совпадению, с чем? Он 16 битный... Можно ли использовать как у меня, таймер 2 по совпадению и гасить по переполнению?
ISR(TIMER1_COMPA_vect){
uint8_t symbol;
if(bright_step_counter >= BRIGHT_STEPS) // число градаций яркости? Если пробежали весь массив, то уходим из прерывания, почему так? Что будет если не уйти?
return;
symbol = display_buffer_raw[digit_counter][bright_step_counter]; // выбираем цифру из массива массивов цифр, так? Получается двумерный массив, в строках идут цифры, 16 значений, которые пишем в лампу?
id1_output(symbol); // цифру в порт, так?
if(symbol < 10){ // Если цифра от 0 до 10, то зажечь порт, если нет, не зажигать порт, верно?
switch(digit_counter){
case 0:
SET_PORT(ANODE_0);
break;
case 1:
SET_PORT(ANODE_1);
break;
case 2:
SET_PORT(ANODE_2);
break;
case 3:
SET_PORT(ANODE_3);
break;
}
}
}
// Совпадение таймера со вторым значением?
ISR(TIMER1_COMPB_vect){
// зачем это? Не пойму что делает этот кусочек,
if(++bright_step_counter == BRIGHT_STEPS_WITH_SAFE_PAUSE){
bright_step_counter = 0;
digit_mask <<= 1;
if(++digit_counter == DIGITS){
digit_counter = 0;
digit_mask = (1 << 0);
}
}
// гасим все цифры? Но почему 4, в часах 4 лампы?
CLR_PORT(ANODE_0);
CLR_PORT(ANODE_1);
CLR_PORT(ANODE_2);
CLR_PORT(ANODE_3);
}
Ср авг 11, 2021 19:10:40
if(bright_step_counter >= BRIGHT_STEPS)
return;
if(++bright_step_counter == BRIGHT_STEPS_WITH_SAFE_PAUSE){
bright_step_counter = 0;
digit_mask <<= 1;
if(++digit_counter == DIGITS){
digit_counter = 0;
digit_mask = (1 << 0);
}
}
Ср авг 11, 2021 19:23:41
#include <mega8.h>
#include <delay.h>
#include <show_num.h>
unsigned char a = 0;
unsigned char digits [6][16] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
};
// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
switch (a) {
case 0: print (digits [0][t]);
PORTC.4 = 0;
break;
case 1: print (digits [1][t]);
PORTC.3 = 0;
break;
case 2: print (digits [2][t]);
PORTC.0 = 0;
break;
case 3: print (digits [3][t]);
PORTC.1 = 0;
break;
case 4: print (digits [4][t]);
PORTC.2 = 0;
break;
case 5: print (digits [5][t]);
PORTD.3 = 0;
break;
}
a++;
t++;
if (t > 5) t = 0;
if (a == 6) {a = 0;}
}
// Timer2 output compare interrupt service routine
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{
off_setki ();
off_segments ();
}
void main(void)
{
DDRB=0b11111111;
PORTB=0x00;
DDRC=0b11011111;
PORTC=0x00;
DDRD=0b11111011;
PORTD=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: Fast PWM top=0xFF
// OC2 output: Disconnected
// Timer Period: 0,256 ms
ASSR=0<<AS2;
TCCR2=(1<<PWM2) | (0<<COM21) | (0<<COM20) | (1<<CTC2) | (0<<CS22) | (1<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(1<<OCIE2) | (1<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<TOIE0);
#asm ("sei");
OCR2 = 250;
while (1) {
}
}
Ср авг 11, 2021 19:30:21
t++;
if (t > 15){
t = 0;
a++;
if (a == 6)
a = 0;
}
Ср авг 11, 2021 19:43:17
Ср авг 11, 2021 19:48:12
Ср авг 11, 2021 19:52:12
Пн авг 23, 2021 21:29:53
volatile uint8_t Digit[4]={0,0,0,0};//текущие отображаемые цифры
volatile uint8_t NewDigit[4]={0,0,0,0};//новые отображаемые цифры
volatile uint8_t ChangeDigitCounter[4]={0,0,0,0};//счётчик перехода от старых к новым цифрам
//----------
//обработчик вектора прерывания таймера T0 (8-ми разрядный таймер) по переполнению
//----------
ISR(TIMER0_OVF_vect)
{
//выполняем плавное зажигание/погасание цифр с импользованием BAM (binary amplitude modulation)
static uint8_t weight=0;//вес разряда
uint8_t mask=0;
mask=(1<<weight);
TCNT0=0xff-mask;
weight++;
if (weight==5) weight=0;
uint8_t digit[4]={Digit[0],Digit[1],Digit[2],Digit[3]};
static bool new_digit[4]={false,false,false,false};
for(uint8_t n=0;n<4;n++)
{
if (ChangeDigitCounter[n]==0) Digit[n]=NewDigit[n];//цифра сменилась
if (ChangeDigitCounter[n]&mask) new_digit[n]=false;
else new_digit[n]=true;
if (new_digit[n]==true) digit[n]=NewDigit[n];
}
OUTPUT_OutputDigit(digit);
}
//----------
//обработчик вектора прерывания таймера T2 (8-ми разрядный таймер) по переполнению
//----------
ISR(TIMER2_OVF_vect)
{
//таймер вызывается 122.0703125 раза в секунду
TCNT2=0;
KEYBOARD_Scan();
SENSOR_DecrementEnabledDataCounter();
static uint8_t tick=0;
tick++;
if (tick==122)//прошла секунда (примерно)
{
if (CathodeCleaningCounter>0) CathodeCleaningCounter--;
tick=0;
}
if ((tick&0x01)!=0) return;
for(uint8_t n=0;n<4;n++)
{
if (ChangeDigitCounter[n]>0) ChangeDigitCounter[n]--;
}
}
for(uint8_t n=0;n<4;n++)
{
if (NewDigit[n]!=set_digit[n]) ChangeDigitCounter[n]=0x1f;
NewDigit[n]=set_digit[n];
}
Ср авг 25, 2021 07:52:28
Пн авг 30, 2021 07:13:15
Пн авг 30, 2021 09:26:54
da-nie писал(а):ISR(TIMER0_OVF_vect)
{
//выполняем плавное зажигание/погасание цифр с импользованием BAM (binary amplitude modulation)
static uint8_t weight=0;//вес разряда
uint8_t mask=0;
mask=(1<<weight);
TCNT0=0xff-mask;
weight++;
if (weight==5) weight=0;
uint8_t digit[4]={Digit[0],Digit[1],Digit[2],Digit[3]};
static bool new_digit[4]={false,false,false,false};
for(uint8_t n=0;n<4;n++)
{
if (ChangeDigitCounter[n]==0) Digit[n]=NewDigit[n];//цифра сменилась
if (ChangeDigitCounter[n]&mask) new_digit[n]=false;
else new_digit[n]=true;
if (new_digit[n]==true) digit[n]=NewDigit[n];
}
OUTPUT_OutputDigit(digit);
}
ISR(TIMER0_OVF_vect) {
//выполняем плавное зажигание/погасание цифр с импользованием BAM (binary amplitude modulation
static uint8_t mask = 1;
TCNT0 = 0xff - mask;
mask <<= 1;
if (mask == (1 << 5)) mask = 1;
uint8_t digind[4];
for (uint8_t n = 0; n < 4; n++) {
if (ChangeDigitCounter[n] == 0) Digit[n] = NewDigit[n]; //цифра сменилась
digind[n] = (ChangeDigitCounter[n] & mask) ? Digit[n] : NewDigit[n];
}
OUTPUT_OutputDigit(digind);
}
Пн авг 30, 2021 09:54:28