Ока в Новосибирске

Клуб Окаводов Новосибирска
Текущее время: 29 мар 2024, 00:25

Часовой пояс: UTC + 7 часов




Начать новую тему Ответить на тему  [ Сообщений: 24 ]  На страницу 1, 2  След.
Автор Сообщение
СообщениеДобавлено: 27 янв 2020, 10:46 
Не в сети
Site Admin
Аватара пользователя

Зарегистрирован: 10 апр 2007, 22:36
Сообщения: 11206
Откуда: Новосибирск, Дзержинский
Авто: ВАЗ-21043
Имя: Алексей
oka275 писал(а):
Про смену компилятора я уже думаю постоянно. Какую версию ставить лучше? В седьмой вот используется Майкрософтовская оболочка visual studio, которая близка мне по С#. Но все равно какая-то обрубленная.

Попробовал перенести простенький проектик в Студию, как тут же столкнулся с проблемой. Ответ нашел здесь. Вот честно - даже не верится, что это всё способно благотворно влиять на проекты. К чему такие сложности не пойму. В CVAVR такого гемороя нету. :-D Тут же какие-то палочки и костылёчки. А сам компилятор на основе Visual Studio от Microsoft мне заходит хорошо. Я уже писал, что эта оболочка знакома мне по C#. CVAVR в этом действительно проигрывает. И отладчик в Студии весёлый.

Ладно, буду потихоньку перетаскивать пробный проектик. Заодно подучусь, потому как синтаксис порой очень различается. Там видно будет.

_________________

Поблагодарить автора:
Контакты:
Телеграмм: alexSh154
Вконтакте
Одноквассники
Instagram
Skype: искать oka275 (в англ.раскладке)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 янв 2020, 13:51 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 23 ноя 2014, 16:40
Сообщения: 113
Откуда: Приморский край, г.Находка
Авто: Land Cruser Prado
Имя: Павел
Цитата:
Попробовал перенести простенький проектик в Студию, как тут же столкнулся с проблемой.

Цитата:
В CVAVR такого гемороя нету. :-D Тут же какие-то палочки и костылёчки.

Да, есть маленько. Синтаксис другой. При отладке есть нюансы. Например такие как вход в функцию _delay... Порой аж вымораживает. И другого способа перескочить эту функцию кроме как комментировать их перед отладкой, я не нашел. А еще в Code Vision есть такое понятие как битовые переменные, которые удобно было использовать как некие флаги различных событий. В Студии же минимальный размер переменной - байт. Поэтому обычно я назначаю переменную флагов, в которой каждый бит (флаг) привязан к какому либо событию и в дальнейшем просто читаю необходимый бит(флаг) с этой переменной. Вообщем на привыкание необходимо время, которого вечно не хватает :( . Могу скинуть в личку документик в котором расписаны самые необходимые операции. Там всего пару листочков. При переходе на Студию где-то в сети нашел. Сейчас-то я уже это дело и так помню, а раньше частенько подглядывал.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 янв 2020, 15:51 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 23 ноя 2014, 16:40
Сообщения: 113
Откуда: Приморский край, г.Находка
Авто: Land Cruser Prado
Имя: Павел
Тот самый документик. А еще обработчики прерываний в Студии по другому описываются. Тоже где-то сохранял для себя, но что-то не могу найти.


Вложения:
Операции с битами регистров.docx [232.79 КБ]
Скачиваний: 284
Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 янв 2020, 16:02 
Не в сети
Site Admin
Аватара пользователя

Зарегистрирован: 10 апр 2007, 22:36
Сообщения: 11206
Откуда: Новосибирск, Дзержинский
Авто: ВАЗ-21043
Имя: Алексей
PSh писал(а):
Например такие как вход в функцию _delay... Порой аж вымораживает.

Не совсем понял что именно. А вообще нет блин, взяли и вкрячили нижнее подчёркивание. Ну словно как прикололись? В принципе, можно задеффайнить это, например так
Код:
#define delay_ms _delay_ms

, если я вообще верно понял чего именно "вымораживает".

PSh писал(а):
В Студии же минимальный размер переменной - байт.

Сначала огорчился, но потом погуглил и оказалось, что
Код:
#include <stdbool.h>
........
... и после этого Studio прекрасно съедает, например, вот такое объявление: bool minus=false;

Поигрался настройками оптимизатора. Решил убедиться в ЧУДЕ AVR Studio и сравнить размер прошивки с точно таким же кодом, но от CVAVR. Кстати, не факт что я правильно делаю - наверное надо сравнивать бинарники, а не HEX-ы? Ну ладно. В общем, каково было мое удивление, что прошивка из Studio была примерно на 100 байт больше CVAVR-овской! Ну, думаю, зря потратил пол-дня на ерунду. Еще подумал, что может быть добавленная stdbool.h для битовых переменных что-то сжирает? Удалил, перевел все переменные (их не много, ровно 5 штук) из битовых в байтовые. Компилирую - капец! Прошивка стала еще жирнее! Отменяю все изменения - всё вернулось обратно. Но когда в Studio включил максимальный режим сжатия (Optimize for size), то она не оставила никаких шансов: 4129 байт против 4513 байт CVAVR! В последней, кстати, тоже стояло Optimize for size, так что условия в общем-то равны.

Опять словил гемор с управлением портами. Тааааак удобно в CVAVR: PORTC.4 = 1; - поднять пин 4 порта С в единицу! Эту же конструкцию можно даже читать. В Studio же это просто садомазохизм какой-то. Конечно я наработаю свои приёмы, можно даже функцию состряпать простенькую. И, передавая ей параметры, рулить портами просто и легко. Но как тяжело отказаться от простого в пользу как бы прааааавильного.

_________________

Поблагодарить автора:
Контакты:
Телеграмм: alexSh154
Вконтакте
Одноквассники
Instagram
Skype: искать oka275 (в англ.раскладке)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 янв 2020, 16:22 
Не в сети
Site Admin
Аватара пользователя

Зарегистрирован: 10 апр 2007, 22:36
Сообщения: 11206
Откуда: Новосибирск, Дзержинский
Авто: ВАЗ-21043
Имя: Алексей
PSh писал(а):
Тот самый документик. А еще обработчики прерываний в Студии по другому описываются. Тоже где-то сохранял для себя, но что-то не могу найти.

Отличный документ! Еще и про ЕЕПРОМ есть. И даже пример того, как можно писать в определенную ячейку по адресу. Это важно! Всё хотел в ЗУ разграничить переменные, чтобы знать по какому адресу что где лежит.

Про прерывания - да, неплохо бы документик тоже. Сегодня помучался немного с объявлением обработчика. Конечно же он в CVAVR называется по-другому! Но потом догнал, да и Студия дальше сама мне помогла подсказками по первым символам. Я прям приторчал.

А вообще 90% кода моего небольшого проектика без проблем переехало под новый компилятор, не считая упомянутых выше затыков с управлением портами, _delay-ями и обработчиком. Чувствуется родство душплатформ (или языков). Это не IAR EWAVR. По-моему я разбирался в коде этого компилятора, но это как русский и польский язык, что вот иногда знакомые слова пролетают, а понять в целом ничего не можешь. Это лично моё впечатление.

_________________

Поблагодарить автора:
Контакты:
Телеграмм: alexSh154
Вконтакте
Одноквассники
Instagram
Skype: искать oka275 (в англ.раскладке)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 янв 2020, 18:27 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 23 ноя 2014, 16:40
Сообщения: 113
Откуда: Приморский край, г.Находка
Авто: Land Cruser Prado
Имя: Павел
Цитата:
Не совсем понял что именно. А вообще нет блин, взяли и вкрячили нижнее подчёркивание.

Я имею ввиду при отладке неудобно немного. Например пошагово идем по коду, и на пути стоит команда например _delay_ms(20). И вот при выполнении этой команды открывается дополнительное окно, где и будешь висеть пока эта задержка не кончится. На выручку приходит применение точек останова, но не всегда это удобно. Вот и приходится перед пошаговой отладкой комментировать _delay. Или возникает какое либо прерывание, рабочая точка перемещается в обработчик прерывания, а там _delay... И снова выскакивает это окно... Выходишь, комментируешь и т.д. То забудешь закомментировать, то потом раскомментировать. Короче неудобно.
Цитата:
... и после этого Studio прекрасно съедает, например, вот такое объявление: bool minus=false;

Не знал... Можно будет попробовать!
Цитата:
В общем, каково было мое удивление, что прошивка из Studio была примерно на 100 байт больше CVAVR-овской!

Да, всетаки я так думаю, что размер программы зависит например от составленного алгоритма и еще каких-то факторов.
А еще в Студии есть такая фишка, тоже на мой взгляд неудобная, потому что игнорируя это дело программа может не заработать и задолбаешься ошибку искать. Я про объявление переменных с квалификатором "volatile". Пример из одной из моих программ:

unsigned char flag_button; //переменная вспомогательных флагов для работы с клавиатурой
unsigned int button_counter; //вспомогательная переменная счетчика длительного нажатия кнопки
volatile unsigned char flag_rabota; //переменная вспомогательных флагов для организации работы основной программы
volatile unsigned long f_priyema; //переменная хранения частоты приема (начальная частота = 124,000МГц)

Из разных источников описание этого volatile разное. Я до конца так и не понял в каких конкретно случаях переменную нужно объявлять именно с volatile. Но понял, что использование volatile неплохо так жрет память, потому что все что связано с переменными, объявленными таким образом, не участвует в оптимизации!
Пока я для себя сделал такой вывод: переменные, которые используются в обработчиках прерываний, по любому нужно объявлять с volatile. переменные, не участвующие в обработчиках прерываний, можно объявить и без него. Это тоже я вычитал где-то. И пока ни на какие грабли не наступил.
Как-то товарищ попросил сделать аппарат для ректификационной колонны. Ради накопления знаний и опыта решил взяться. Устройство сложное, очень много вычислений, 4-х строчный дисплей, датчик атмосферного давления, датчики температур, стабилизация напряжения на нагревателе куча всяких разных настроек и еще много всего. МК взял ATmega16. Программу начинал писать в Code Vision, т.к. на тот момент она для меня была более привычной. Ну и в определенный момент уперся в нехватку памяти. Проект развернулся примерно на 80...85% от задуманного. В итоге всетаки решил все перевести в Atmel Studio. Оп, немного памяти освободилось. Но не очень много (по сравнению с тем что я писал выше про термометр, там прилично получилось освободить). Причесал код, еще немножко выиграл. И тут я вспомнил про volatile (тогда я его толкал везде и всюду, на всякий случай). Оставил этот квалификатор только у переменных, участвующих в обработчиках прерываний. И на тебе!!! Появилось целое поле, делай что хочешь! Задуманное все было реализовано! Еще осталось немного места. Ну как это всегда бывает, в процессе испытаний у товарища появилось много желаний, добавок и того и этого. А памяти всего пару процентов оставалось. Включил оптимизацию на максимум. И снова поле!!! Вообщем завершил проект вполне удачно. Товарищ доволен как кот! Я тоже! Угостил меня продуктом ;) ! Вообщем получилось круто. Вообще думаю что в ATmega16 впихнул невпихуемое...
И вот на этом аппарате я и забыл про Code Vision.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 янв 2020, 18:59 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 23 ноя 2014, 16:40
Сообщения: 113
Откуда: Приморский край, г.Находка
Авто: Land Cruser Prado
Имя: Павел
Еще забыл про оптимизацию написать. Как-то в одном из источников наткнулся на информацию, что оптимизацию в процессе разработки программы менять не желательно. Возможны глюки. Т.е. поставил первый уровень и шпаришь на этом уровне оптимизации до конца. А если необходимо изменить уровень оптимизации, то необходимо создать новый проект, установить необходимый уровень оптимизации, скопировать в проект программу и продолжать далее ее написание. Это я про Atmel Studio.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 янв 2020, 19:20 
Не в сети
Site Admin
Аватара пользователя

Зарегистрирован: 10 апр 2007, 22:36
Сообщения: 11206
Откуда: Новосибирск, Дзержинский
Авто: ВАЗ-21043
Имя: Алексей
Поняяятно. Спасибо за бесценный опыт, Павел!
На счет volatile прочитал тут https://tproger.ru/problems/what-is-the ... tile-in-c/
Волатильные переменные используются как глобальные переменные в многопотоковых программах — любой поток может изменить общие переменные
Пытаюсь рассуждать вслух:
Ну в атмеге16 точно уж один поток, хоть и создаётся порой иллюзия одновременного исполнения за счет прерываний. Я не знаю как отнести это к МК "мелкой" архитектуры. В CVAVR переменные, которые участвуют в прерываниях и потом значения этих переменных используются в основном цикле, где даже иногда их значение изменяются - это обычные переменные нужного типа (char, int и тд). Только конечно они обязательно должны быть объявлены глобально (это мы все знаем). И всё до сих пор работало нормально. Так что может быть это совсем не про нас *PARDON* Я бы обязательно попробовал лишить их этой волотильности :-[ :-D и посмотрел бы что с этого будет.

_________________

Поблагодарить автора:
Контакты:
Телеграмм: alexSh154
Вконтакте
Одноквассники
Instagram
Skype: искать oka275 (в англ.раскладке)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 янв 2020, 19:42 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 23 ноя 2014, 16:40
Сообщения: 113
Откуда: Приморский край, г.Находка
Авто: Land Cruser Prado
Имя: Павел
Вот тут и проблема... Пару раз наталкивался на такое, что данные с переменной чудным образом куда-то девались, или изменялись, не помню уже. Хорошо при отладке этой части программы я сразу обратил на это внимание. А иногда компилятор выдает предупреждение. Объявляешь volatile и все ок.
Цитата:
На счет volatile прочитал тут

Вот ещё один источник. Вообщем с этим volatile есть некая путаница.
Да, я помоему уже пробовал лишать все переменные volatile. И там вроде получалось так, что переменная счетчик, обявленная глобально, должна увеличиваться в обработчике прерывания по переполнению таймера. И вот рабочая точка заходит в обработчик, увеличивает эту переменную, выходит из обработчика. А когда при следующем переполнении таймера снова вызывается прерывание, в этой переменной снова 0. Вроде бы так было. Точно уже не вспомню, может это и в другой ситуации было. Это надо так, по факту таких блох ловить и выяснять причину глюка.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 янв 2020, 20:10 
Не в сети
Site Admin
Аватара пользователя

Зарегистрирован: 10 апр 2007, 22:36
Сообщения: 11206
Откуда: Новосибирск, Дзержинский
Авто: ВАЗ-21043
Имя: Алексей
Понятно. Буду иметь ввиду (если не забуду) :-[

Итак, чего мне первый день принёс? Писать постоянно в коде типа PORTC |= (1 << 4) - это можно маньяком стать и на помощь конечно пришли директивы. Но тоже не гибко и код повторяется. Сваял себе маленькую библиотечку (если можно её так назвать). Вынесу её в отдельный файлик, типа там ports_out.c, буду подгружать в проект #include "ports_out.c" и использовать почти как PORTC.3=1; (как привык в CVAVR). После замены кучи дефайнов на эту библиотечку, hex-файл никак не изменился. Но если проект будет большой и работа с портами будет куда более активной, думаю даже небольшая выгода будет :-D

Выложу сюда, может кому из начинающих пригодится:
Вложение:
img-2020-01-27-19-47-06.png
img-2020-01-27-19-47-06.png [ 28.95 КБ | Просмотров: 8406 ]

Вот так выглядит библиотечка.

Вложение:
img-2020-01-27-19-48-05.png
img-2020-01-27-19-48-05.png [ 3.02 КБ | Просмотров: 8406 ]

Вызов очень простой - указать номер пина и желаемое состояние - 0 или 1.

Вложение:
img-2020-01-27-19-48-44.png
img-2020-01-27-19-48-44.png [ 9.67 КБ | Просмотров: 8406 ]

А с соответствующими дефайнами так вообще одно удовольствие )))

Вложение:
ports_out.c [490 байт]
Скачиваний: 274

_________________

Поблагодарить автора:
Контакты:
Телеграмм: alexSh154
Вконтакте
Одноквассники
Instagram
Skype: искать oka275 (в англ.раскладке)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 янв 2020, 04:27 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 23 ноя 2014, 16:40
Сообщения: 113
Откуда: Приморский край, г.Находка
Авто: Land Cruser Prado
Имя: Павел
Так это тогда нужно делать библиотеку и для считывания состояния определенного бита порта. Это конечно дело каждого, кому как удобней. Я бы так делать не стал, потому что кроме портов у нас есть ещё переменные, в определенные биты которых тоже часто нужно записать или считать 1 или 0. И получается что в тексте программы команды записи/считывания бита порта и бита некой переменной будут выглядеть по разному. На мой взгляд это сделает программу менее читаемой. Тогда для таких переменных тоже библиотека нужна (или дополнять уже существующую). Мне кажется это не рациональное использование памяти. Но наверное это дело привычки. Кому как нравится, тот так и делает.
А так в строках вроде как все понятно:
PORDC |= 1<<5; //установить 5 бит порта С
PORTC & = ~(1<<5); //сбросить 5 бит порта С
data |= 1<<3; //установить 3 бит переменной data
data & = ~(1<<2); //сбросить 2 бит переменной data
it(PINC & (1<<7)) //считать состояние бита 7 порта С
if(data & (1<<4)) //считать состояние бита 4
// переменной data
Только что скобочек многовато :(. Зато смотришь в текст программы и сразу понятно, какой бит ты считываешь или в какой бит записываешь. Это как говориться на вкус и цвет...


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 янв 2020, 06:07 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 18 мар 2016, 16:52
Сообщения: 58
Авто: NISSAN
Имя: Олег
Доброго времени суток, Алексей и Павел.
Давненько я здесь неписал, но за темой слежу. И так к делу. Хочу Вас "подтолкнуть" в сторону макроопределений. Ведь Студия использует компилятор GCC, а это еще и макро язык. Думаю это секономит и RAM и время выполнения, по сравнению с Вашим подходом. Потому как каждый раз, при обращении к пину MCU будет вызывать функции при которых заполняется СТЕК, и делаются лишние телодвижения. А если это происходит еще и в обработчике прерывания ? Зачем грузить каждый раз MCU ? Давайте нагрузим один раз компилятор. В Codevision такого нет. Предлагаю идею и реализацию уважаемого человека под ником WiseLord, популярного и на GitHub и на Радиокоте своим проэктами "AmpControl". Я лишь взял на себя смелость добавить ремарки в его файлы и немножко изменить для наглядности. Хотя там и так все понятно. Правда проэкт я скомпилил в СТУДИИ 4.19.
Загляните в файлик в архиве с рашрирением lss. Установка в 1 или в 0 занимает всего одну ассемблерную комманду.


Вложения:
pins_macros.RAR [8.21 КБ]
Скачиваний: 279
Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 янв 2020, 08:12 
Не в сети
Site Admin
Аватара пользователя

Зарегистрирован: 10 апр 2007, 22:36
Сообщения: 11206
Откуда: Новосибирск, Дзержинский
Авто: ВАЗ-21043
Имя: Алексей
Здравствуйте, Олег! Прикольная лялька! Спасибо! Я искал как раз что-то подобное. То есть при таком исполнении стек не заполняется?

Попытаюсь порассуждать вслух: За то, как мне кажется, не получится сэкономить на флеше. Потому, что каждый раз будет использована новая команда работы с портом - лишние байты, когда можно определить одну функцию и обращаться к ней каждый раз. Пусть при таком подходе заполняется стек, но на много ли? Тем более, сразу после выполнения единственной команды в функции(ну кроме IF/ELSE, конечно), она закончит свою работу и стек откатится на прежнее состояние (если я верно помню предназначение стека и как он работает) и МК побежит по своим делам дальше.

_________________

Поблагодарить автора:
Контакты:
Телеграмм: alexSh154
Вконтакте
Одноквассники
Instagram
Skype: искать oka275 (в англ.раскладке)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 янв 2020, 08:18 
Не в сети
Site Admin
Аватара пользователя

Зарегистрирован: 10 апр 2007, 22:36
Сообщения: 11206
Откуда: Новосибирск, Дзержинский
Авто: ВАЗ-21043
Имя: Алексей
oka275 писал(а):
А так в строках вроде как все понятно:
PORDC |= 1<<5; //установить 5 бит порта С
PORTC & = ~(1<<5); //сбросить 5 бит порта С

Да, Павел, видимо это действительно дело привычки. Как Винни-пуха расстраивали длинные слова, так и я не привык еще после CVAVR видеть такое нагромождение всяких закорючек :-D Хотя действительно всё понятно! На худой конец можно воспользоваться макроопределениями, предложенными Олегом. Это тоже самое, но чуть по-другому выглядит.

_________________

Поблагодарить автора:
Контакты:
Телеграмм: alexSh154
Вконтакте
Одноквассники
Instagram
Skype: искать oka275 (в англ.раскладке)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 янв 2020, 15:14 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 23 ноя 2014, 16:40
Сообщения: 113
Откуда: Приморский край, г.Находка
Авто: Land Cruser Prado
Имя: Павел
Цитата:
Загляните в файлик в архиве с рашрирением lss.

Добрался до компьютера, посмотрел. Ну да, можно и так :)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 янв 2020, 22:26 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 18 мар 2016, 16:52
Сообщения: 58
Авто: NISSAN
Имя: Олег
oka275 писал(а):
Здравствуйте, Олег! Прикольная лялька! Спасибо! Я искал как раз что-то подобное. То есть при таком исполнении стек не заполняется?

Алексей, данные макроопределение к СТЕКу не имеют вообще никакого отношения. Там нет ни вызовов функций, ни переходов, тоесть "ветвления" при которых перед вызовом, в СТЕК помещается адрес для обратного возврата. Хотя можно создать один макрос с функцией. Да и не дело тут в стеке. А в удобстве. Чтобы в каждом месте не писать эти чудо-символы, вспоминая при этом где они находятся на клавиатуре, а описать их один раз, и потом использовать во всей программе. А влиять макрос, на ресурсы MCU НЕМОЖЕТ. Ведь макроязык - это не язык программирования для MCU, это язык для КОМПИЛЯТОРА. К примеру многие программисты любят использовать тип переменной BYTE вместо CHAR. А компилятор, вообще ни сном ни духом не знает о существовании такого типа. Вот тут и пригодится макроопределение. И после этого компилятор в исходнике при встрече типа BYTE подставит CHAR. И все поймут друг друга.
Ну и подтвеждение моего применения. Вроде писанины в исходниках много. Но результ в конце компиляции машинный код.
Кусок из файла *.lss

Код:
// Использование макроподстановок
int main(void)
{
    OUT(LED_RED);  // Здесь компилятор подставит строку DDRB |=(1<<0)
  38:   b8 9a          sbi   0x17, 0   ; 23 <------------------------------- установить бит 0 в регистре с адресом 0x17 в 1
                  // тоесть настроит пин на OUT установкой бита в 1
    IN(BUTTON);    // Здесь компилятор подставит строку DDRB &=~(1<<1)
  3a:   b9 98          cbi   0x17, 1   ; 23
                   // тоесть настроит пин на IN установкой бита в 0
    SET(BUTTON);   // Подключаем внутренний pull-up резистор
  3c:   c1 9a          sbi   0x18, 1   ; 24


Всего два байта заняла одна ассемблерная комманда. Я Вас, ни вкоем случае, непереубеждаю применять этот метод. И Ваш подход имеет право на жизнь. Я все лишь хотел расскрыть прелести и удобства макросов


Последний раз редактировалось olegzom 29 янв 2020, 06:35, всего редактировалось 2 раз(а).

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 29 янв 2020, 05:08 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 23 ноя 2014, 16:40
Сообщения: 113
Откуда: Приморский край, г.Находка
Авто: Land Cruser Prado
Имя: Павел
Да уж... С макросами я как-то не работал. Надо повникать в эту тему :-[


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 29 янв 2020, 06:32 
Не в сети
Уже был(а), и не раз, и не два

Зарегистрирован: 18 мар 2016, 16:52
Сообщения: 58
Авто: NISSAN
Имя: Олег
oka275 писал(а):
Попытаюсь порассуждать вслух: За то, как мне кажется, не получится сэкономить на флеше. Потому, что каждый раз будет использована новая команда работы с портом - лишние байты, когда можно определить одну функцию и обращаться к ней каждый раз.


Как раз и получится. И еще как. Даная "макроподстановка" дергания пина занимает во флеши всего два байта - одна команда в машинном коде, меньше некуда. Я специально создал проектик по Вашему методу, компильнул и вот результат из lss:

Код:
0000006a <main>:
{
 #define ON   true   // 1
 #define OFF  false  // 0
 char LED_RED=0; // для PB0

 DDRB|=(1<<LED_RED);  // Настройка PB0 на OUT обратите ВНИМАНИЕ 1 команда в АСМЕ
  6a:   b8 9a          sbi   0x17, 0   ; 23
 _PORTB(LED_RED,ON);  // Подготовка к установке PB0 в 1
  6c:   80 e0          ldi   r24, 0x00   ; 0                                 <------------------------ 2 байта
  6e:   61 e0          ldi   r22, 0x01   ; 1                                 <------------------------ 2 байта
  70:   e3 df          rcall   .-58        ; 0x38 <_PORTB>          <------------------------ 2 байта и здесь будет использоваться СТЕК
 _PORTB(LED_RED,OFF); // Подготовка к установке PB0 в 0
  72:   80 e0          ldi   r24, 0x00   ; 0
  74:   60 e0          ldi   r22, 0x00   ; 0
  76:   e0 df          rcall   .-64        ; 0x38 <_PORTB>       
  78:   ff cf          rjmp   .-2         ; 0x78 <main+0xe>



Получается каждый вызов процедуры дергания пина - шесть байт. Это что касаемо экономии места во flash.
Этих шесть байт будут занимать флеш при каждом вызове процедуры установки бита. Да, конечно, сама процедура установки - одно место(колличество байт тоже можно подсчитать, но не суть). Но два байта против шести.
Теперь по быстродействию. При "макросоподходе" - пин опрокинется сразу при выполнении асмовской команды sbi-установка пина в 1 или cbi-сброс пина в 0 , которые, напомню занимают 2 байта

А вот кусок процедурного метода:

Код:
// это обработчик пина
void _PORTB (char pin, bool bit)
{
   if(bit) PORTB |= (1 << pin); // Тут уже вроде должны БЫСТРО переключить в 1
  38:   66 23          and   r22, r22
  3a:   59 f0          breq   .+22        ; 0x52 <__SREG__+0x13>
  3c:   98 b3          in   r25, 0x18   ; 24
  3e:   21 e0          ldi   r18, 0x01   ; 1
  40:   30 e0          ldi   r19, 0x00   ; 0
  42:   02 c0          rjmp   .+4         ; 0x48 <__SREG__+0x9>
  44:   22 0f          add   r18, r18
  46:   33 1f          adc   r19, r19
  48:   8a 95          dec   r24
  4a:   e2 f7          brpl   .-8         ; 0x44 <__SREG__+0x5>
  4c:   92 2b          or   r25, r18
  4e:   98 bb          out   0x18, r25   ; 24           <--------------------- Ажжж здесь опрокинется
  50:   08 95          ret
   else PORTB &=~(1 << pin);    // А вот здесь в 0
  52:   98 b3          in   r25, 0x18   ; 24
  54:   21 e0          ldi   r18, 0x01   ; 1
  56:   30 e0          ldi   r19, 0x00   ; 0
  58:   02 c0          rjmp   .+4         ; 0x5e <__SREG__+0x1f>
  5a:   22 0f          add   r18, r18
  5c:   33 1f          adc   r19, r19
  5e:   8a 95          dec   r24
  60:   e2 f7          brpl   .-8         ; 0x5a <__SREG__+0x1b>
  62:   20 95          com   r18
  64:   29 23          and   r18, r25
  66:   28 bb          out   0x18, r18   ; 24                      <---------------- ELSE здесь опрокинется
  68:   08 95          ret


То есть MCU, пока добереться до самой команды смены уровней на пине, отработает несколько команд проверок, загрузок в регистры и математики.
Да и опять же, дело не в макроопределениях в данной ситуации. Это просто дает возможность красиво, гибко и "причесано" применять вроде этого PORTB|=(1<<0). Но это самый быстрый и экономный способ (в плане MCU) работы с битами.
Если нужно, могу и этот проэктик целиком выложить. Но помоему здесь и так все понятно, если вы знакомы с асемблером.
Я специально в Сишных исходниках раскидаю ремарки, они попадают после компиляции в асемблерный файл. Так легче потом локализовать тот или инной кусок кода в листинге асма, что по сути и является рузультатом "перевода" из Си в машинны код, только более наглядный для восприятия человеком. А вот Линкер уже делает его понятным для MCU.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 29 янв 2020, 10:03 
Не в сети
Site Admin
Аватара пользователя

Зарегистрирован: 10 апр 2007, 22:36
Сообщения: 11206
Откуда: Новосибирск, Дзержинский
Авто: ВАЗ-21043
Имя: Алексей
olegzom писал(а):
Всего два байта заняла одна ассемблерная комманда. Я Вас, ни вкоем случае, непереубеждаю применять этот метод. И Ваш подход имеет право на жизнь. Я все лишь хотел расскрыть прелести и удобства макросов

Олег, да я и не спорю. Вся информация убедительна. Все, что я может быть напишу дальше, это лишь попытка разобраться, т.к. мне не всё понятно. Кстати, функцией #define пользуюсь постоянно в силу своих знаний и фантазии, и продолжаю совершенствовать этот опыт.

olegzom писал(а):
если вы знакомы с асемблером.

Скажем так, что имею представление. Во времена Spectrum делал шаги по изучению, даже простенькие программки делал. Уже конечно много подзабыл, да и команды тут какие-то незнакомые что-ли.

olegzom писал(а):
Получается каждый вызов процедуры дергания пина - шесть байт. Это что касаемо экономии места во flash.

Не совсем понял. Эти 6 байт есть непосредственная подготовка к вызову функции? Или сама функция занимает 6 байт вместо одного, как в макросе?
А вот теперь из области того, чего я пока не могу понять вообще: Если эти 6 байт сидят в самой функции, а непосредственный её вызов "ничего не стоит", то проигрыш в экономии места во флеши будет только, если этих вызывов будет менее шести. А дальше типа уже должна начинаться экономия (пусть в ущерб быстродействию, напряганию стека и тд). Нам на уроках информатики говорили, что если в коде несколько раз встречаются одинаковые фрагменты, то это серьезный повод для того, чтобы создать функцию с ним и вызывать её нужное количество раз. Мол, это ведет к сокращению и оптимизации программы. В Ваших трудах я пока что вижу обратное, без всяких вариантов. А если таких вызывов в программе будет 100, 200? Двести байт макросов против 6 байт функции. Что я неправильно понимаю?

_________________

Поблагодарить автора:
Контакты:
Телеграмм: alexSh154
Вконтакте
Одноквассники
Instagram
Skype: искать oka275 (в англ.раскладке)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 29 янв 2020, 17:21 
Не в сети
Заслуженный участник Клуба ЗУ-ОКА275

Зарегистрирован: 21 янв 2016, 05:33
Сообщения: 13
Авто: golfvi
Имя: Евгений
oka275 писал(а):
Не совсем понял. Эти 6 байт есть непосредственная подготовка к вызову функции?

Здравствуйте Алексей.
У любой функции, помимо рабочего кода, есть пролог и эпилог-это неизбежные накладные расходы, разработчик решает сам, что лучше использовать:
макроподстановки - выигрываем в скорости, проигрываем в объеме
вызов функций - соответственно наоборот (при достаточно большом количестве вызовов)
так же есть ключи компилятора, которые позволяют разворачивать тело функции в месте вызова( получается почти аналог макроподстановки).
В любом случае необходимо экспериментировать на примере конкретной здачи, единой рекомендации тут быть не может :)


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 24 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 7 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB