Форум РадиоКот https://radiokot.ru/forum/ |
|
Динамическая индикация на 74HC595 https://radiokot.ru/forum/viewtopic.php?f=57&t=149947 |
Страница 1 из 2 |
Автор: | 7seg [ Ср ноя 15, 2017 03:52:41 ] |
Заголовок сообщения: | Динамическая индикация на 74HC595 |
Запускаю симуляцию в протеусе динамическая индикация отображается "кракозябрами"(раньше дин.индикация всегда отображалась в протеусе корректно). Вот и закралась мысль ко мне может я чего то не знаю ?( Может кто подсказать где кроется ошибка? Схема: Спойлер![]() Фулл код СпойлерКод: #define F_CPU 8000000UL #include <util/delay.h> #include <avr/interrupt.h> #include <avr/io.h> #include <avr/pgmspace.h> #include <avr/eeprom.h> volatile uint8_t TEST=10; #define SPI_PORT PORTB #define SPI_DDR DDRB #define SPI_MISO PB4 #define SPI_MOSI PB3 #define SPI_SCK PB5 #define SPI_SS PB2 //настройка параметров работы функций #define BTN_LOCK_TIME 50 /*время обработки дребезга в милисекундах (10-100)*/ #define BTN_LONG_TIME 2000 /*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/ //настройки портов /*порт чтения кнопок*/ #define BTN_PORT PORTC #define BTN_DDR DDRC #define BTN_PIN PINC /*пины чтения кнопок*/ #define BTN_LINE_UP (1<<0) #define BTN_LINE_DN (1<<1) #define BTN_LINE_POWER (1<<2) #define BTN_LINE_SW (1<<3) //глобальные переменные volatile uint8_t BtnFlags; //байт флагов нажатия кнопки #define BTN_SHRT_UP (1<<0) /*бит короткого нажатия кнопки up*/ #define BTN_SHRT_DN (1<<1) /*бит короткого нажатия кнопки dn*/ #define BTN_SHRT_POWER (1<<2) /*бит короткого нажатия кнопки POWER */ #define BTN_SHRT_SW (1<<3) /*бит короткого нажатия кнопки SW*/ #define BTN_LONG_UP (1<<4) /*бит длинного нажатия кнопки up*/ #define BTN_LONG_DN (1<<5) /*бит длинного нажатия кнопки dn*/ #define BTN_LONG_SW (1<<6) /*бит короткого нажатия кнопки SW*/ //Функция настройки библиотеки работы с кнопками void BtnInit (void) { BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER|BTN_LINE_SW);//на ввод BTN_PORT |= (BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER|BTN_LINE_SW);//подтяжка вкл } //---------- //Функция чтения данных о нажатии кнопок char BtnGet (void) { cli(); char temp = BtnFlags; BtnFlags = 0; sei(); return temp; } //---------- //короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags //длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags void BtnExe (void) { static unsigned char BtnLockBit; //защелка (защита от дребезга) static unsigned char BtnLockCoun; //счетчик защелки (защита от дребезга) static unsigned char BtnLongCoun; //счетчик длинного нажатия static unsigned char BtnLastState; //последнее состояние кнопок перед отпусканием char mask = 0; if (! (BTN_PIN & BTN_LINE_UP)) mask = BTN_SHRT_UP; if (! (BTN_PIN & BTN_LINE_DN)) mask = BTN_SHRT_DN; if (! (BTN_PIN & BTN_LINE_POWER)) mask = BTN_SHRT_POWER; if (! (BTN_PIN & BTN_LINE_SW)) mask = BTN_SHRT_SW; if (mask){ //опрос состояния кнопки if (BtnLockCoun < (BTN_LOCK_TIME/10)){ //клавиша нажата BtnLockCoun++; return; //защелка еще не дощитала - возврат } BtnLastState = mask; BtnLockBit =1; //нажатие зафиксировано if (BtnLongCoun >= (BTN_LONG_TIME/10)) return; //возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше if (++BtnLongCoun >= (BTN_LONG_TIME/10)) BtnFlags |= (BtnLastState<<4); //счетчик досчитал до максимума - устанавливаем биты длинного нажатия } else{ //клавиша отжата if (BtnLockCoun){ BtnLockCoun --; return; //защелка еще не обнулилась - возврат } if (! BtnLockBit) //СТАТИЧЕСКИЙ ВОЗВРАТ return; BtnLockBit =0; //отжатие зафиксировано if (BtnLongCoun < (BTN_LONG_TIME/10)) BtnFlags |= BtnLastState; //установка бита короткого нажатия BtnLongCoun = 0; //сброс счетчика длительности нажатия } } /******************************************************************************************************/ struct UnionBits { unsigned DO0: 1; unsigned DO1: 1; unsigned DO2: 1; unsigned DO3: 1; unsigned DO4: 1; unsigned DO5: 1; unsigned DO6: 1; unsigned DO7: 1; }; union Byte { uint8_t ByteRegister; struct UnionBits Register; }; union Byte OneOUT; union Byte TwoOUT; union Byte ThreeOUT; union Byte FourOUT; union Byte FifthOUT; union Byte SixOUT; union Byte SevenOUT; union Byte EightOUT; union Byte OneIN; union Byte TwoIN; union Byte ThreeIN; union Byte FourIN; union Byte FifthIN; union Byte SixIN; union Byte SevenIN; union Byte EightIN; #define AMOUNT_TIMERS 5 //Количество используемых таймеров typedef struct { uint8_t FlagTimersON; //Флаг работы таймера uint8_t FlagTimersOFF; volatile uint32_t TimeCountingON; //Переменная фиксирующая время старта volatile uint32_t TimeCountingOFF; }TimerStruct; typedef struct { TimerStruct Channel[AMOUNT_TIMERS]; volatile uint32_t MS; volatile uint32_t TimeCurrent; //Текущие время }SoftTimers; SoftTimers TIMER; /*Функция инициализации таймеров (установка всех значений в 0 )*/ void InitTimers() { TIMER.TimeCurrent=0; TIMER.MS=0; for(uint8_t i=0;i<AMOUNT_TIMERS;i++) { TIMER.Channel[i].FlagTimersON=0; TIMER.Channel[i].FlagTimersOFF=0; TIMER.Channel[i].TimeCountingON=0; } } //Функция включения сегментов + кодировка. #define SEG_PORT EightOUT.ByteRegister #define SEGA 0 #define SEGB 1 #define SEGC 2 #define SEGD 3 #define SEGE 4 #define SEGF 5 #define SEGG 6 #define SEGH 7 #define ANOD1 SevenOUT.Register.DO5 #define ANOD2 SevenOUT.Register.DO6 #define ANOD3 SevenOUT.Register.DO7 static void segchar (unsigned char seg) { switch (seg) { case 0: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG)|(1<<SEGH);break; case 1: SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break; case 2: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 3: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 4: SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 5: SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 6: SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 7: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break; case 8: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 9: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 99: //OFF Все сегменты SEG_PORT=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break; } } volatile uint8_t data1=0; volatile uint8_t data2=0; volatile uint8_t AnodCount=0; void WriteSegNumber(uint8_t Seg3,uint8_t NeberChar) { data1=NeberChar%10; data2=NeberChar/10; AnodCount++; switch (AnodCount) { case 1: segchar(data1); ANOD2=1; ANOD3=1; ANOD1=0;break; case 2: segchar(data2); ANOD1=1; ANOD3=1; ANOD2=0;break; case 3: segchar(Seg3); ANOD1=1; ANOD2=1; ANOD3=0; AnodCount = 0;break; } } #define MAX_UINT32 4294967295UL ISR (TIMER0_OVF_vect) { TCNT0=125; //значение для T0_0VF переполнения 1 раз в MS TIMER.MS++; //Подсчет MS if (TIMER.MS == MAX_UINT32) { TIMER.MS=0; } BtnExe(); } /*Функция вернет TRUE через время TimeVar,Иначе возвращает CurrentFlag */ uint8_t OnAfterTimeMS(uint32_t TimeVar,uint8_t Number,uint8_t CurrentFlag) { cli(); uint8_t OutFlag=CurrentFlag; //Переменная отвечает за RETURN f(). TIMER.TimeCurrent=TIMER.MS; //Присваиваем текущие значение МС //Условия для захвата времени вызова функции, и установки флага работы if (TIMER.Channel[Number].FlagTimersON==0) { TIMER.Channel[Number].TimeCountingON=TIMER.MS; TIMER.Channel[Number].FlagTimersON=1; } volatile uint32_t TimerToStart = TIMER.TimeCurrent-TIMER.Channel[Number].TimeCountingON; //Если (время до старта == TimeVar) и (условия по переполнению MAX_UINT32 выполняеться), //то OutFlag=1 и обнуляем Флаг работы if ((TimerToStart >= TimeVar)&&((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)>TimeVar)) { OutFlag=1; TIMER.Channel[Number].FlagTimersON=0; TIMER.Channel[Number].TimeCountingON=0; TimerToStart=0; } else { OutFlag=CurrentFlag; //Если MAX_UINT32 переполниться быстрей чем досчитает TimeVar то обнулим таймер if (((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)<TimeVar)) { TIMER.MS=0; TIMER.Channel[Number].TimeCountingON=0; } } sei(); return OutFlag; } uint8_t OFFAfterTimeMS(uint32_t TimeVar,uint8_t Number,uint8_t CurrentFlag) { cli(); uint8_t OutFlag=CurrentFlag; //Переменная отвечает за RETURN f(). TIMER.TimeCurrent=TIMER.MS; //Присваиваем текущие значение МС //Условия для захвата времени вызова функции и установки флага работы if (TIMER.Channel[Number].FlagTimersOFF==0) { TIMER.Channel[Number].TimeCountingOFF=TIMER.MS; TIMER.Channel[Number].FlagTimersOFF=1; } volatile uint32_t TimerToSTOP = TIMER.TimeCurrent-TIMER.Channel[Number].TimeCountingOFF; //Если (время до старта == TimeVar) и (условия по переполнению MAX_UINT32 выполняеться), //то OutFlag=0 и обнуляем Флаг работы if ((TimerToSTOP >= TimeVar)&&((MAX_UINT32-TIMER.Channel[Number].TimeCountingOFF)>TimeVar)) { OutFlag=0; TIMER.Channel[Number].FlagTimersOFF=0; TIMER.Channel[Number].TimeCountingOFF=0; TimerToSTOP=0; } else { OutFlag=CurrentFlag; //Если MAX_UINT32 переполниться быстрей чем досчитает TimeVar то обнулим таймер if (((MAX_UINT32-TIMER.Channel[Number].TimeCountingOFF)<TimeVar)) { TIMER.MS=0; TIMER.Channel[Number].TimeCountingOFF=0; } } sei(); return OutFlag; } void StartInitIO() { OneOUT.ByteRegister=0x00; TwoOUT.ByteRegister=0x00; ThreeOUT.ByteRegister=0x00; FourOUT.ByteRegister=0x00; FifthOUT.ByteRegister=0x00; SixOUT.ByteRegister=0x00; SevenOUT.ByteRegister=0x00; EightOUT.ByteRegister=0x00; OneIN.ByteRegister=0x00; TwoIN.ByteRegister=0x00; ThreeIN.ByteRegister=0x00; FourIN.ByteRegister=0x00; FifthIN.ByteRegister=0x00; SixIN.ByteRegister=0x00; SevenIN.ByteRegister=0x00; EightIN.ByteRegister=0x00; } /*инициализация SPI модуля в режиме master*/ void SPI_Init(void) { /*настройка портов ввода-вывода все выводы, кроме MISO выходы*/ SPI_DDR |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO); SPI_PORT |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO); SPCR = (1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(0<<SPR1)|(0<<SPR0); SPSR = (0<<SPI2X); } uint8_t SPI_UpdataByte(uint8_t data) { uint8_t report; SPDR = data; while(!(SPSR & (1<<SPIF))); report = SPDR; return report; } void SpiOutRegister() { SPI_PORT &= ~(1<<SPI_SS); OneIN.ByteRegister=SPI_UpdataByte(EightOUT.ByteRegister); TwoIN.ByteRegister=SPI_UpdataByte(SevenOUT.ByteRegister); ThreeIN.ByteRegister=SPI_UpdataByte(SixOUT.ByteRegister); FourIN.ByteRegister=SPI_UpdataByte(FifthOUT.ByteRegister); FifthIN.ByteRegister=SPI_UpdataByte(FourOUT.ByteRegister); SixIN.ByteRegister=SPI_UpdataByte(ThreeOUT.ByteRegister); SevenIN.ByteRegister=SPI_UpdataByte(TwoOUT.ByteRegister); EightIN.ByteRegister=SPI_UpdataByte(OneOUT.ByteRegister); SPI_PORT |= (1<<SPI_SS); } void TransmitStatusGerkonToLed() { OneOUT.ByteRegister=FourIN.ByteRegister; TwoOUT.ByteRegister=FifthIN.ByteRegister; ThreeOUT.ByteRegister=SixIN.ByteRegister; FourOUT.ByteRegister=SevenIN.ByteRegister; } void TransmitStatusTumblerSwToLed() { FifthOUT.ByteRegister=OneIN.ByteRegister; SixOUT.ByteRegister=TwoIN.ByteRegister; SevenOUT.Register.DO0=ThreeIN.Register.DO0; SevenOUT.Register.DO1=ThreeIN.Register.DO1; SevenOUT.Register.DO2=ThreeIN.Register.DO2; SevenOUT.Register.DO3=ThreeIN.Register.DO3; SevenOUT.Register.DO4=ThreeIN.Register.DO4; } volatile uint8_t flagBtnLnUp=0; void BtnUpdate(void) { char BtnMask = BtnGet (); if (BtnMask == BTN_SHRT_POWER) { } if ((BtnMask == BTN_SHRT_SW)) { } //одиночное нажатие + if (BtnMask == BTN_SHRT_UP) { TEST++; } //одиночное нажатие - if ((BtnMask == BTN_SHRT_DN)) { TEST--; } //Удержание + if ((BtnMask == BTN_LONG_UP)) { flagBtnLnUp=1; } //Удержание - if ((BtnMask == BTN_LONG_DN)) { TEST--; } } void Algoritm() { } void DebugAlgoritm() { TransmitStatusTumblerSwToLed(); TransmitStatusGerkonToLed(); } uint8_t Step=0; int main(void) { SPI_Init(); StartInitIO(); InitTimers(); BtnInit(); DDRD=0xFF; ANOD1=1;ANOD2=1;ANOD3=1;segchar(99);//Офф 7сег индикация. TCCR0=(1<<CS01)|(1<<CS00); //Настраиваем пред делитель 64 TIMSK=(1<<TOIE0); // Запускаем таймер TCNT0=131; sei(); while(1) { Step++; switch (Step) { case 1: SpiOutRegister();break; case 2: WriteSegNumber(3,21);break; case 3: DebugAlgoritm();break; case 4: BtnUpdate(); Step=0;break; } } return 0; } Код Функции динамической индикации: Код: //Функция включения сегментов + кодировка.
#define SEG_PORT EightOUT.ByteRegister #define SEGA 0 #define SEGB 1 #define SEGC 2 #define SEGD 3 #define SEGE 4 #define SEGF 5 #define SEGG 6 #define SEGH 7 #define ANOD1 SevenOUT.Register.DO5 #define ANOD2 SevenOUT.Register.DO6 #define ANOD3 SevenOUT.Register.DO7 static void segchar (unsigned char seg) { switch (seg) { case 0: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG)|(1<<SEGH);break; case 1: SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break; case 2: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 3: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 4: SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 5: SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 6: SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 7: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break; case 8: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 9: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 99: //OFF Все сегменты SEG_PORT=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break; } } volatile uint8_t data1=0; volatile uint8_t data2=0; volatile uint8_t AnodCount=0; void WriteSegNumber(uint8_t Seg3,uint8_t NeberChar) { data1=NeberChar%10; data2=NeberChar/10; AnodCount++; switch (AnodCount) { case 1: segchar(data1); ANOD2=1; ANOD3=1; ANOD1=0;break; case 2: segchar(data2); ANOD1=1; ANOD3=1; ANOD2=0;break; case 3: segchar(Seg3); ANOD1=1; ANOD2=1; ANOD3=0; AnodCount = 0;break; } } |
Автор: | Dimon456 [ Ср ноя 15, 2017 07:22:10 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
У вас Код: SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break; К примеру SEGG- это 1(первый) бит, а в схеме R8ANOD G подключен на 6 бит ---- это правильно? |
Автор: | 7seg [ Ср ноя 15, 2017 07:48:35 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
Это пологаю что это правильно т.к SEGG находиться в структуре :: EightOUT.ByteRegister Код: struct UnionBits { unsigned DO0: 1; unsigned DO1: 1; unsigned DO2: 1; unsigned DO3: 1; unsigned DO4: 1; unsigned DO5: 1; unsigned DO6: 1; unsigned DO7: 1; }; union Byte { uint8_t ByteRegister; struct UnionBits Register; }; union Byte EightOUT; и при передачи (1<<SEGG), т.е мы установим 1 в EightOUT.Register.DO6 , а это битовое поле как раз и отвечает за Q6 в регистре "R8ANOD". Добавлено after 6 minutes 34 seconds: Такая если конечно можно выразиться "инверсия" происходит из-за SPI и принципа работы сдвиговых регистров. Код: uint8_t SPI_UpdataByte(uint8_t data)
{ uint8_t report; SPDR = data; while(!(SPSR & (1<<SPIF))); report = SPDR; return report; } void SpiOutRegister() { SPI_PORT &= ~(1<<SPI_SS); OneIN.ByteRegister=SPI_UpdataByte(EightOUT.ByteRegister); TwoIN.ByteRegister=SPI_UpdataByte(SevenOUT.ByteRegister); ThreeIN.ByteRegister=SPI_UpdataByte(SixOUT.ByteRegister); FourIN.ByteRegister=SPI_UpdataByte(FifthOUT.ByteRegister); FifthIN.ByteRegister=SPI_UpdataByte(FourOUT.ByteRegister); SixIN.ByteRegister=SPI_UpdataByte(ThreeOUT.ByteRegister); SevenIN.ByteRegister=SPI_UpdataByte(TwoOUT.ByteRegister); EightIN.ByteRegister=SPI_UpdataByte(OneOUT.ByteRegister); SPI_PORT |= (1<<SPI_SS); } |
Автор: | Dimon456 [ Ср ноя 15, 2017 15:57:52 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
Все таки я ее заставил работать, видос |
Автор: | 7seg [ Чт ноя 16, 2017 04:24:36 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
Dimon456, Поздравляю ) а исходником не поделитесь ?) Добавлено after 35 minutes 34 seconds: Видос как она ̶Р̶а̶б̶о̶т̶а̶е̶т̶ не работает у меня ( |
Автор: | Dimon456 [ Чт ноя 16, 2017 15:55:13 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
Исходник я не менял, он ваш полностью и всецело. Это Протеус косячит, в реальном железе будет работать. У китайцев же эти модули работают Спойлер![]() |
Автор: | 7seg [ Пт ноя 17, 2017 02:46:43 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
я тогда предполагаю что это настройки пртеуса. System->Set display options и System->Animation Options. |
Автор: | Dimon456 [ Пт ноя 17, 2017 08:58:49 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
Я же написал, странно, ну да ладно. Нет, неверно, но если ваш компутер переваривает 100 кадр/сек, можете поставить. Я туда не лазил. Просто отсоедините вывод OE микрух R3R и R8ANOD от общей схемы, что бы они в воздухе оказались, соедините их между собой, подсоедините это соединение OE через инвертор к точке соединения выводов ST_CP микрух R3R и R8ANOD. Если не понятно вот схема Спойлер![]() Это только для вашего кода, вы неверно формируете импульс ST_CP для 74HC595, хотя этот импульс может быть верен для 74HC165 (не разбирался с ней, не знаю). Это только для протеуса. Инвертор формирует правильный импульс для вывода OE. Не зацикливайтесь на этом. Спойлер![]() |
Автор: | Starichok51 [ Вс ноя 19, 2017 13:42:04 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
7seg писал(а): #define SEG_PORT EightOUT.ByteRegister все это до фига избыточно (как и многое другое в полном коде).#define SEGA 0 #define SEGB 1 #define SEGC 2 #define SEGD 3 #define SEGE 4 #define SEGF 5 #define SEGG 6 #define SEGH 7 #define ANOD1 SevenOUT.Register.DO5 #define ANOD2 SevenOUT.Register.DO6 #define ANOD3 SevenOUT.Register.DO7 static void segchar (unsigned char seg) { switch (seg) { case 0: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG)|(1<<SEGH);break; case 1: SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break; case 2: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 3: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 4: SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 5: SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 6: SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 7: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break; case 8: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 9: SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break; case 99: //OFF Все сегменты SEG_PORT=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break; } } достаточно определить байты цифр - по одному байту для каждой цифры. вот, как это сделано у меня: ; 0 - горит, 1 - потушен ; сегменты: D.CGAFBE .equ _0 = 0b01010000 .equ _1 = 0b11011101 .equ _2 = 0b01100100 .equ _3 = 0b01000101 .equ _4 = 0b11001001 .equ _5 = 0b01000011 .equ _6 = 0b01000010 .equ _7 = 0b11010101 .equ _8 = 0b01000000 .equ _9 = 0b01000001 .equ _x = 0b11111111 ; пустое место, пробел .equ _m = 0b11101111 ; минус там также определены дополнительные символы, которые нужно выводить. (сегменты в байтах идут не по порядку, а так, как было удобно разводить на плате). далее все просто: соответственно цифре ее код (байт) отправляем прямо в порт. либо другой нужный символ. и не нужны твои огромные навороты с объявлениями большой кучи констант и созданием комбинаций из этих констант... |
Автор: | Demiurg [ Вс ноя 19, 2017 18:24:58 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
Писанины много, это так. Но тут полностью работает пословица: долго запрягаем, зато быстро едем. Последующие проекты собираются гораздо быстрее. Тебе остается переопределить пины и все. Немного посложнее с микросхемами ввода-вывода. Но все равно, при шаблоне проект гораздо быстрее собрать, чем с нуля все писать. Динамическая индикация. Расширение ввода-вывода. 74HC595. Период вывода 1 мс. Функция работает в основном цикле. Ну про свой подход в программировании я неоднократно писал. "seven_segm_led_ind.h" СпойлерКод: //================== #ifndef SEVEN_SEGM_LED_IND_H #define SEVEN_SEGM_LED_IND_H #include "seven_segm_led_ind.h" //================== //================== #include "main_def_func.h" //================== //================== //#define __COMMON_METHOD_ONE__ #define __COMMON_METHOD_ZERO__ //#define __SEGMENT_METHOD_ONE__ #define __SEGMENT_METHOD_ZERO__ //================== //================== #define IND_1 b00000010 // 1<<1 #define IND_2 b00000100 // 1<<2 #define IND_3 b00001000 // 1<<3 #define IND_4 b00000001 // 1<<0 #ifdef __COMMON_METHOD_ONE__ #define IND_1_MASK IND_1 #define IND_2_MASK IND_2 #define IND_3_MASK IND_3 #define IND_4_MASK IND_4 #endif #ifdef __COMMON_METHOD_ZERO__ #define IND_1_MASK (0xFF ^ (IND_1)) #define IND_2_MASK (0xFF ^ (IND_2)) #define IND_3_MASK (0xFF ^ (IND_3)) #define IND_4_MASK (0xFF ^ (IND_4)) #endif //---------- #define SEG_A b00000010 // 1<<1 #define SEG_B b00001000 // 1<<3 // A #define SEG_C b10000000 // 1<<7 // F B #define SEG_D b00100000 // 1<<5 // G #define SEG_E b00010000 // 1<<4 // E C #define SEG_F b00000100 // 1<<2 // D H #define SEG_G b00000001 // 1<<0 #define SEG_H b01000000 // 1<<6 //---------- typedef struct tab_char_7_segm_cod_t { u08 Char; u08 seven_segm_cod; } tab_char_7_segm_cod_t; extern struct tab_char_7_segm_cod_t __flash tab_char_7_segm_cod []; //================== //================== #define MAX_LED_INDS 4 //================== //================== extern u08 dsp_buf []; void clr_dsp_buf (void); //================== //================== typedef struct index_inds { u08 i; u08 ind; } index_inds; //================== //================== u08 recod_char_7_segm_cod (u08 data); void set_proc_7_segm_ind_on (void); void set_proc_7_segm_ind_off (void); void proc_7_segm_ind (void); //================== //================== #endif //================== "seven_segm_led_ind.с" СпойлерКод: //================== #include "seven_segm_led_ind.h" //================== //================== struct index_inds __flash tab_index_inds [] = { {1, IND_2_MASK}, {2, IND_3_MASK}, {3, IND_4_MASK}, {0, IND_1_MASK}, }; struct tab_char_7_segm_cod_t __flash tab_char_7_segm_cod [] = { #ifdef __SEGMENT_METHOD_ONE__ {'0', (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F)}, // 0 {'1', (SEG_B | SEG_C)}, // 1 {'2', (SEG_A | SEG_B | SEG_D | SEG_E | SEG_G)}, // 2 {'3', (SEG_A | SEG_B | SEG_C | SEG_D | SEG_G)}, // 3 {'4', (SEG_B | SEG_C | SEG_F | SEG_G)}, // 4 {'5', (SEG_A | SEG_C | SEG_D | SEG_F | SEG_G)}, // 5 {'6', (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)}, // 6 {'7', (SEG_A | SEG_B | SEG_C)}, // 7 {'8', (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)}, // 8 {'9', (SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G)}, // 9 {'A', (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G)}, // 10 {'B', (SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)}, // 11 {'C', (SEG_A | SEG_D | SEG_E | SEG_F)}, // 12 {'D', (SEG_B | SEG_C | SEG_D | SEG_E | SEG_G)}, // 13 {'E', (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G)}, // 14 {'F', (SEG_A | SEG_E | SEG_F | SEG_G)}, // 15 {'G', (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F)}, // 16 {'H', (SEG_B | SEG_C | SEG_E | SEG_F | SEG_G)}, // 17 {'L', (SEG_D | SEG_E | SEG_F)}, // 18 {'N', (SEG_C | SEG_E | SEG_G)}, // 19 {'O', (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F)}, // 20 {'P', (SEG_A | SEG_B | SEG_E | SEG_F | SEG_G)}, // 21 {'П', (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F)}, // 22 {'-', (SEG_G)}, // 23 {' ', 0xFF}, // 24 #endif #ifdef __SEGMENT_METHOD_ZERO__ {'0', (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F))}, // 0 {'1', (0xFF ^ (SEG_B | SEG_C))}, // 1 {'2', (0xFF ^ (SEG_A | SEG_B | SEG_D | SEG_E | SEG_G))}, // 2 {'3', (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_D | SEG_G))}, // 3 {'4', (0xFF ^ (SEG_B | SEG_C | SEG_F | SEG_G))}, // 4 {'5', (0xFF ^ (SEG_A | SEG_C | SEG_D | SEG_F | SEG_G))}, // 5 {'6', (0xFF ^ (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G))}, // 6 {'7', (0xFF ^ (SEG_A | SEG_B | SEG_C))}, // 7 {'8', (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G))}, // 8 {'9', (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G))}, // 9 {'A', (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G))}, // 10 {'B', (0xFF ^ (SEG_C | SEG_D | SEG_E | SEG_F | SEG_G))}, // 11 {'C', (0xFF ^ (SEG_A | SEG_D | SEG_E | SEG_F))}, // 12 {'D', (0xFF ^ (SEG_B | SEG_C | SEG_D | SEG_E | SEG_G))}, // 13 {'E', (0xFF ^ (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G))}, // 14 {'F', (0xFF ^ (SEG_A | SEG_E | SEG_F | SEG_G))}, // 15 {'G', (0xFF ^ (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F))}, // 16 {'H', (0xFF ^ (SEG_B | SEG_C | SEG_E | SEG_F | SEG_G))}, // 17 {'L', (0xFF ^ (SEG_D | SEG_E | SEG_F))}, // 18 {'N', (0xFF ^ (SEG_C | SEG_E | SEG_G))}, // 19 {'O', (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F))}, // 20 {'P', (0xFF ^ (SEG_A | SEG_B | SEG_E | SEG_F | SEG_G))}, // 21 {'П', (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F))}, // 22 {'-', (0xFF ^ (SEG_G))}, // 23 {' ', 0xFF}, // 24 #endif {0xFF, 0xFF}, }; //================== //================== u08 dsp_buf [MAX_LED_INDS]; //---------- // Очистка буфера дисплея. u08 dsp_buf [MAX_LED_INDS]; void clr_dsp_buf (void) { for (u08 i = 0; i < MAX_LED_INDS; i++) dsp_buf [i] = ' '; } //================== //================== u08 recod_char_7_segm_cod (u08 data) { struct tab_char_7_segm_cod_t __flash *ptr = tab_char_7_segm_cod; for (; ptr -> Char != 0xFF; ptr++) { if (ptr -> Char == data) return ptr -> seven_segm_cod; } return false; } //================== //================== static u08 _proc_7_segm_ind; void set_proc_7_segm_ind_on (void) { _proc_7_segm_ind = 1; } void set_proc_7_segm_ind_off (void) { _oe_disable (); _proc_7_segm_ind = 0; } void proc_7_segm_ind (void) { static soft_timer ST_PROC_7_SEGM_IND; static u08 cnt_7_segm_ind; u08 a; u08 inds; u08 segments; switch (_proc_7_segm_ind) { case 0: break; case 1: spi_init (); cnt_7_segm_ind = 0; set_soft_timer (ST_PROC_7_SEGM_IND, 1, 1); _proc_7_segm_ind = 2; break; case 2: if (handle_soft_timer (ST_PROC_7_SEGM_IND)) { u08 cnt = cnt_7_segm_ind; cnt_7_segm_ind = tab_index_inds [cnt].i; inds = tab_index_inds [cnt].ind; segments = recod_char_7_segm_cod (dsp_buf [cnt_7_segm_ind]); spi_transf_buf [0] = inds; a = segments; if ((get_dp_flag () == true) && (cnt_7_segm_ind == 2)) { #ifdef __SEGMENT_METHOD_ONE__ a |= SEG_H; #endif #ifdef __SEGMENT_METHOD_ZERO__ a &= (0xFF ^ SEG_H); #endif } spi_transf_buf [1] = a; strob_latch_in (); for (u08 i = 0; i < SPI_BYTES; i++) { spi_transf (i); spi_receive_buf [i] = SPDR; } _oe_disable (); strob_latch_out (); _oe_enable (); } break; default: break; } } //================== |
Автор: | asus2015 [ Вс ноя 19, 2017 22:34:29 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
Исправьте в название регистр 595й |
Автор: | 7seg [ Пн ноя 20, 2017 03:12:42 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
Уважаемый модератор исправьте пожалуйста ошибочку в название темы, которая была допущена мною ( . На Динамическая индикация на 74HC595 |
Автор: | Demiurg [ Пн ноя 20, 2017 03:14:19 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC597 |
Это можно и самому сделать. Правка и меняете заголовок. |
Автор: | 7seg [ Пн ноя 20, 2017 03:29:43 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC595 |
Starichok51, в первых прошивках делал по принципу который вы описали ) но как оказалось при смени камня или печатной латы даже того же индикатора ,следовало вносить очень много правок (. Поэтому было решено написать более универсальную функцию, и теперь всё изменения кода сводиться к правке дефайнов. Добавлено after 2 minutes 15 seconds: Re: Динамическая индикация на 74HC597 Demiurg, к сожалению править можно только свежие посты( |
Автор: | Starichok51 [ Пн ноя 20, 2017 06:39:21 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC595 |
я исправил название. если нужна портация под разные устройства, тогда ты прав, и я беру свои слова обратно. |
Автор: | 7seg [ Пн ноя 20, 2017 06:49:16 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC595 |
Не хочу создавать новую тему решил спросить тут, может кто посоветовать для прочтения книжечку/статейки про КА(конечные автоматы)?, а если в ней еще будут примеры то было бы совсем замечательно ) Добавлено after 36 seconds: И спасибо за правку названия темы Starichok51. |
Автор: | Demiurg [ Пн ноя 20, 2017 07:24:57 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC595 |
Почему-то пропали статьи. Тут про них написано. Там же ссылка на архив статей Татарчевского. Лично я с этих статей многое почерпнул. Ищите также Шалыто. Ну и "автоматное программирование", "конечные автоматы". |
Автор: | 7seg [ Пн ноя 20, 2017 08:05:57 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC595 |
Demiurg, Спасибо за Статью и автора книги, попробую проникнуться парадигмой автома́тного программи́рования ) |
Автор: | 7seg [ Пт ноя 24, 2017 09:41:35 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC595 |
Дабы не создавать новую тему , есть у кого на примете (твердотельные реле или гальванически развязанные ключи ) ? DIP4 На подобии KAQY214 или PVA3054NPBF. Просто (PC817+Транзистор) слишком много места занимают (. Характеристики нагрузки: 12..24V 100mA. Управление сдвиговые регистры или сам МК. |
Автор: | Demiurg [ Пт ноя 24, 2017 09:53:05 ] |
Заголовок сообщения: | Re: Динамическая индикация на 74HC595 |
PRAB37S. Отечественные. Протон-Орел. Сам использую. Доволен. У мну есть сколько-то. Запас. Сколько не помню, надо смотреть. |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |