Вывод чисел

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Аватара пользователя
virus33
Нашел транзистор. Понюхал.
Сообщения: 175
Зарегистрирован: Пт июн 29, 2012 23:48:11

Вывод чисел

Сообщение virus33 »

Мы принимаем по uart некоторое число, которое считается по какой то формуле и его необходимо вывести на семисегментный индикатор.
Чтобы не заморачиваться с примером допустим будем снимать значения с ацп и выводить их(типовый вольтметр), суть остается та же.
Верхний предел 5в, в таком случае на 1 преобразование приходится 0,0048в. Пускай мы получили после преобразования 512, что есть 512*0,0048 = 2,46в(нас это устраивает).
Вот это число и нужно вывести на три разряда последовательно.
Взял немного готового кода:

Код: Выделить всё

void delay(unsigned int p)
{
	unsigned int i;
	for(i=0;i<p;i++){asm("NOP");}
}

void seg7(unsigned char c, unsigned char s)
{
unsigned char t=0;
switch(c%10)        //  выбор сегментов (катодов)
{
//                      gcPdeafb
case 0 : {t=0b11000000;} break;
case 1 : {t=0b11111001;} break;
case 2 : {t=0b10100100;} break;
case 3 : {t=0b10110000;} break;
case 4 : {t=0b10011001;} break;
case 5 : {t=0b10010010;} break;
case 6 : {t=0b10000010;} break;
case 7 : {t=0b11111000;} break;
case 8 : {t=0b10000000;} break;
case 9 : {t=0b10010000;} break;
}
RB1 = 0;
RB2 = 0;
RB3 = 0;
switch(s)       //  выбор анода
{
case 1 :{ RB1 = 1;}break;
case 2 :{ RB2 = 1;}break;
case 3 :{ RB3 = 1;}break;
}
PORTD = t;
if(c>9){
PORTD=t&0b01111111;
}
}

void main (void)
{
	int i,v;
	unsigned int M,D;	// множитель и детитель
	init();
	vn=0;
	M=10;	// множитель
	D=20;	// детитель
	while(1)
	{
//		GODONE=1;		//	Устанавливаем бит GO для того что бы сделать опрос АЦП
//		while(GODONE){}
//		v=ADRESL;		//	читаем младший байт с АЦП
//		i=ADRESH;		//	читаем старший байт с АЦП (а именно 2 байта с него)
//		i=i*256;
//		v=v+i;			//	складываем младщий и старший байт с АЦП
//		v=v*M;
//		v=(int)v/D;
//		v=(int)v%1000;
		v = 2.46*100;
		v1=v/100;
		v=v%100;
		v2=v/10;
		v3=v%10;
		delay(10000);
	}
}
То что под таймером(переключаем сегменты):

Код: Выделить всё

void interrupt pwm_int(void)	// общая процедура прерывания
{
	if(T0IF) 	//	при переполнение TMR1
	{
		vn++;
		switch(vn)
		{
			case 1:seg7(v1,1);break;		//сегмент 1
			case 2:seg7(v2,2);break;		//сегмент 2
			case 3:{seg7(v3,3);vn=0;}break;	//сегмент 3
		}
		TMR0=100;
		T0IF=0; 	//	сбрасываем флаг
	}
}
Преобразование АЦП заккоментил(ибо пока не нужно).
После него идут следующие строки:

Код: Выделить всё

		v = 2.46*100;
		v1=v/100;
		v=v%100;
		v2=v/10;
		v3=v%10;
		delay(10000);
Где запись v = 2.46*100; - те самые 2.46 которые необходимо вывести. Функция seg7 мне понятна, только для "почти" корректного вывода дробного числа пришлось его домножить на 100. Последующие записи мне непонятны вообще. Если кто может - растолкуйте. И еще. В функции seg7 есть запись

Код: Выделить всё

if(c>9){
PORTD=t&0b01111111;
}
которая должна выводить точку, только у меня почему то ничего не выводится. Из комментария автора
Спойлер
Точка у символа загорается, если с больше 9, значение на индикатор выводиться всё равно будет, т.е. будет выводиться только младший разряд, остальное всё отбрасываться (например: 19, 39 = 9. ).
Взято отсюда http://alex-exe.ru/radio/microcontrolle ... ndication/
Ну и результат работы соответственно:
Изображение

