|
динамическая индикация, вывод децимиальной точки |
|
|
|
Jan 24 2011, 13:00
|
Участник

Группа: Участник
Сообщений: 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(); }; }
|
|
|
|
|
Jan 24 2011, 14:25
|
Участник

Группа: Участник
Сообщений: 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 //пустота }; пардон, неправильно понял про буфер.
|
|
|
|
|
Jan 24 2011, 14:30
|
Участник

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

|
читайте начало темы.
|
|
|
|
|
Jan 24 2011, 14:49
|
Участник

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

|
извиняюсь я не совсем понял как это воплотить в коде. можете привести пример?
|
|
|
|
|
Jan 24 2011, 15:03
|

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

|
Цитата(RicLab @ Jan 24 2011, 17:49)  извиняюсь я не совсем понял как это воплотить в коде. можете привести пример? старший бит в массиве digits - это точка? тогда простая операция Код char b; b = digits[x]; if (decimal_point) { b |= 0x80; }
|
|
|
|
|
Jan 24 2011, 15:16
|
Участник

Группа: Участник
Сообщений: 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-разряд }
|
|
|
|
|
Jan 24 2011, 15:40
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Jan 24 2011, 16:00
|
Участник

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

|
Спасибо за подсказку проверил работает. Код 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
|
|
|
|
|
Jan 25 2011, 03:33
|
Участник

Группа: Участник
Сообщений: 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 Гц, засветов нет.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|