Проблема начинающих на форумах по микроконтроллерам в том, что они пытаются начинать программировать без знания языка и/или железа. Если второе еще можно понять, то с первого всегда стоит начинать.
спасибо товарищи за вашу помощь, за разносторонний подход и критику) теперь я буду каждый ваш предложенный вариант прорабатывать, в си я новичок это правда , немного знаю ассемблер, так то я железячник) но решил пробрался в ваши стройные ряды сишников) еще раз спасибо, обстоятельно позанимаюсь полученой информацией и выложу сюда свой код вам на суд))
_________________ глаза боятся, а руки что то не делают))
ну простите великодушно, про Demiurg-а я как-то забыл... у вас второе место
Demiurg писал(а):
И считаю, что новичкам нужно практически сразу и с него начинать. Проблема начинающих однотипна. На всех известных мне форумах по микроконтроллерам.
и только единственнй последователь этого метода - вы - на всем просторе интернета знает истину? не смешите: каждый программист-самоучка уверен, что именно он нашел единственно верный подход к тому, как с нуля освоить "это". профессиональным программистам проще - они просто "тупо" делают, что им скажут (сначала в учебных заведениях, потом по работе), и не считают свой путь исключительным, единственным и неповторимым...
NStorm писал(а):
Проблема начинающих на форумах по микроконтроллерам в том, что они пытаются начинать программировать без знания языка и/или железа. Если второе еще можно понять, то с первого всегда стоит начинать.
а вот я уверен, что начинать надо не с языка... начинать надо именно с логического мышления, алгоритмизации. как минимум, надо научиться излагать свои собственные мысли непротиворечиво, четко и кратко. подставлять вместо "если" слово "if" или заменять предложение "повторять вот это самое сктолько-то раз" или "пока не наступаает такое-то собыие, надо делать..." соответствующим оператором цикла - самое простое. то есть узнать относительно небольшой набор синтаксических правил и десяток ключевых слов (то есть освоить основы языка) - это, хоть и важно, но далеко не первостепенно.
я учил "программирвоание" в ВУЗе еще тогда, когда в ходу были "мини-ЭВМ м-6000". учили нас бейсику, паскалю, фортрану, PL/1 и ассемблеру i8080... но по-настоящему я научился программировать, когда взял (у друга) в руки калькулятор МК-61 и написал самостоятельно реализацию игры "быки и коровы", а позже - аналог "городков" по мотивам из журнала "Наука и жизнь". именно тогда я осознал, что без умения решать задачи в уме никакие знания языков программирования не помогут.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
а вот я уверен, что начинать надо не с языка... начинать надо именно с логического мышления, алгоритмизации. как минимум, надо научиться излагать свои собственные мысли непротиворечиво, четко и кратко. подставлять вместо "если" слово "if" или заменять предложение "повторять вот это самое сктолько-то раз" или "пока не наступаает такое-то собыие, надо делать..." соответствующим оператором цикла - самое простое. то есть узнать относительно небольшой набор синтаксических правил и десяток ключевых слов (то есть освоить основы языка) - это, хоть и важно, но далеко не первостепенно.
Ну подразумевается, что это уже есть на базовом уровне. НО от языка много что зависит. Да в том же банально С мы видим что в этой теме, что в других, когда приходя с АСМа, люди пытаются "в лоб" решать задачи, алгоритмы слишком прямолинейны. Не используется гибкость языка. И возможности. Ресурсы расходуются расточительно. Множество повторяющегося кода и т.д. А уж если за пределы С посмотреть, и пока за пределы эмбедеда - ух! В корне другие парадигмы программирования. С++ тот же с ООП, если писать именно в ООП стиле, а не как на "С с доп. возможностями", то многое меняется. А уж всякие функциональные языки программирования... тут совсем не поможет алгоритмическое мышление, принявшееся до этого в императивном программировании. С бурным развитием железок, они и в сегмент эмбеддед проникают уже. Вопрос сложный с общем достаточно. Но я согласен, что в целом без должного склада ума и умения в логику нельзя никак. Но у ТС конкретно в этой теме вопрос уже в технике владения Си.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Проблема не в языке. Если человек решает задачи прямолинейно, он на любом языке будет это делать. Я начал с ассемблера. Сидел на нем несколько лет. Как раз на ассемблере алгоритмы и рулят. Но и на этом этапе я смотрел дальше. Алгоритмы, подходы. Системный подход в решении задач. Когда я перешёл на си, мне стало проще только в одном аспекте. Я перестал думать о регистрах. То есть ещё на этапе ассемблера я уже думал на уровне объектов.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Demiurg вы себя похвалили, мы похлопали, меня перевели в ранг тормозов ( покорнейше благодарю) надеюсь вы не будите тратить свое драгоценное время на эту тему.
_________________ глаза боятся, а руки что то не делают))
Я в вашу сторону намеков не делал. Мало того, подарил вам один своих проектов со своими наработками, к которым я шел несколько лет. Поэтому, можете надумывать и дуть губки. А можете засунуть свой гонор (я тоже когда-то начинал), и учиться на чужих примерах. Я не хвалился, а показывал, как вам вникнуть в интересный мир МК. Если вы молодой, ничего страшного, поймете. Если уже в возрасте, значит поняли, что я сказал. Вы в топике уже написали, что понятия не имеете, как сделать параллельную работу программных модулей. Я это понял с первого же вашего сообщения. В моем проекте решение этой проблемы.
не буду дуть губки) как то не к лицу) значит я не верно вас понял, принял не за того ,тогда примите мои извинения , мир суров приходится быть на чеку))
_________________ глаза боятся, а руки что то не делают))
Такой подход в разы сокращает время на создание проекта. Проекты собираются как конструктор из модулей.
Это точно, где-то лет 5 назад применил алгоритм из цикла статей Татарчевского, и вообще проблем не знаю, пару раз меня когда придумывал только более удачные доработки.Кстати к ним можно отнести, избавление от системы событий, немножко не нравилось что на 1 опросы кнопок надо 2-3 процесса в майне закрутить, причем они как бы друг друге же сидят. Весь модуль не буду приводить так как там у меня хаос с define и масками. Вот основные функции Вот основная логика алгоритма тут, тоже наворочено многое, что особо неиспользуеться, причесать это руки не доходят(делал событие на отжатие кнопки) Спойлер
Код:
//======================== /* * @Описание: Сканирует клавиатуру и преобразует полученный код ввиде событий. * @Параметр: Нету. */ void ProcessKeyFSM(void){ uint16_t Key_Code; //---------- if(Scan_key(&Key_Code)){ //---------- //---------- switch(key_state){ //---------Ожидаем нажатие клавиши------------- case WAIT_KEY:{ if(Key_Code>0){ // Получен код _Key_Code=Key_Code; // сохранили текущий код timer_set_ms(&KEY_TIMERS,DEBOUSE); key_state=WAIT_DEBOUNCE;// изменили состояние } break; } //---------- case WAIT_DEBOUNCE:{ if(timer_expired(&KEY_TIMERS)){ key_state=CHEK_PRESS; } break; } //---------- // фиксируем нажатие кнопки и отправляем сообщение case CHEK_PRESS:{ if(Key_Code==_Key_Code){ //сравниваем текущий код клавиши с тем который был в самом первом состоянии //--------Клавиша нажата------------------ //--------Передаем код клавиши------------ //--------Тип клавиши--------------------- //---------- Processing_ScanCodekey(MSG_TYPE_PRESS,Key_Code); //---------- timer_set_ms(&KEY_TIMERS,(FIRST_DELAY-1)); key_state=DELAY_AVTO; }else{ key_state=WAIT_KEY; }
break; } //---------- // В этом состоянии осуществляется задержка перед автоповтором нажатия кнопки // Перед тем как начнется длительное нажатие кнопки case DELAY_AVTO:{ if(Key_Code==_Key_Code){ if(timer_expired(&KEY_TIMERS)){ #if long_pressing==1 //------Длительное нажатие----------------- //--------Клавиша нажата------------------ //--------Передаем код клавиши------------ //--------Тип клавиши--------------------- Processing_ScanCodekey(MSG_TYPE_LONG,Key_Code); //---------- #endif timer_set_ms(&KEY_TIMERS,AUTO_REPEAT); } }else{ //--Добавил 18.02.2015 // нету разделения между этим отжатием и после длительного удержанием(.. отжатием) #if key_up==1 //---------- клавиши(отжатие)---------- //--------Клавиша нажата------------------ //--------Передаем код клавиши------------ //--------Тип клавиши--------------------- //---------- Processing_ScanCodekey(MSG_TYPE_UP,_Key_Code); //---------- #endif key_state=WAIT_KEY; } break; } //---------- // Длительное нажатие пока кнопка не отпущена будет генерироваться событие // На обработку длительного нажатия // А как только кнопку отпустят отправится сообщение на отжатие кнопки case AVTO:{ if(Key_Code==_Key_Code){ if(timer_expired(&KEY_TIMERS)){ #if long_pressing==1 //--------Клавиша нажата------------------ //--------Передаем код клавиши------------ //--------Тип клавиши--------------------- Processing_ScanCodekey(MSG_TYPE_LONG,Key_Code); //---------- #endif timer_set_ms(&KEY_TIMERS,(AUTO_REPEAT)); key_state=AVTO; } }else{ #if key_up==1 //---------- клавиши(отжатие)---------- //--------Клавиша нажата------------------ //--------Передаем код клавиши------------ //--------Тип клавиши--------------------- Processing_ScanCodekey(MSG_TYPE_UP,_Key_Code); //---------- #endif key_state=WAIT_KEY; } break; } //---------- default:{key_state=WAIT_KEY;break;} //Ошибка } } }
Потом идет файл с зависимостью от железа (количества кнопок) Спойлер
//======================== /* * @Описание: Анализирует полученный скан код и вызывает соответствующий обработчик. * @Параметр: MSG_TYPE_KEY - тип скан кода MSG_TYPE_PRESS - быстрое нажатие. MSG_TYPE_LONG длительное нажатие. MSG_TYPE_UP - отпускание клавиши. * @Параметр: MSG_CODE_KEY - Код клавиш(несколько зажатых). */ void Processing_ScanCodekey(uint8_t MSG_TYPE_KEY,uint16_t MSG_CODE_KEY){ //---------- switch(MSG_TYPE_KEY){ case MSG_TYPE_PRESS:{ switch(MSG_CODE_KEY){ //---------- case but_OK:{Handler_key(PRES_OK);break;} case but_ESC:{Handler_key(PRES_ESC);break;} case but_UP:{Handler_key(PRES_UP);break;} case but_DOWN:{Handler_key(PRES_DOWN);break;} //case but_RIGHT:{Handler_key(PRES_RIGHT);break;} //case but_LEFT:{Handler_key(PRES_LEFT);break;} //---------- // case but_F1:{Handler_key(PRES_F1);break;} // case but_F2:{Handler_key(PRES_F2);break;} // case but_F3:{Handler_key(PRES_F3);break;} // case but_F4:{Handler_key(PRES_F4);break;} //-------двойное нажатие--------------------------------------------------- //case but_LOCK:{Handler_key(PRES_LOCK_UNLOCK_KEY);break;}// кнопка 2 отпущена //---------- default:{break;} } break; } //---------- нажатие------------------------------------------- #if long_pressing==1 case MSG_TYPE_LONG:{ switch(MSG_CODE_KEY){ //---------- case but_OK:{Handler_key(PRES_LONG_OK);break;} case but_ESC:{Handler_key(PRES_LONG_ESC);break;} case but_UP:{Handler_key(PRES_LONG_UP);break;} case but_DOWN:{Handler_key(PRES_LONG_DOWN);break;} //---------- case (but_UP|but_ESC|but_DOWN):{Handler_key(PRES_LONG_DOWN_UP_ESC);break;} // case but_F1:{Handler_key(PRES_LONG_F1);break;} // case but_F2:{Handler_key(PRES_LONG_F2);break;} // case but_F3:{Handler_key(PRES_LONG_F3);break;} // case but_F4:{Handler_key(PRES_LONG_F4);break;} //---------- default:{break;} } break; } #endif //---------- кнопки------------------------------------------- #if key_up==1 case MSG_TYPE_UP:{ switch(MSG_CODE_KEY){ //---------- case but_OK:{Handler_key(RELEASED_OK);break;} case but_ESC:{Handler_key(RELEASED_ESC);break;} case but_UP:{Handler_key(RELEASED_UP);break;} case but_DOWN:{Handler_key(RELEASED_DOWN);break;} // case but_RIGHT:{Handler_key(RELEASED_RIGHT);break;} // case but_LEFT:{Handler_key(RELEASED_LEFT);break;} //---------- // case but_F1:{Handler_key(RELEASED_F1);break;} // case but_F2:{Handler_key(RELEASED_F2);break;} // case but_F3:{Handler_key(RELEASED_F3);break;} // case but_F4:{Handler_key(RELEASED_F4);break;} default:{break;} } break; } #endif } //---------- }
Ну и на последок как это все используеться с примером, хождения по меню, в файле с меню находиться функция menu_Key, во время инициализации дрейвера клавиатуры её мы подцепляем (init_driver_key(&menu_Key);) к нему, и по нажатию кнопки будет вызываться menu_Key с передачей в неё какая кнопка была нажата или сочетание кнопок + тип нажатия долго жали или быстро
Код:
int main(){ init_driver_key(&menu_Key); while(1){ ProcessKeyFSM(); }
menu_Key:Спойлер
Код:
//========= //========= //========= /* * @Описание: Обработчик сообщений от кнопок * @Параметр: sel_out - код события (выходной параметр) */ void menu_Key(unsigned char key_code){ static uint8_t CntPresButWebRestart=0; //---------- //---Перезапускаем обработчик сброса в дефлтный пункт меню------- //---Если была нажата любая клавиша------------------------------ ResetTimerRebootMenu(); //---------- switch(key_code){ //---------- //-------Нажатие кнопки OK-------------------- //---------- //case PRES_LONG_OK: case PRES_OK:{ //----Секундная задержка на повторное нажатие ок--- if ((MENU_OK) != 0){ add_queue_act_menu(MENU_OK); } menuChange(CHILD); break; } //---------- //-------Нажатие кнопки ESC----------------- //---------- case PRES_LONG_ESC: case PRES_ESC:{ if ((MENU_ESC) != 0) { add_queue_act_menu(MENU_ESC); } menuChange(PARENT); // Сначало вызвали действие а потом отобразим то что в было в предыдушем пункте break; } //---------- //-------Нажатие кнопки UP----------------- //---------- case PRES_LONG_UP: case PRES_UP:{ if ((MENU_UP) != 0) { add_queue_act_menu(MENU_UP); } menuChange(PREVIOUS); break; } //---------- //-------Нажатие кнопки DOWN----------------- //---------- case PRES_LONG_DOWN: case PRES_DOWN:{ if ((MENU_DOWN) != 0) { add_queue_act_menu(MENU_DOWN); } menuChange(NEXT); break; } //---------- //---------- //---------- case PRES_LONG_DOWN_UP_ESC:{ CntPresButWebRestart++; if(CntPresButWebRestart>3){ CntPresButWebRestart=0; SHOW_MESEGER(" Web Restart ",1500); } break; } default:{break;} } //---------- }
Доброго времени суток! В теме несколько вариантов кода включения нагрузки по нажатию кнопки, а можно сделать чтобы при нажатии кнопки высокий уровень появлялся не сразу а с задержкой 0.2 сек а при отпускании сразу переключался на низкий.
В теме несколько вариантов кода включения нагрузки по нажатию кнопки, а можно сделать чтобы при нажатии кнопки высокий уровень появлялся не сразу а с задержкой 0.2 сек а при отпускании сразу переключался на низкий.
Эмм... а зачем тут МК тогда? ) Дребезг легко убирается аппаратно.
Ну у меня такое впечатление, что в данной теме когда такие вопросы задают, то больше МК делать ничего и не будет. Если уж такой вопрос возникает. Тогда зачем ставить МК, когда можно копеечную логическую ИС поставить. Надежнее и проще будет. Конечно задачу нужно рисовать в целом в таких случаях.
Ответ прост. На МК можно задать логику работы, ничего не перепаивая. Понимаете, целесообразность, она тоже разная бывает. Кто пойдёт из вашего же соображения. Типа зачем МК. А кто то ценит свое время выше вашей целесообразности. Это тоже целесообразно.
А кто то ценит свое время выше вашей целесообразности.
Сомнительно. Для МК нужно написать программу и прошить. Это легко, когда знаешь хотя бы основы. Но тогда подобных вопросов не возникает, это ж элементарщина. Я уж молчу о деньгах. Что 6-разрядная ИС логики стоит 3 рубля в розницу и есть в любом радиолюбительском ларьке. А МК за адекватные деньги надо почтой ждать из Китая. Короче всё зависит от задачи в целом, как я уже сказал.
Короче всё зависит от задачи в целом, как я уже сказал.
Эта тема не первый раз поднимается. И если я не путаю, вы тоже тогда участвовали. Именно на условиях задачи мы и остановились. Притом под условиями понимается многое. Вплоть до жизненной ситуации.
Можно. В теме я дал достаточно примеров, чтобы за полчаса а то и меньше накидать то, что вы просите.
Добавлено after 26 minutes 10 seconds: Готово.
Спасибо огромное!!!! Схема нужна для задержки включения усилителя передатчика. В симуляторе перепробовал много простых транзисторных ключей с задержкой, не понравилось. На жёсткой логике можно конечно, но плата заточена под конкретный корпус и места очень мало, а элементов там довольно много. Поэтому стал смотреть в сторону мк. А в плане цены единичного экземпляра устройства цена 5 и 50 руб роли никакой не играет
Стоп. Вам не пример нужен был, а готовая прошивка? В архиве проект скомпилирован как тестовый. Времянки уменьшены. Так как симулятор AVR-Studio на сотни миллисекунд долго отрабатывает.
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения