NStorm, спасибо. Дизасму включил. Камень pic10f322, это я реализовал контроллер управления питанием от Li-ion, который включает/выключает нагрузку от нажатия кнопки на 15 минут (с автоотключением), или без автоотключения в зависимости от положения перемычки. Так же идет предупреждение звуковым сигналом, если напряжение на АКБ меньше 3,2В, или отключение при напряжении на АКБ менее 3В. По поводу: 1. Так как это контроллер управления питанием, то он всегда подключен к банке АКБ, поэтому единоразовая проверка(во время инициализации регистров) не подходит поэтому проверка в коде программы, и режимы работы легко меняются в активном состоянии. Хотя раньше я делал в ассемблере, как Вы советуете. 2. А как кнопка может тормознуть программу? Опрос кнопки идет на определенном участке программы, а прерывания отключены в основном цикле программы, и вкл только на период сна 3. Так с конца программы после звукового сигнала отключения итак идет переход на начало (после Power_Off) на while (1) и контроллер уходит в спячку.
Насчет безGOTOвых переходов еще потренируюсь писать программы, чтобы обойтись без них.
2. Ну вас в коде одна проверка: "if (!TK) // если кнопка нажата - подаем короткий звуковой сигнал" внутри сразу уже в любом случае происходит сигнал, после которого ожидание 999мс. Вот тут и тормозится. 3. return в c - выход из функции. Из main() значит завершение программы. Не уверен, как код генерит xc8, но в avr-gcc насколько я помню в этом случае проиходит переход ко встроенной функции exit(), где просто крутится бесконечный цикл. Надо будет глянуть что xc8 выдает при return'e из main().
2. Точно, 2 проверки состояния кнопки. Короткое нажатие просто сбрасывает таймер ожидания и подает звуковой сигнал (чтобы устройство не отключилось). Длинное нажатие более 1 сек подает сначала короткий звуковой сигнал, а потом двухтональный сигнал отключения и спячка
Глянул выхлоп xc8 - понятно, он инициализацию пихает в конец, а return из main() реально возвращается в конец инициализации этой, на последней адрес во флэш памяти. Тем самым прокручивая PC обратно до 0. Но как-то это неправильно с точки зрения Си. Это не на while(1) прыжок обратно, а всей программы сначала. Все переменные будут переинициализированы. Кстати полный дизасм еще генерится в каталоге с проектом в подкаталоге dist/default/TARGET/PROJECT.lst
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
3. В общем всё-равно на МК в общем принципе для портабельности лучше избегать return из main(). 2. Ну если вам тут не важно, что нажатие кнопки даже короткое по сути откладывает измерение АЦП на секунду, то можно и так конечно оставить.
Цитата:
Да нет, именно на while(1) прыгает.
Это видимо оптимизатор постарался. Вообще в целом return из main() в embedded зависит от компилятора.
Вообщем СИ и МПЛАБ Х вещь, раньше сидел на Асме, и не знаю сколько бы у меня ушло времени на написание аналогичной программы, где куча программных таймеров связанных между собой. А вышеуказанную программу написал менее чем за день с учетом того, что раньше не имел опыта написания программ на СИ (мигание светодиода не в счет). Еще конфигурируемые логические ячейки довольно забавная вещь. https://habr.com/ru/post/372509/ Я проверил - работает, но правда ног у 10f322 очень мало. Закажу МК, где ног побольше для экспериментов. Можно будет например аппаратные подавители дребезга контактов кнопки/энкодера делать...
4uvak, всё-таки это не программные таймеры, а просто задержки. Но в остальном вы правы, на Си куда проще многие штуки делаются. Но надо учиться абстрагироваться от асма, тут так в лоб не надо. Я даже не о сложных абстракциях, которые можно делать в Си, а просто хотя бы к базовым вещами привакать - не надо "переходить", надо вызывать функции. А потом еще привыкаем к тому, что у функций бывают аргументы и возвращаемое значение.
у функций бывают аргументы и возвращаемое значение.
Прямого отношения к Си это не имеет. На АСМе совершенно так же делаются вызовы, в подпрограмму передаются значения и подпрограмма возвращает значение. Тут дело не в языке, а в мышлении. В способности генерировать абстракции вообще, а не потому, что так требует язык. Кстати, код написанный на АСМе в стиле языка высокого уровня не намного более объёмен нежели в ЯВУ.
Прямого отношения к Си это не имеет. На АСМе совершенно так же делаются вызовы, в подпрограмму передаются значения и подпрограмма возвращает значение. Тут дело не в языке, а в мышлении. В способности генерировать абстракции вообще, а не потому, что так требует язык.
Без сомнения. Но обычно на асме более прямолинейно всегда пишут. ЯВУ всё-таки более располагает к большему уровню абстракции
Кстати, код написанный на АСМе в стиле языка высокого уровня не намного более объёмен нежели в ЯВУ.
Смотря какой уровень сложности программы и владения ЯВУ. Структуры в Си, например, очень сильно могу сократить объем и наглядность кода. Да и портабельность с ЯВУ проще - перейти с одной архитектуры на другую с ЯВУ попроще - не надо набор инструкций на низком уровне изучать и "привыкать" к ним. Но я не хочу разводить холивар на этом месте. Везде свои преимущества. Оптимизация под архитектуру на асме ес-но возможна такая, которой ни один оптимизатор ЯВУ не сможет.
Это начало основного цикла while (1), по условиям ложного срабатывания (контроллер чувствителен к помехам по цепям питания) и он ложно может выйти из сна через прерывание. Поэтому я добавил строку с проверкой срабатывания кнопки после сна. Если кнопка не нажата нужно повторно отправиться спать. Я организовал команду перехода через goto qwe. Есть другой способ начать цикл заново?
Код:
while (1) { qwe: PWM1CON = 0b00000000; // отключаем ШИМ1 FVRCON = 0b00000000; // отключаем ИОН, отключаем температурный индикатор ADCON = 0b00000000; // отключаем модуль АЦП PORTA = 0; // все выходы порта переводим в низкое состояние __delay_ms(500); IOCIE = 1; // разрешаем прерывание по изменению уровня PORTA IOCAF = 0; // сбрасываем флаг IOCAF (свидетельствующий о прерывании RA3) SWDTEN = 0; // отключаем сторожевой таймер на период сна SLEEP(); // здоровый крепкий сон до пробуждения нажатием кнопки) IOCIE = 0; // запрет прерывания по изменению уровня PORTA SWDTEN = 1; // включаем сторожевой таймер __delay_ms(50); if (TK) // если кнопка отжата - было ложное страбатывание прерывания (из-за помех по цепям питания), отправляемся повторно спать { goto qwe; } CLRWDT(); LED = 1; // включаем питание
while(1){ // тут какой то код перед началом ожидания кнопки while(условие не нажатой кнопки){ // тут код пока кнопка не нажата } // тут код после нажатой кнопки }
4uvak, я вам дал на прошлой странице пример с функциями. Просто вынесите выключение и сон в отдельную функцию и вызывайте её в данном случае. А после неё можно как у вас сделать return (уже из main()), чтобы "перезапуститься".
Еще лучше - начинать переходить к конечному автомату. Если писать сразу так, то все эти переходы между состояниями легче расширяются и обрабатываются.
Вот простенький относительно пример: https://github.com/N-Storm/flashlight/b ... ashlight.c Это я делал для фонарика прошивку на замен штатному китайскому МК на базе PIC10F200 - самый простой и примитивный МК пожалуй в мире из ныне выпускающихся. У него нет прерываний. Поэтому с некоторыми вещами пришлось "извращаться" и очень мало памяти, чтобы сделать красивее. Но оно работает. ) Вот выключение сделано в функции enter_sleep(), которая всё выключает и отправляет МК в сон, как вам нужно.
С нажатием кнопки тоже посмотрите как сделано. Точно также лучше просто в основном цикле если нажата кнопка - увеличиваем некую переменную счетчик. А если отжата - проверяем значение счетчика и тут понятно что у нас было - короткое нажатие, длинное или просто дребезг.
Но если хотите "простыней", то что мешает вместо if (TK) goto qwe; написать:
Код:
IOCIE = 0; // запрет прерывания по изменению уровня PORTA SWDTEN = 1; // включаем сторожевой таймер __delay_ms(50); if (!TK) // если кнопка нажата { CLRWDT(); LED = 1; // включаем питание ... } // qwe: ...
оператор continue немедленно осуществляет переход к проверке условия продолжения цикла (внутри которого находится этот оператор) - это 100% то самое, что вам нужно для замены goto
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Всем добрый день, я в программировании не понимаю, нужна прошивка для pic12f675 или pic12f629 для датчика скорости одометра вектра б, в мплаб пробовал компилировать исходники и постоянно выбрасывает ошибки, прошу вашей помощи.
igorua27, а под XC8 она не соберется, т.к. в бесплатной версии плохая оптимизация и по месту из-за float операций не влезет. Если найдете PRO версию, то вот так переделать: Спойлер
Код:
/****************************************************************/ /* Множитель/делитель частоты */ /* http://radiokot.ru/forum/viewtopic.php?f=20&t=59172 */ /* */ /* МК: PIC12F675 */ /* */ /* Автор: Alex */ /* al.kl@list.ru */ /* http://ChipMk.ru */ /****************************************************************/ // CONFIG #pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-Up Timer Enable bit (PWRT disabled) #pragma config MCLRE = ON // GP3/MCLR pin function select (GP3/MCLR pin function is MCLR) #pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled) #pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled) #pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 11
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения