Как отправить 40 бит на 7-ми сегментный индикатор

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
alexey6522
Встал на лапы
Сообщения: 149
Зарегистрирован: Чт июл 28, 2011 18:12:28

Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение alexey6522 »

Добрый вечер! Хочу отправить 40 бит с помощью алгоритма ниже

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

void export_data (long double data)
{
  unsigned char i; //переменная i
  for (i=0;i<40;i++) {
    if ((data&80000000)==0x00){
      PORTD&=~_BV(PD5); //Выставляем биты данных на PD5 (DATA канал)   
     }
    else {
     PORTD|=_BV(PD5);
     }
    PORTD|=_BV(PD6); //Импульс на SH_CP (запись)
    PORTD&=~_BV(PD6);
    data<<=1;
  }

   PORTD|=_BV(PD7); //Импульс на ST_CP (защелка - вывод на индикатор записанных данных)
    PORTD&=~_BV(PD7);
}
вызов функции export_data(0x065B4F666D);
на индикаторе должны получить число 54321
Вложения
7-х.JPG
схема
(100.13 КБ) 378 скачиваний
Реклама
Аватара пользователя
koyodza
Собутыльник Кота
Сообщения: 2623
Зарегистрирован: Вс июл 17, 2011 11:51:52
Контактная информация:

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение koyodza »

А вопрос в чём?
Реклама
alexey6522
Встал на лапы
Сообщения: 149
Зарегистрирован: Чт июл 28, 2011 18:12:28

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение alexey6522 »

это и был вопрос, функция не работает, выдает ошибку на строке
if ((data&80000000)==0x00){
alexey6522
Встал на лапы
Сообщения: 149
Зарегистрирован: Чт июл 28, 2011 18:12:28

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение alexey6522 »

alexey6522 писал(а):это и был вопрос, функция не работает, выдает ошибку на строке
if ((data&80000000)==0x00){
main.c:30: error: invalid operands to binary & (have 'long double' and 'long unsigned int')
Реклама
Эиком - электронные компоненты и радиодетали
alexey6522
Встал на лапы
Сообщения: 149
Зарегистрирован: Чт июл 28, 2011 18:12:28

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение alexey6522 »

В принципе разобрался использовал переменную unsigned long long
Реклама
Аватара пользователя
koyodza
Собутыльник Кота
Сообщения: 2623
Зарегистрирован: Вс июл 17, 2011 11:51:52
Контактная информация:

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение koyodza »

Без обид, но профессионалы используют в подобных случаях слово "говнокод".
Там ошибок куча. Не говоря уже о потенциально опасных местах.
Например, константа 0х80000000 это в лучшем случае long, установлен 31 бит. Вы же пытаетесь использовать её как маску к более длинным данным.
Ну с long double вроде уже сами разобрались?
Сравнение с нулём может дать неожиданный результат, поскольку разрядность данных большая. Лучше поменять местами установку и сброс битов, и делать проверку на неноль, т.е. if (x) вместо if (x == 0), или if (!x)
Для столь длинных данных лучше передавать не значение, а указатель на буфер.
В самой функции двигать каждый раз 64 бита (особенно если оно у Вас работает на 8-битнике, а похоже это как раз на AVR) тоже не очень хорошо, мягко говоря.
Кстати, подсказка: двигать иногда удобнее не данные, а маску.
В общем: учиться, учиться, учиться
Реклама
alexey6522
Встал на лапы
Сообщения: 149
Зарегистрирован: Чт июл 28, 2011 18:12:28

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение alexey6522 »

Спасибо koyodza, Вы гений!

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

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

// составляем из сегментов цифры
#define	N0	(0x3F)		//0
#define	N1	(0x06)		//1
#define	N2	(0x5B)		//2
#define	N3	(0x4F)		//3
#define	N4	(0x66)		//4
#define	N5	(0x6D)		//5
#define	N6	(0x7D)		//6
#define	N7	(0x07)		//7
#define	N8	(0x7F)	    //8
#define	N9	(0x6F)		//9

unsigned char indikator[10]={N0, N1, N2, N3, N4, N5, N6, N7, N8, N9};
unsigned char y=0; //переменная y  

void export_data (unsigned long long data)
{
  unsigned char i; //переменная i
  for (i=0;i<40;i++) {
    if (!(data&0x8000000000)){
      PORTD&=~_BV(PD5); //Выставляем биты данных на PD5 (DATA канал)   
     }
    else {
     PORTD|=_BV(PD5);
     }
    PORTD|=_BV(PD6); //Импульс на SH_CP (запись)
    PORTD&=~_BV(PD6);
    data<<=1;
  }

   PORTD|=_BV(PD7); //Импульс на ST_CP (защелка - вывод на индикатор записанных данных)
    PORTD&=~_BV(PD7);
}

int main(void)
{
  long int DS=0;   //переменная DS
  unsigned int i=0;    //переменная i
  PORTD=0x00; //Первоначально устанавливаем на всех выходах 0
  DDRD=0xff; //установить PD0-PD2 как выходы
  while (1)  //Бесконечный цикл
   {   
      export_data(0x065B4F666D);   //Отправляем данные на сдвиговый регистр
   }
}
Еще вопрос, который мне спать не дает, как мне добавить 0x06 к числу 0x065B4F666D это будет примерчик и ответ будет выводиться в десятичной форме на индикатор (54321+1 = 54322)
или еще лучше, покажите как сделать цикл и организовать счетчик от 0 до 99999, а потом обнулять
alexey6522
Встал на лапы
Сообщения: 149
Зарегистрирован: Чт июл 28, 2011 18:12:28

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение alexey6522 »

koyodza писал(а): Кстати, подсказка: двигать иногда удобнее не данные, а маску.
Объясните почему?
Аватара пользователя
koyodza
Собутыльник Кота
Сообщения: 2623
Зарегистрирован: Вс июл 17, 2011 11:51:52
Контактная информация:

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение koyodza »

alexey6522 писал(а):Спасибо koyodza, Вы гений!
Нет, я не гений. Просто это часть моей работы по покраске бобров http://eprst2000.livejournal.com/133119.html
alexey6522 писал(а):Еще вопрос, который мне спать не дает, как мне добавить 0x06 к числу 0x065B4F666D это будет примерчик и ответ будет выводиться в десятичной форме на индикатор (54321+1 = 54322)
или еще лучше, покажите как сделать цикл и организовать счетчик от 0 до 99999, а потом обнулять
Мне кажется, Вы в корне неверно подходите к решению задачи.
Я бы сделал примерно так:
1. отдельно существует счётчик нужной длины (для дианазона 0..99999 нужен long), с ним делаете, что Вам нужно. Допустим, инкрементируете.
2. Отдельно существует функция перевода двоичного числа в "массив образов".
3. Отдельно существует функция отображения, которая принимает указатель (на массив) и выводит на индикатор.
alexey6522 писал(а):
koyodza писал(а): Кстати, подсказка: двигать иногда удобнее не данные, а маску.
Объясните почему?
Не всегда, конечно же. Но иногда всё-таки удобнее.
Например, двигая маску, можно избавиться от счётчика цикла. Это хорошо работает, когда маска двигается вправо. При её обнулении цикл можно завершать. При сдвигах влево такая штука удобна при проходе до старшего бита.
Ещё не всегда удобно двигать данные, когда используется не локальная их копия, а оригинал по указателю. Это может применяться к данным большой разрядности.

Будут ещё вопросы - спрашивайте
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение urry »

а я как-то не улавливаю связь между числом 0x065B4F666D и 54321.
И в аск бред какой то , и не флоат и не хекс...
Аватара пользователя
koyodza
Собутыльник Кота
Сообщения: 2623
Зарегистрирован: Вс июл 17, 2011 11:51:52
Контактная информация:

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение koyodza »

urry писал(а):а я как-то не улавливаю связь между числом 0x065B4F666D и 54321.
И в аск бред какой то , и не флоат и не хекс...
Связь простая: это битовый образ. Каждый бит соответствует одному сегменту индикатора. Как раз 7 сегментов плюс точка, один байт на одно знакоместо.
Хотя точки у топикстартера кажется не подключены
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение urry »

а, что-то типа tic8148 ?
:) я тут вычисляю...
Аватара пользователя
koyodza
Собутыльник Кота
Сообщения: 2623
Зарегистрирован: Вс июл 17, 2011 11:51:52
Контактная информация:

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение koyodza »

urry писал(а):а, что-то типа tic8148 ?
:) я тут вычисляю...
Нет, в самом первом сообщении схема. Куча 595 сдвиговых регистров, прямо к ним индикаторы. Индикация статическая. Всё просто
alexey6522
Встал на лапы
Сообщения: 149
Зарегистрирован: Чт июл 28, 2011 18:12:28

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение alexey6522 »

koyodza Вы можете показать наглядно, не думаю что для вас составит большого труда написать 20 строк кода, понимаете в программировании МК я новичек и много еще не знаю.
Отдельный счетчик должен выглядеть таким образом?

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

unsigned long long toDigital(unsigned long int i)
{
     unsigned long long result=0;
     int r;
     
     for (r=0; r<5; r++)
     { 
	  result = (result>>8) | (indikator[(unsigned char)(i%10)]<<32); 
	  i/=10; 
	 }
     return result;
}
А вот и вызов

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

int main(void)
{
unsigned long int s=0;

  unsigned long long DS=0;   //переменная DS
  unsigned int i=0;    //переменная i
  PORTD=0x00; //Первоначально устанавливаем на всех выходах 0
  DDRD=0xff; //установить PD0-PD2 как выходы
  while (1)  //Бесконечный цикл
   {   
     export_data(toDigital(s++));   //Отправляем данные на сдвиговый регистр
     if (s>99999) s=0;
     _delay_ms(500); // Ждём полсекунды
   }
}
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение urry »

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

#define DIGIT 5
unsigned char cArr[DIGIT];
unsigned int step[DIGIT]={10000,1000,100,10,1};
#define   N0   (0x3F)      //0
#define   N1   (0x06)      //1
#define   N2   (0x5B)      //2
#define   N3   (0x4F)      //3
#define   N4   (0x66)      //4
#define   N5   (0x6D)      //5
#define   N6   (0x7D)      //6
#define   N7   (0x07)      //7
#define   N8   (0x7F)       //8
#define   N9   (0x6F)      //9

unsigned char indikator[10]={N0, N1, N2, N3, N4, N5, N6, N7, N8, N9};
void fnLongToStr(unsigned  long tmp)
{
unsigned char i,atemp;
unsigned long val,temp;
val=tmp;
for (i=0; i<DIGIT; i++)
{
   temp=(unsigned long)step[i];
   atemp=0;
   while(val >= temp)
     {
       atemp++;
       val-=temp;
     }
   cArr[i]=atemp;
 }
}
//------------------------------
void fnImageDigit(void)
{
unsigned	char i;
	for (i=0; i<DIGIT; i++)
		{
		cArr[i]=indikator[cArr[i]];
		}
}
//-----------------------------
void 	fnOutByte(unsigned char cByte)
{
unsigned char mask =0x80;
	do{
	if(mask & cByte)
	{
	PORTD|=_BV(PD5);
	}
	else
	{
	PORTD&=~_BV(PD5);
	}
    PORTD|=_BV(PD6); //Импульс на SH_CP (запись)
    PORTD&=~_BV(PD6);
	mask>>=1;
}while(mask);
}
//-----------------------------
void fnShowDigit(unsigned  long tmp)
{
	unsigned	char i;
	fnLongToStr(tmp);
	fnImageDigit();
	for (i=0; i<DIGIT; i++)
	{
	fnOutByte(cArr[i]);
	}
}
//-----------------------------
Это не единственный способ, можно через форматирование по sprintf
Да, код не проверялся.
alexey6522
Встал на лапы
Сообщения: 149
Зарегистрирован: Чт июл 28, 2011 18:12:28

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение alexey6522 »

urry Ты решил мою задачу, спасибо, код конечно получился мудреный, но работает. Было бы замечательно если бы ты объяснил какая функция и что она делает, по подробнее.
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение urry »

fnLongToStr(unsigned long tmp)
раскладывает число tmp в массив 5 байтов, т.е если в лонг 0х00000010
то в массиве 0,0,0,1,6
fnImageDigit(void)
перекидывает реальные значения этого массива в их образы
после нее в массиве будет
0x3F 0x3F 0x3F 0x06 0x7D
fnOutByte(unsigned char cByte)
вывод байта на регистр
fnShowDigit(unsigned long tmp)
выводит tmp на регистры
alexey6522
Встал на лапы
Сообщения: 149
Зарегистрирован: Чт июл 28, 2011 18:12:28

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение alexey6522 »

Я вот думаю над размером hex файла, он у меня получился 1,43 кб, это нормально для такой простой операции? :shock:
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение urry »

я не кашпировский - листинг сквозь монитор не вижу.
Посмотрите, что выдает компилятор и что кушает больше всего .
alexey6522
Встал на лапы
Сообщения: 149
Зарегистрирован: Чт июл 28, 2011 18:12:28

Re: Как отправить 40 бит на 7-ми сегментный индикатор

Сообщение alexey6522 »

Вот полный код программы

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

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

/*		 -A-
		F	B
		 -G-
		E	C
		 -D-	
*/
#define DIGIT 5
unsigned char cArr[DIGIT];
unsigned int step[DIGIT]={10000,1000,100,10,1};
#define   N0   (0x3F)      //0
#define   N1   (0x06)      //1
#define   N2   (0x5B)      //2
#define   N3   (0x4F)      //3
#define   N4   (0x66)      //4
#define   N5   (0x6D)      //5
#define   N6   (0x7D)      //6
#define   N7   (0x07)      //7
#define   N8   (0x7F)      //8
#define   N9   (0x6F)      //9

unsigned char indikator[10]={N0, N1, N2, N3, N4, N5, N6, N7, N8, N9};

void fnLongToStr(unsigned long tmp)
{
unsigned char i,atemp;
unsigned long val,temp;
val=tmp;
for (i=0; i<DIGIT; i++)
{
   temp=(unsigned long)step[i];
   atemp=0;
   while(val >= temp)
     {
       atemp++;
       val-=temp;
     }
   cArr[i]=atemp;
}
}
//------------------------------
void fnImageDigit(void)
{
unsigned   char i;
   for (i=0; i<DIGIT; i++)
      {
      cArr[i]=indikator[cArr[i]];
      }
}
//-----------------------------
void fnOutByte(unsigned char cByte)
{
unsigned char mask =0x80;
   do{
   if(mask & cByte)
   {
   PORTD|=_BV(PD5);
   }
   else
   {
   PORTD&=~_BV(PD5);
   }
    PORTD|=_BV(PD6); //Импульс на SH_CP (запись)
    PORTD&=~_BV(PD6);
   mask>>=1;
}while(mask);
}
//-----------------------------

void fnShowDigit(unsigned long tmp)
{
   unsigned char i;
   fnLongToStr(tmp);
   fnImageDigit();
   for (i=0; i<DIGIT; i++)
   {
   fnOutByte(cArr[i]);
   }
}
//-----------------------------

int main(void)
{
  unsigned long int s=0;
  PORTD=0x00; //Первоначально устанавливаем на всех выходах 0
  DDRD=0xff; //установить PD0-PD2 как выходы
  while (1)  //Бесконечный цикл
   {   
   fnShowDigit(s++);
   PORTD|=_BV(PD7); //Импульс на ST_CP (защелка - вывод на индикатор записанных данных)
   PORTD&=~_BV(PD7);
   if (s>99999) 
     s=0;
   _delay_ms(1500);  //пауза 300 мс
 }
 }
размер файла hex = 1,43кб
а вот при компиляции
> "make.exe" all

-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Size before:
AVR Memory Usage
----------------
Device: atmega8

Program: 492 bytes (6.0% Full)
(.text + .data + .bootloader)

Data: 25 bytes (2.4% Full)
(.data + .bss + .noinit)




Compiling: main.c
avr-gcc -c -mmcu=atmega8 -I. -gdwarf-2 -DF_CPU=1000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst -std=gnu99 -MD -MP -MF .dep/main.o.d main.c -o main.o

Linking: main.elf
avr-gcc -mmcu=atmega8 -I. -gdwarf-2 -DF_CPU=1000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o -std=gnu99 -MD -MP -MF .dep/main.elf.d main.o --output main.elf -Wl,-Map=main.map,--cref -lm

Creating load file for Flash: main.hex
avr-objcopy -O ihex -R .eeprom main.elf main.hex

Creating load file for EEPROM: main.eep
avr-objcopy -j .eeprom --set-section-flags .eeprom=alloc,load \
--change-section-lma .eeprom=0 -O ihex main.elf main.eep
avr-objcopy: --change-section-lma .eeprom=0x00000000 never used

Creating Extended Listing: main.lss
avr-objdump -h -S main.elf > main.lss

Creating Symbol Table: main.sym
avr-nm -n main.elf > main.sym

Size after:
AVR Memory Usage
----------------
Device: atmega8

Program: 514 bytes (6.3% Full)
(.text + .data + .bootloader)

Data: 25 bytes (2.4% Full)
(.data + .bss + .noinit)



-------- end --------


> Process Exit Code: 0
> Time Taken: 00:00
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»