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;
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;
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;
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Это Протеус косячит, в реальном железе будет работать. У китайцев же эти модули работаютСпойлерНо и Протеус можно заставить корректно отображать, так сказать для отладки, надо просто
Нет, неверно, но если ваш компутер переваривает 100 кадр/сек, можете поставить. Я туда не лазил.
Просто отсоедините вывод OE микрух R3R и R8ANOD от общей схемы, что бы они в воздухе оказались, соедините их между собой, подсоедините это соединение OE через инвертор к точке соединения выводов ST_CP микрух R3R и R8ANOD.
Если не понятно вот схемаСпойлерЕще раз говорю, исходный код тот же, ни чего не надо там менять, это только для отладки в протеусе, в реальной схеме будет работать и без этого. Это только для вашего кода, вы неверно формируете импульс ST_CP для 74HC595, хотя этот импульс может быть верен для 74HC165 (не разбирался с ней, не знаю). Это только для протеуса. Инвертор формирует правильный импульс для вывода OE. Не зацикливайтесь на этом.Спойлер
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; } }
все это до фига избыточно (как и многое другое в полном коде). достаточно определить байты цифр - по одному байту для каждой цифры. вот, как это сделано у меня:
там также определены дополнительные символы, которые нужно выводить. (сегменты в байтах идут не по порядку, а так, как было удобно разводить на плате).
далее все просто: соответственно цифре ее код (байт) отправляем прямо в порт. либо другой нужный символ. и не нужны твои огромные навороты с объявлениями большой кучи констант и созданием комбинаций из этих констант...
_________________ Мудрость приходит вместе с импотенцией... Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Писанины много, это так. Но тут полностью работает пословица: долго запрягаем, зато быстро едем. Последующие проекты собираются гораздо быстрее. Тебе остается переопределить пины и все. Немного посложнее с микросхемами ввода-вывода. Но все равно, при шаблоне проект гораздо быстрее собрать, чем с нуля все писать. Динамическая индикация. Расширение ввода-вывода. 74HC595. Период вывода 1 мс. Функция работает в основном цикле. Ну про свой подход в программировании я неоднократно писал.
Starichok51, в первых прошивках делал по принципу который вы описали ) но как оказалось при смени камня или печатной латы даже того же индикатора ,следовало вносить очень много правок (. Поэтому было решено написать более универсальную функцию, и теперь всё изменения кода сводиться к правке дефайнов.
Добавлено after 2 minutes 15 seconds: Re: Динамическая индикация на 74HC597 Demiurg, к сожалению править можно только свежие посты(
Не хочу создавать новую тему решил спросить тут, может кто посоветовать для прочтения книжечку/статейки про КА(конечные автоматы)?, а если в ней еще будут примеры то было бы совсем замечательно )
Добавлено after 36 seconds: И спасибо за правку названия темы Starichok51.
Почему-то пропали статьи. Тут про них написано. Там же ссылка на архив статей Татарчевского. Лично я с этих статей многое почерпнул. Ищите также Шалыто. Ну и "автоматное программирование", "конечные автоматы".
Дабы не создавать новую тему , есть у кого на примете (твердотельные реле или гальванически развязанные ключи ) ? DIP4 На подобии KAQY214 или PVA3054NPBF. Просто (PC817+Транзистор) слишком много места занимают (. Характеристики нагрузки: 12..24V 100mA. Управление сдвиговые регистры или сам МК.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 26
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения