Перейти к содержанию
    

динамическая индикация

Добрый день

Необходим совет.

на 4-х разрядный 7-сегментый индикатор выводиться произвольное число 0-9999, необходимо во втором разряде включать децимиальную точку т.е. 0,0-999,9.

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

 

код для CVAVR

Chip type           : ATtiny2313
Clock frequency     : 8,000000 MHz
Memory model        : Tiny
External SRAM size  : 0
Data Stack size     : 32
*****************************************************/

#include <tiny2313.h>
#include <delay.h>

#define digit1 PORTD.5 // разряд 4
#define digit2 PORTD.4 // разряд 3
#define digit3 PORTD.1 // разряд 2
#define digit4 PORTD.0 // разряд 1 

flash char digits []= {       //создаём массив с цифрами
0x3F,                   //0
0x06,                   //1
0x5B,                   //2
0x4F,                   //3
0x66,                   //4
0x6D,                   //5
0x7D,                   //6
0x07,                   //7
0x7F,                   //8
0x6F,                   //9
0x40,                   //знак минуса
0x00                    //пустота
};                 
char digit_out[4], cur_dig;  //переменные для работы с LED

unsigned int indication;    //переменная для хранения чисел 
unsigned int x;
void recoding(void) {       //функция для перекодировки из hex в dec 
if (indication<10000)       //начинаем преобразование если число < 1000 так как 4-х разрядный LED
{        
digit_out[0]=indication%10;     //Делим на 10, остаток записываем в масив 1-разряд     
indication=indication/10;               //Оставляем 3 разряда                        
digit_out[1]=(indication%10);   //Делим на 10, остаток записываем в масив 2-разряд    
indication=(indication/10);                //Оставляем 2 разряда                     
digit_out[2]=indication%10;     //Делим на 10, остаток записываем в масив 3-разряд 
indication=(indication/10);                //Оставляем 1 разряда                     
digit_out[3]=indication%10;     //Делим на 10, остаток записываем в масив 4-разряд  
}                                           
}                                          

//таймер 0
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTB=0x00;       //чтобы предотвратить эффект “тени” на соседних индикаторах
switch (cur_dig){
case 0:{digit1=0; digit2=0; digit3=0; digit4=1; break;};  //подаём питание на разряд 1, гасим остальные разряды
case 1:{digit4=0; digit2=0; digit1=0; digit3=1; break;};  //подаём питание на разряд 2, ггасим остальные разряды
case 2:{digit3=0; digit1=0; digit4=0; digit2=1; break;};  //подаём питание на разряд 3, гасим остальные разряды
case 3:{digit2=0; digit3=0; digit4=0; digit1=1; break;};  //подаём питание на разряд 3, гасим остальные разряды
}
PORTB=digits[digit_out[cur_dig]];    //выводим с каждым срабатыванием таймера число с массива в порт В, но не для всех разрядов сразу

cur_dig++;                                           //с каждым срабатыванием таймера, увеличиваем переменную cur_dig на 1
if(cur_dig==4) cur_dig=0;                  //если cur_dig = 4 обнуляем  

}
void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port A initialization
// Func2=In Func1=In Func0=In 
// State2=T State1=T State0=T 
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTB=0x00;
DDRB=0xFF;

// Port D initialization
// Func6=In Func5=Out Func4=Out Func3=In Func2=In Func1=Out Func0=Out 
// State6=T State5=0 State4=0 State3=P State2=P State1=0 State0=0 
PORTD=0x0C;
DDRD=0x33;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x01;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=0x00;
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x02;

// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;

// Global enable interrupts
#asm("sei")
while (1)
      { 
      x++;
      delay_ms(100);
      if(x>9999) x=0;
      indication=x;
      recoding();
      };
}

:laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В буфере индикации можно хранить не цифры а символы в 8-сегментном формате. Тогда простановка точки - простая операция очистки/установки бита сегмента H.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

поясните?

в массиве они и так находяться в 8 сегментном формате т.е.

 

flash char digits []= {       //создаём массив с цифрами
0x3F,                   //0      0b00111111
0x06,                   //1      0b00000110
0x5B,                   //2      0b01011011
0x4F,                   //3      0b01001111
0x66,                   //4      0b01100110
0x6D,                   //5      0b01101101
0x7D,                   //6      0b01111101
0x07,                   //7      0b00000111
0x7F,                   //8      0b01111111
0x6F,                   //9      0b01101111
0x40,                   //знак минуса
0x00                    //пустота
};

 

 

пардон, неправильно понял про буфер.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в массиве они и так находяться в 8 сегментном формате т.е.
У вас все символы в таблице без точки. Добавьте к этой таблице еще одну, где все символы с точкой.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я прочитал. С самого начала. Вам был дан совет оперировать не бинарным значением из таблицы, а кодом символа. При этом можно использовать управляющую последовательность для формирования буфера вывода. Когда код символа "точка" дает указание подменить следующий за ним символ на его бинарное значение, содержащее точку. Для этого либо нужна вторая таблица, которая содержит бинарные значения с точкой, либо отдельная операция, которая накладывает маску на бинарное значение, считанное из таблицы так, чтобы при выводе десятичная точка светилась.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

извиняюсь я не совсем понял как это воплотить в коде.

можете привести пример?

старший бит в массиве digits - это точка?

тогда простая операция

char b;
b = digits[x];
if (decimal_point)
{
    b |= 0x80;
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет времени и желания, чтобы кормить вас бесплатной "рыбой". Могу только объяснить, как сделать "удочку" самому.

В прерывании выводите в порт значения массива digit_out, без извлечения его из таблицы. Значениями, извлеченными из таблицы, этот массив заполняйте заранее. При заполнении используйте какой-либо признак "наличия точки" по которому на бинарное значение, извлеченное из таблицы, накладывайте маску для включения точки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

т.е. например если нужно вывести второй разряд с точкой делаем так

 

if (indication<10000)       //начинаем преобразование если число < 1000 так как 4-х разрядный LED
{        
digit_out[0]=indication%10;     //Делим на 10, остаток записываем в масив 1-разряд     
indication=indication/10;               //Оставляем 3 разряда                        
digit_out[1]=((indication%10)|= 0x80);  //Делим на 10, остаток записываем в масив 2-разряд    
indication=(indication/10);                //Оставляем 2 разряда                     
digit_out[2]=indication%10;     //Делим на 10, остаток записываем в масив 3-разряд 
indication=(indication/10);                //Оставляем 1 разряда                     
digit_out[3]=indication%10;     //Делим на 10, остаток записываем в масив 4-разряд  
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

т.е. например если нужно вывести второй разряд с точкой делаем так
Сделайте еще один шаг:

 

digit_out[0]=digits[indication%10];
indication=indication/10;               //Оставляем 3 разряда                        
digit_out[1]=digits[indication%10] | 0x80;

а из вывода чтение digits уберите.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за подсказку :biggrin:

проверил работает.

 

 

void recoding(void) {       //функция для перекодировки из hex в dec 
if (indication<10000)       //начинаем преобразование если число < 1000 так как 4-х разрядный LED
{        
digit_out[0]=digits[indication%10];     //Делим на 10, остаток извлекаем из таблицы записываем в 1-разряд     
indication=indication/10;               //Оставляем 3 разряда                        
digit_out[1]=digits[indication%10]| 0x80;  //Делим на 10, остаток извлекаем из таблицы накладываем маску записываем в 1-разряд 
indication=(indication/10);                //Оставляем 2 разряда                     
digit_out[2]=digits[indication%10];     //Делим на 10, остаток извлекаем из таблицы записываем в 3-разряд
indication=(indication/10);                //Оставляем 1 разряда                     
digit_out[3]=digits[indication%10];     //Делим на 10, остаток извлекаем из таблицы записываем в 4-разряд
}                                           
}                                          

//таймер 0
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTB=0x00;       //чтобы предотвратить эффект “тени” на соседних индикаторах
switch (cur_dig){
case 0:{digit1=0; digit2=0; digit3=0; digit4=1; break;};  //подаём питание на разряд 1, гасим разряд 3
case 1:{digit4=0; digit2=0; digit1=0; digit3=1; break;};  //подаём питание на разряд 2, гасим разряд 1
case 2:{digit3=0; digit1=0; digit4=0; digit2=1; break;};  //подаём питание на разряд 3, гасим разряд 2  
case 3:{digit2=0; digit3=0; digit4=0; digit1=1; break;};  //подаём питание на разряд 3, гасим разряд 2      
}

PORTB=digit_out[cur_dig];    //выводим с каждым срабатыванием таймера число с массива в порт В, но не для всех разрядов сразу

cur_dig++;                                           //с каждым срабатыванием таймера, увеличиваем переменную cur_dig на 1
if(cur_dig==4) cur_dig=0;                  //если cur_dig = 4 обнуляем  

}

 

но появилась слабая засветка соседних разрядов.

Изменено пользователем RicLab

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

но появилась слабая засветка соседних разрядов.

А что переключает разряды? На время выдачи след. символа обычно гасятся и аноды/катоды разрядов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

с проблемой разобрался, причина в неправильной настройке таймера.

слишком высокая частота преключения разрядов, видимо транзисторы в цепи общих катодов не успевали до конца закрыться.

поменял частоту переключения.

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x03;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

частота моргания каждого разряда получилась примерно 123 Гц, засветов нет. :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

слишком высокая частота преключения разрядов, видимо транзисторы в цепи общих катодов не успевали до конца закрыться. поменял частоту переключения.
Одно из двух - либо вы нашли экстремально медленные транзисторы середины 50-х годов, либо вы их некорректно включили.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...