реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> динамическая индикация, вывод децимиальной точки
RicLab
сообщение Jan 24 2011, 13:00
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901



Добрый день
Необходим совет.
на 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.gif
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Jan 24 2011, 13:28
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



В буфере индикации можно хранить не цифры а символы в 8-сегментном формате. Тогда простановка точки - простая операция очистки/установки бита сегмента H.
Go to the top of the page
 
+Quote Post
RicLab
сообщение Jan 24 2011, 14:25
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901



поясните?
в массиве они и так находяться в 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                    //пустота
};



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

Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 24 2011, 14:26
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(RicLab @ Jan 24 2011, 19:23) *
в массиве они и так находяться в 8 сегментном формате т.е.
У вас все символы в таблице без точки. Добавьте к этой таблице еще одну, где все символы с точкой.
Go to the top of the page
 
+Quote Post
RicLab
сообщение Jan 24 2011, 14:30
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901



читайте начало темы.
Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 24 2011, 14:40
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Я прочитал. С самого начала. Вам был дан совет оперировать не бинарным значением из таблицы, а кодом символа. При этом можно использовать управляющую последовательность для формирования буфера вывода. Когда код символа "точка" дает указание подменить следующий за ним символ на его бинарное значение, содержащее точку. Для этого либо нужна вторая таблица, которая содержит бинарные значения с точкой, либо отдельная операция, которая накладывает маску на бинарное значение, считанное из таблицы так, чтобы при выводе десятичная точка светилась.
Go to the top of the page
 
+Quote Post
RicLab
сообщение Jan 24 2011, 14:49
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901



извиняюсь я не совсем понял как это воплотить в коде.
можете привести пример?
Go to the top of the page
 
+Quote Post
toweroff
сообщение Jan 24 2011, 15:03
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(RicLab @ Jan 24 2011, 17:49) *
извиняюсь я не совсем понял как это воплотить в коде.
можете привести пример?

старший бит в массиве digits - это точка?
тогда простая операция
Код
char b;
b = digits[x];
if (decimal_point)
{
    b |= 0x80;
}

Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 24 2011, 15:09
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Нет времени и желания, чтобы кормить вас бесплатной "рыбой". Могу только объяснить, как сделать "удочку" самому.
В прерывании выводите в порт значения массива digit_out, без извлечения его из таблицы. Значениями, извлеченными из таблицы, этот массив заполняйте заранее. При заполнении используйте какой-либо признак "наличия точки" по которому на бинарное значение, извлеченное из таблицы, накладывайте маску для включения точки.
Go to the top of the page
 
+Quote Post
RicLab
сообщение Jan 24 2011, 15:16
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901



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

Код
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-разряд  
}

Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 24 2011, 15:40
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (RicLab @ Jan 24 2011, 17:16) *
т.е. например если нужно вывести второй разряд с точкой делаем так
Сделайте еще один шаг:

CODE
digit_out[0]=digits[indication%10];
indication=indication/10;               //Оставляем 3 разряда                        
digit_out[1]=digits[indication%10] | 0x80;
а из вывода чтение digits уберите.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
RicLab
сообщение Jan 24 2011, 16:00
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901



Спасибо за подсказку biggrin.gif
проверил работает.


Код
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 - Jan 24 2011, 16:01
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 24 2011, 20:07
Сообщение #13


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(RicLab @ Jan 24 2011, 19:00) *
но появилась слабая засветка соседних разрядов.

А что переключает разряды? На время выдачи след. символа обычно гасятся и аноды/катоды разрядов.
Go to the top of the page
 
+Quote Post
RicLab
сообщение Jan 25 2011, 03:33
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 24-11-08
Пользователь №: 41 901



с проблемой разобрался, причина в неправильной настройке таймера.
слишком высокая частота преключения разрядов, видимо транзисторы в цепи общих катодов не успевали до конца закрыться.
поменял частоту переключения.
Код
// 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.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 25 2011, 07:30
Сообщение #15


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (RicLab @ Jan 25 2011, 05:33) *
слишком высокая частота преключения разрядов, видимо транзисторы в цепи общих катодов не успевали до конца закрыться. поменял частоту переключения.
Одно из двух - либо вы нашли экстремально медленные транзисторы середины 50-х годов, либо вы их некорректно включили.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th June 2025 - 15:11
Рейтинг@Mail.ru


Страница сгенерированна за 0.01496 секунд с 7
ELECTRONIX ©2004-2016