Помогите пожалуйста до конца разобраться с семисегментной индикацией. Заранее спасибо.
Реклама
Аватара пользователя
rxstart1
Вымогатель припоя
Сообщения: 508
Зарегистрирован: Пт фев 22, 2013 18:00:43
Откуда: Беларусь, г. Гомель

Re: Вывод чисел

Сообщение rxstart1 »

Мне думается Ваша проблема в том, что Вы пытаетесь вывести точку как отдельный символ, попробуйте просто изменить 1 бит сегмента PORTA|=(1<<7) в данном примере изменится только один 7 байт порта А. А маской можно только проверить биты, это не совсем С++))
Реклама
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Вывод чисел

Сообщение pyzhman »

Десятичной точки нет. Пичалька.
Docendo discimus
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Re: Вывод чисел

Сообщение Mishany »

точку выводить отдельным свободным портом, либо зажечь в постоянке,
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
rxstart1
Вымогатель припоя
Сообщения: 508
Зарегистрирован: Пт фев 22, 2013 18:00:43
Откуда: Беларусь, г. Гомель

Re: Вывод чисел

Сообщение rxstart1 »

В Вашем случае лучше подать +3В на сегмент с точкой, либо при выводе в динамической индикации, указывать точку как отдельный сегмент, с соостветствующей задержкой в нужное Вам знакоместо.
Реклама
Аватара пользователя
virus33
Нашел транзистор. Понюхал.
Сообщения: 175
Зарегистрирован: Пт июн 29, 2012 23:48:11

Re: Вывод чисел

Сообщение virus33 »

А как вот, допустим, можно разбить число на сегменты другим способом, нежели указанным в примере?
Реклама
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Вывод чисел

Сообщение pyzhman »

А как еще по-другому можно? Только выделяя разряды. А разряды выделяются делением.
Docendo discimus
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Вывод чисел

Сообщение COKPOWEHEU »

Во извращение - выполнять преобразование числа в строку при каждом вызове прерывания и выставление точек хоть перед каждым символом. На самом деле все делается гораздо проще

Код: Выделить всё

unsigned char digit[3]; //отдельные разряды для вывода
//значения, соответствующие отдельным символам
const unsigned char digit_table[10]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001,0b10010010,0b10000010,0b11111000,0b10000000,0b10010000};
//прерывание для индикации
ISR(TIMER0_OVF){
 static unsigned char count=0; //номер разряда для индикации
 PORTB |= (0b00000111); //из кода я не понял на каких выводах висят общие провода. Пусть будут на PB0-PB2. Чтобы не мерцало - отключаем все
 PORTD=digit[count]; //выводим интересующий символ
 count++; //немного черной магии - увеличение count здесь приносит меньше всего сложностей
 switch(count){ //включаем интересующее знакоместо
  1: PORTB &=~(1<<0); break; //0-е (это потому что после увеличения count'а)
  2: PORTB &=~(1<<1); break; //1-е
  default: PORTB &=~(1<<2); count=0; //любое другое (по идее, не больше 2-го
 }
}
//вывод числа на индикатор. 3 разрядов идеально хватит для байта. val - само значение, dot - положение десятичной точки (если не влезает в индикаторы - игнорируется)
void outchar(unsigned char val,unsigned char dot){
 digit[2] = digit_table[val%10]; val/=10; //младший разряд. Сразу переводим из численного представления в символьное
 digit[1] = digit_table[val%10]; val/=10; //средний
 digit[0] = digit_table[val]; //старший. Поскольку val передан по значению, его можно менять без последствий
 if(dot<3) digit[dot]&=~(1<<7); //за точку отвечает 7-й бит, его и устанавливаем в нужное значение.
}
Писал по опыту работы с AVR, но платформо-зависимого тут немного - описание прерывания да названия портов.
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Вывод чисел

Сообщение YS »

Код: Выделить всё

const unsigned char digit_table[10]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001,0b10010010,0b10000010,0b11111000,0b10000000,0b10010000};
Здесь лучше добавить PROGMEM (для AVR-GCC). Без этого компилятор запулит эту таблицу в RAM. Слово const от этого не спасает. :idea:
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Вывод чисел

Сообщение COKPOWEHEU »

Вообще, да, лучше запихныть массив в ПЗУ, но десяток байтов и в оперативке не слишком помешают. К тому же конструкции
void interrupt pwm_int(void) // общая процедура прерывания
if(T0IF)
RB1 = 0;
заставляют сомневаться, не похоже на AVR, в как в других системах идет запись в ПЗУ я не знаю.
Ответить

Вернуться в «Разные вопросы по МК»