C vs Assembler

Если ты впервые столкнулся с микроконтроллерами, то наверняка у тебя стал выбор на чем писать.

На Си или на Ассемблере. Выбор не прост, не зря программисты однокристальщики раскололись на два непримиримых лагеря. Одни с пеной у рта доказывают, что те кто пишут на Си лохи изнеженные, а настоящий брутальный кодер должен воспринимать только ассемблер. Другие же, усераясь, доказывают, что на ассемблере разве что лампочками помигать можно, а какой либо серьезный проект делать на низком уровне невозможно.

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

Assembler+
Парадоксально, но под микроконтроллеры писать на ассемблере ничуть не сложней чем на Си. В самом деле, программирование контроллера неотделимо от его железа. А когда пишешь на ассемблере, то обращаешься со всей периферией контроллера напрямую, видишь что происходит и как это происходит. Главное, что при этом ты четко понимаешь что, как и зачем ты делаешь. Очень легко отлаживать и работа программы как на ладони.
Да и сам ассемблер изучается очень быстро, за считанные дни. Достаточно постоянно иметь перед глазами систему команд и навык программирования алгоритмов. А соответствующее состояние мозга, когда начинаешь мыслить ассемблерными конструкциями наступает очень быстро.

C-
А вот с высокими языками, например с Си, ситуация уже куда хуже. Да, повторить какой нибудь пример из обучалки, вроде вывода строки на дисплей, Сях куда проще, подключил нужную библиотеку, набрал стандартную команду и вот тебе результат. Но это только так кажется. На самом деле, стоит чуть вильнуть в сторону, как начинается темный лес. Особенно когда дело начинает касаться адресации разных видов памяти,

Напомню, что у AVR, как и подавляющего числа МК, память разделена на код и данные и адреса у них в разных адресных пространствах о которых стандарт Си ничего не знает, ведь он расчитан на некий универсальный вычислитель. А тут приходится вводить всякие модификаторы, квалификаторы и без яростного курения мануалов разобраться в этих примочках бывает очень сложно. Особенно работа с памятью осложняется тем, что программа то работает в том и другом случае, но вот если неправильно указать тип памяти, то оперативка забьется константами и в дальнейшем программу скрючит в самый неподходящий момент. Вот и найди такой глюк

работе на прерываниях, использованию многопоточных процессов, использующих одни и те же ресурсы.

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

В таких случаях обычно открывают листинг и смотрят что там происходит в коде на уровне команд процессора, но вот засада — без знания ассемблера там делать нечего! Зато если понимаешь то как работает программа на уровне команд, то найти багу вроде срыва стека или нарушения атомарного доступа проще простого.

Ну и такие гадкие вещи как overhead. Программа на Си требует значительно больше оперативной памяти, значительно больше места во flash памяти, работает куда медленней чем ассемблерная программа. И если на обычном компьютере с его гигагерцами частот, гигабайтами оперативки и дисковой памяти это не столь критично, то вот для контроллера с жалкими килобайтами флеша, у которого частота порой не превышает 16 мегагерц, а оперативки и килобайта не наберется, такой расход ресурсов более чем критичен.

Кроме того существуют такие контроллеры как ATTiny 1x у которых либо вообще нет оперативки, либо она такая мизерная, что даже стек там сделан аппаратным. Так что на Си там ничего написать в принципе нельзя.

Assembler+
Представь, что ты прораб, а компилятор это банда джамшутов. И вот надо проделать дырку в стене. Даешь ты джамшутам отвертку и говоришь — ковыряйте. Проковряют они отверткой бетонную стену? Конечно проковыряют, вопрос лишь времени и прочности отвертки. Отвертка сточится (читай памяти процессора или быстродействия не хватит)? Не беда — дадим джамшутам отвертку побольше, благо разница в цене между большой отверткой и маленькой копеечная. В самом деле, зачем прорабу, руководителю, знать такие низкоуровневые тонкости, как прочность и толщина бетонной стены, типы инструмента. Главное дать задание и проконтроллировать выполнение, а джамшуты все сделают сами.
Задача решается? Да! Эффективно это решение? Совершенно нет! А почему? А потому что прораб не знал, что бетон твердый и отверткой его проковырять сложно. А будь прораб сам когда то рабочим, пусть даже не профи, но своими руками положил плитку, посверлил дырки, то впредь таких идиотских заданий бы не давал. Конечно, нашего прораба можно и в шараге выучить, дав ему всю теорию строения стен, инструмента, материалов. Но ты представь сколько это сухой теории придется перелопатить, чтобы чутье было интуитивным, на уровне спинного мозга? Проще дать в руки инструмент и отправить сверлить стены. Практика — лучший учитель.

Также и с ассемблером. Хочешь писать эффективные программы на высокоуровневом языке — изучи хотя бы один ассемблер, попиши на нем немного. Чтобы потом, глядя на любую Сишную строку, представлять себе во что это в итоге компилируется и как обрабатывается контроллером. Очень помогает в отладке и написании, а уж про ревесирование чужих программ я вообще не говорю.

Assembler-
Но засиживаться в ассемблерщиках и стараться все сделать на нем далеко не обязательно. Ассемблерный код тяжелей переносить с контроллера на контроллер, в нем при переносе можно наделать много незначительных, но тем не менее фатальных ошибок. Отладка которых занимает много времени. Большие проекты писать на ассемблере то еще развлечение. На ассемблере трудно сделать полноценную библиотеку, подключаемую куда угодно. Ассемблер жестко привязан к конкретному семейству контроллеров.

С+
Си хорош за счет огромного числа готового кода, который можно очень легко и удобно подключать и использовать в своих нуждах. За большую читабельность алгоритмов. За возможность взять и перетащить код, например, с AVR на ARM без особых заморочек. Или с AVR на PIC. Разумеется для этого надо уметь ПРАВИЛЬНО писать на Си, выделяя все аппаратно зависимые части в HAL.

Общий расклад примерно таков, что использование высокоуровневого языка на контроллерах с обьемом памяти меньше 8 килобайт является избыточным. Тут эффективней писать все на Ассемблере. Особенно если проект подразумевает не просто мигание светодиодом.
8-16 килобайт тут уже зависит от задачи, а вот пытаться писать на ассемблере прошивку более 16 килобайт можно, но это напоминает прокладку тоннеля под Ла Маншем с помощью зубила.

В общем, знать надо и то и другое. Настоятельно тебе рекомендую начать изучать МК с ассемблера. А как только поймешь, что на асме можешь реализовать все что угодно, любой алгоритм. Когда досконально прочувствуешь работу стека, прерываний, организацию переходов и ветвлений. Когда разные трюки и хитрости, вроде игр с адресами возврата из прерываний и процедур, переходами и конечными автоматами на таблицах и всякие извраты будут вызывать лишь интерес, но никак не взрыв мозга из серии «Аааа как это работает??? Не понимаю?!!»
Вот тогда и можно изучать Си. Причем, изучать его с дебагером в руках. Не просто изучить синтаксис (там то как раз все элементарно), а понять ЧТО и КАК делает компилятор из твоего исходника. Поржать над его тупостью или наоборот поудивляться извратам искуственного интелекта. Понять как компилятор делает ветвления, как организует циклы, как идет работа с разными типами данных, как ведется оптимизация. Где ему лучше помочь, написав в ассемблерном стиле, а где не критично и можно во всю ширь использовать языковые возможности Си.

А вот начать изучение ассемблера после Си мало кому удается. Си расслабляет, становится лень и впадлу. Скомпилировалось? Работает? Ну и ладно. А то что там быдлокод, та пофигу… =)

А как же бейсик, паскаль и прочие языки? Они тоже есть на AVR?
Конечно есть, например BascomAVR или MicroPASCAL и во многих случаях там все проще и приятней. Не стоит прельщаться видимой простотой. Она же обернется тем, что потом все равно придется переходить на Си.

Дело в том, что мир микроконтроллеров далеко не ограничивается одним семейством. Постоянно появляются новые виды контроллеров, развиваются новые семейства. Ведь кроме AVR есть еще и ARM, PIC, STM8 и еще куча прекрасных контроллеров со своими плюсами.
И под каждый из этих семейств есть Си компилятор. Ведь Си это, по сути, промышленный стандарт. Он есть везде и контроллер который не имеет под него компилятора популярным у профессионалов не станет никогда.

А вот на бейсик с паскалем, обычно, всем пофигу. Если на AVR и PIC эти компиляторы и сделали, то лишь потому, что процы эти стали особо популярны у любителей и там наверняка найдется тот, кто заинтересуется и бейсиками всякими. С другим семейством контроллеров далеко не факт, что будет также радужно. Например под STM8 или Cortex M3 я видел Pascal в лучшем случае только в виде кривых студенческих поделок. Никак не тянущих на нормальный компилятор.

Такой разный Си
С Си тоже не все гладко. Тут следует избегать компиляторов придумывающих свои диалектные фишки. Например, CodeVision AVR (CVAVR) позволяет обращаться к битам порта с помощью такого кода:

1
PORTB.7 = 1; 		// Выставить бит 7 порта B в 1

Удобно? Конечно удобно! Вот только в Си так делать нельзя, стандарт языка не позволяет. И ни один другой Си компилятор такой кусок кода не примет. Т.к. по стандарту корректней будет так:

1
PORTB |= 1<<7;

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

Приплюснутый
Некоторое время назад я считал, что С++ в программировании микроконтроллеров не место. Слишком большой overhead. C тех пор мое мнение несколько поменялось.
Мне показали очень красивый кусок кода на С++, который компилился вообще во что то феерическое. Компактней и быстрей я бы и на ассемблере не факт что написал. А уж про читабельность и конфигурируемость и говорить не приходится. Все из знакомых программистов, кто видел этот код, говорили что-то вроде «Черт, а я то думал, что я знаю С++».

Так что писать на С++ можно! Но сделать компактный и быстрый код на С++ чертовски виртуозная задача, надо знать этот самый С++ в совершенстве. Судя по тому, что столь качественных примеров эффективности С++ при программировании под МК мне попадалось раз-два, то видимо пороговый уровень входа в эту область весьма и весьма велик.

В общем, как говорил Джон Кармак, «хороший С++ код лучше чем хороший С код. Но плохой С++ может быть намного ужасней чем плохой С код».

83 thoughts on “C vs Assembler”

    1. Вот для этого и надо изучать ассемблер, чтобы сразу же вкурить что там и для чего. Кстати, попробуй пописать софт под Tiny ;))) я в своих разработках стараюсь делать все на них — они дешевле. Для одиночного дейвайса это не критично, но когда их приходится делать десятками…

    1. Да региться тут не обязательно было :) Комментить можно либо по мылу, либо по open ID (от ЖЖ вполне работет, вписывай свой ЖЖ адрес в поле URL и все)

    2. Ну, коль уж зарегился, куда уж терь, зато и сайтик поддержим. Хотя в закладках месяца 3 лежит -че только не перечитали….Грейт Респект!

  1. я думаю что примеры прог нужно писать (абстрактно или уневерсально) т-е а заголовке проги описываем присвоение метки—регистр или порт потому как конечный пользователь может использовать любую мегу и стало быть вероятность что ваш пример у него не заработает, конечно моё предложение призывает к тому что надо бы сделать на каждый проц заголовок или один ну почти на все к тому же я такой где то видел…..

    kuzminyaleksandr@yandex.ru

    1. Дак и так у меня вначале каждой проги идет присвоение всего всему, а дальше только символические метки/замещения, так что можно будет при желании перевесить все на другие порты. Но трудность в том, что у AVR сильно разнится набор команд внутри семейств (особенно в Tiny), а также переферийные девайсы могут иметь разный фунционал. Так что не все тут так просто, одними макросами не обойдешься.

  2. Ассемблер это конечно хорошо и правильно, но возникают серьезные проблемы со скоростью разработки. + разоборатся в ассемблерном листинге (даже зная его досконально) будет посложнее чем в сишном. В общем ассемблер знать нужно, факт. Но вот о массовом применение речь помоему не идет….

    1. От задачи зависит. Сталкивался с тем, что приходилось все упихивать в один кристалл и выбора тут не было :)

  3. Грамотно, но хотелось бы добавить от себя пару слов.
    Компилятор компилятору рознь, особенно по части оптимизации. Не совсем верно будет прессовать в одно и то же IAR с avr-gcc и КодВижен, к примеру. Также и с «готовеньким», а уже из количества «готовенького» высчитывается «тёмный лес». Например, в avr-gcc уровень достаточно низок, чтобы не уходить в дебри при чтении даташита на АВР’ку. Часто встречаются inline функции, которые сводятся до 1-3 ассемблерной команд(ы).
    Что до tiny — да, лучше ассемблер, но при хорошем знании компилятора можно попробовать и Си.

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

      + на ГСС дофига готового кода и все в одном месте. На иар тоже не меньше, но все как то разрозненно.

      1. На avr-gcc полез потому, что:
        а) официально его поддерживает AVR Studio;
        б) именно под него заточен Obdev AVR-USB;
        в) по тестам на разных форумах в оптимизации кода уступал только IAR’у;
        г) OpenSource.

        А где это одно место с готовым кодом? :) Для меня единственным источником данных всегда был мануал на avr-libc.
        В любом случае, имхо, если есть время и возможность — лучше наклепать набор собственных lib’ов, что в ASM, что в Си. Иначе на чём не пиши — полного понимания не будет.

          1. avr-libc — это штатное. ;) Мифы это — про FAT и Enet. Да и задача в avr-libc другая — там нет ничего того, чтобы нельзя было бы написать минут за 5. Так сказать, платформа, элементарная для понимания, на базе которой уже строятся свои библиотеки. Чаще всего я, например, использую delay.h — кристаллонезависимые _us и _ms задержки. Сделать свои сложно? Нет. Понять принцип сложно? Нет. Если очень уж прижало — delay_basic.h — элементарные циклы-задержки со счётчиком, в которых откалибровано количество тактов за итерацию. Мелочь? А приятно.
            А ещё больше там простых дефайнов. Вот кому будет интересно писать то, что PIN1 — это 1, а PIN7 — это 7? :)

            http://www.nongnu.org/avr-libc/user-manual/modules.html
            А что главное — вижу различия с моей текущей локальной версией. Появились новые модули — значит, развивается проект.

      2. Недавно обнаружил приятную особенность у компиляторов семейства gcc: бинарная нотация констант: 0bxx или 0Bxx, по аналогии 0xFF :-) мелочь а приятно, у себя в блоге чуть более полно описал.

        1. Хм, только заметил? В AVR ассемблере это изначально так было, я даже и не задумывался когда в GCC это применял.

    1. Вот только готовых либ для AVR под него кот наплакал. А коли уж писать с нуля, так может уж сразу на ассемблере? ;)

  4. походу и 16 и 32 буду писать не на Си
    почемуто непонимаю Си.. а нормальных обучалок не встречал (Си везде Си повсюду..позор, но чтож делать)
    наверно потомучто понятен мне Паскаль как default и архитектурно привязаный-Асемблер

  5. Здравствуйте всем! Уважаемый DI HALT, пробовали ли Вы использовать для своих разработок Algorithm Builder? Если пробовали, то хотелось бы услышать Ваше мнение. С уважением!

    1. Я не пробовал, но общее впечатление — вещь в себе. Да, на ней легко программировать в виду ее визуальности.
      1) Но представь на ней действительно БОЛЬШУЮ программу. Это же сколько этих алгоритмов будет?
      2) Это вещь в себе. Да у него есть поклонники, но такого количества готового кода как на асме или Си под АБ не будет никогда. Так что под любую хрень придется изобретать велосипед заново.

      3) Автор хочет за нее денег. В принципе естественное желание, но платить за это я считаю лишней тратой денег, когда есть бесплатные промышленные решения, вроде WINAVR.

      Ну и личный пример:
      У нас на кафедре разрабатывался вентильный привод. ТАк вот, статор и ротор делали разные команды разработчиков. Профессор руководивший «статором» очень любил АБ. Команда же разработчиков «ротора» крепко сидела на Си. Несмотря на равный примерно обьем работ и схожую квалификацию программеров Сишники сварганили свою часть и отладили ее намного быстрей чем АБшники. Плюс ко всему они вовсю пользовались JTAGом гоняя свою прогу по родному исходнику. Не знаю умеет ли АБ жтаг, но те его даже не пытались заюзать.
      В общем, какой то он странный. Диодом помигать сгодится.

      1. Здравствуйте всем!
        Согласен насчёт АБ. Хотелось бы сказать пару слов в защиту С. Конечно, ассемблер знать нужно, хотя бы для того, чтобы представлять себе, как МК выполняет то или иное действие. Другой момент, что большое количество любителей, а ещё большее количество профессионалов стараются заработать деньги на своём умении и берутся за разработку и программирование различных устройств, где большое значение имеет срок выполнения заказа. Вот здесь и сказываются преимущества С. Разрабатывал как-то на мегу16 программу для управления bluetooth-модулем (для установления голосовой связи между двумя такими модулями). Конечно, на асме программа вышла бы поменьше в размерах, но, думаю, за месяц я бы не управился. Да и заказчику пофиг какого размера прошивка и насколько изящный код — ему главное результат и побыстрей. Использую WinAVR, потому что некоторые дотошные заказчики бывает спрашивают, лицензионный ли компилятор.
        С уважением. Сайт очень познавательный. Удачи!

        1. Скорость написания проги зависит от мастерства программера и наработаного материала. На си правда готовый код найти проще. Но я его ценю в первую очередь за переносимость. Это супер. А вот по написанию… я бы поспорил еще. У меня задачи обычно нестандартные и написание кода это 5% времени, остальное отладка. Тут я на си (пробовал когда то) теряю дико много времени т.к. приходится все равно лазать в ассемблерный листинг и смотреть что там на самом деле происходит. А на асме проц делает точно что ему приказал и никуда не денется. Отлаживать проще, особенно в конченых автоматах с диким количеством состояний. Конечно, помогает JTAG, но его поддерживают только большие меги, а я обычно все делаю на Tiny. в 90% случаев хватает Tiny2313 (я их поэтому и закупаю сразу сотнями штук)

          1. А Вы случайно не знакомы с таким языком как Q-basik ( точнее-QASIQ) ?
            Помнится писал на нём, очень быстро и эффективно работает. Он имеет свой компилятор.
            Правда это было несколько давно ( лет 20 назад),но очень быстро на нём писал программы для Электроника 60.-значительно проще ассемблера,но по скорости ничем не уступал (замерял время выполнения). Жалко что сейчас не могу его пока найти..и назывался он-QASIQ/ ( в отличие от BASIK,который не является компилятором)
            И вопрос: возможно ли написание прог на нём для м/к ATMEL (очень хочется оживить какой-нибудь Микрик)

  6. Отлично! Нигде не встречала нужной инфы в более доходчивом виде, чем здесь. Большое спасибо.

  7. На 99% согласен !!! Но, всё же, моя практика показывает, что писать проект на АСМе, на 64к прекрасно можно … Просто, когда упоминается слово АСМ, люди представляют себе только мнемонику асмовских команд. Имя качественный компилятор, который позволил бы тебе легко смешать высокий уровень и низкий, СИ можно отбросить. Конечно, если человек себе поставил задачу поднять ОСь, то тут только СИ и никакой речь об асме. Но если есть качественный (гибкий) компилятор, то любых размеров проекты пишутся на ура. В любом случае в гигантском проекте как на СИ так и на АСМе будет «мясо». Только на АСМе это мясо при хороших мозгах не будет глючить.

    Я с самого детства мечтал заиметь такой АСМ, который позволил бы мне делать нужный мне набор мат функций но основу оставлял именно АСМа … В итоге я написал собственный асм, с помощью которого уже 10-ть лет пишу проекты для контроллеров. Примерно код у меня выглядит так:

    MOV R6,#0
    MOV A,#10
    MLOOP1:
    PUSH ACC

    LET A=@IzBINW.F
    MATH A=A/G

    LET B=@IzBINB.F
    MATH B=B/H

    LET C=@IzBIN.F
    MATH C=C/I

    MOV R0,#AL0
    CALL CCLR
    MOV DPTR,#RiWi
    MOV A,R6
    MOVC A,@A+DPTR
    MOV AL0+4,A
    MOV A,R6
    INC A
    MOVC A,@A+DPTR
    MOV AL0+5,A
    STORE B
    MATH ((((C-B)/(A-B))*D)+((A-C)/(A-B))*0.00231)*50000+1000

    MOV DPH,#HIGH(RiBIN)
    MOV DPL,R6
    MOV A,AL0+4
    MOVX @DPTR,A
    INC DPTR
    MOV A,AL0+5
    MOVX @DPTR,A

    INC R6

    POP ACC
    DJNZ ACC,MLOOP1

    И нет никаких проблем … Понятно, что у меня получилось более ёмко с точки зрения строчичке, чем в СИ, но с точки зрения кода не хуже. Но не в этом дело, главное, что в программе это 2-3% кода, остальное логика … Я молчу уже про методы матричных процедур, которые в СИ вообще не доступны. А результат — компактность и скорость !!!

    Я по работе в 50% случаев программирую на СИ, но это вынужденность … Всякие линуксы и подобное … Но на много быстрее пишется на универсальном АСМе …

      1. Да, это макросы … Приводить пример не буду, там набор математики, будет ёмко … Собственно команда MATH — просто раскрывает скобки и перед всем этим делает вызов функции калькуляции, остальное это макросы ! Но дело не в этом, главное, что если серьёзно подойти к вопросу кода приближённому к АСМу, можно натворить много уникального … Очень много ! А самое главное, меня поражают высказывания программистов на СИ, которые хвастаются — вот я пишу под АРМ9 или КОРТЕКС ! И в чём оно, это писание заключается именно под АРМ ? В ИФах ??? А как много предоставлено в архитектуре разных ядер. Например банальное перевёртывание байта по битам, я имею в виду зеркальное отражение. На АСМе 5-6 строчек, а СИ такое вам на-оптимизирует, что лучше сразу отформатировать винт с проектом и не начинать вообще, чтобы не позориться.

        Все языки нужно использовать с умом !!! Хотя я больший сторонник низкого уровня.

  8. Добрый день! Изините если не в той теме ворос ,но очень нужна помощь. Объясните как создать массив чисел на асемблере для Atmega16, просто я не могу найти нужную команду:k:
    inc r21 ;\ r21:= r21+1 \
    inc AdrXL ;| увеличения адреса на 1 |
    ;sts $61,r21 ;| | задаём исходный массив чисел
    cpi r21,0b11111110 ;| |
    brne k
    AdrXL—переменная обозначающая адес
    я увеличиваю число, адрес , и хочу записать новое число в новый адрес, а как не знаю, ПОМОГИТЕ!!!!

      1. а это точно та ссылка? Содержание:
        Надо же!

        Кажись, что то пошло не так и страница не нашлась. Ничего, бывает — не беда! Попробуйте осмотреться на моем сайте — там много интересного. Например:
        Реальное положение дел на постсовестком производстве в юмористическом цикле рассказов «Последний Герой Труда»

        Как отучиться в Южно Уральском Гос Университете забивая на все и вся в юмористическом цикле рассказов «Вечный студент»

        Кроме того, я пишу мини рассказики и байки из жизни — тоже есть над чем поржать.

        Любителям погонять на велосипеде наверняка будет любопытно мое мнение об этом виде спорта.

        А может быть, вы увлекаетесь радиоэлектроникой? У меня и под это есть кое чего интересного — я давний любитель паяльника и осциллографа

              1. подскажи какие книги надо почитать чтобы просто и доходчиво дошло,для действительно начинающего

              2. Как оказалось позже то чего я хотела, делается совсем по другому, как мне подсказал преподаватель— просто вручную создать массив чисел—просто, но ушло два вечера)):)

                  1. Конечно,(отл) это нужно было для ДЗ,преподователь конечно в почте чуть-чуть по возмущялся:»Во-первых массив, заданный в вашем варианте ДЗ, размещается в ЭСППЗУ, а для записи\чтения ЭСППЗУ существует своя определенная процедура (описана в моей методичке!!!).»Я об этом рассказывал на практических занятиях.»
                    Но потом всё подробно расказал. Переписывались так как он пол семестра провёл потом уехал в Китай, и Дз присылал по почте и т.д. (ХАИ, что ещё сказать, кстати препод умничка,)

  9. Артемий, я подсчитываю количество переполнений TIFR, чтобы организовать 30 секундную задержку между импульсами на выходе. Если переполнений больше 255, где оптимальней хранить результат болmше чем $FF ?

    1. Ну во первых ТИФР не переполняется. Там всего лишь встает бит переполнения TOV0. Переполняется регистр TCNT. Чтобы получить выдержку в 30 секунд не обязательно много считать. Дело в том, что таймер можно заставить тикать с предделителем. Максимальный, емнип это 1024 т.е. частота тика будет в 1024 раза медленней.

      Ну а если надо именно считать, то либо переменная в памяти, либо один из младших регистров которые реже пользуются (если у тебя тини12 и оперативки нет).

      1. Я и хочу подсчитать количество тиканий TIFR
        Прескалер я и так поставил на 1024. Мне каждые 30 сек импульс нужен
        Кварц у меня 4МГц

        1. Тебе проще будет сделать по прерываниям. Т.е. в прерывании по TOV0 будет щелкать твой счетчик. А главная программа будет его проверять на нужное значение. Как допроверяет — выдает импульс если натикало. Либо тупит дальше.

  10. in Temp,TOV0
    subi Temp,0b00000010
    BRNE METKA1

    Не получается запихнуть в регистр R19 значение регистра переполнения счетчика.
    P.S. ATtiny12

  11. Артем, тавлю RETI и в таблице векторов, и там где пишу подпрограммы обработки, а компилятору похер — ошибку не видит. Это норма ??

    Я тут не понял : если нет ОЗу стек для обработчиков прерываний где формируется
    У тиньки 12 ОЗУ вроде нет

    1. А какую он должен видеть ошибку? RETI это обычная команда выхода из прерывания. Ты их можешь хоть на каждом углу ставить и компилятор не пикнет. Следить за правильностью выхода из прерывания задача программиста.

      У Тини12 стек аппаратный, всего на три уровня или около того.

  12. Уважаемый DI HALT Я последние несколько месяцев плотно занимаюсь самопостижением микроконтроллерной техники AVR. Начал с изучения С/С++, параллельно изучая МК семейства мега. Проштудировал курс «123avr» и вот взявшись за Ваш саит, понял что действительно нуна знать ассемблер, стал въезжать в него потихоньку. И вот теперь у меня в голове образовалась такая каша, что не знаю к какому берегу грести. Прошу поддержать новичка советом. Отступать не собираюсь, просто укажите вектор AVR-ассемблера.

    1. Знач так. Расставляю точки.

      Си это язык промышленный. На нем пишут большие проекты. Его надо знать. Можешь писать все на нем. Ассемблер тоже надо знать, чтобы понимать контроллер и чувствовать узкие места. Напиши на ассемблере несколько простеньких проектов. Проникнись работой, пойми как оно все делается и дальше.

      В ассемблере тебе надо досконально понять следующие вещи:

      Как работает стек. Как в него грузятся переменные, как работают адреса возврата, как сохраняются локальные переменные.

      Как работают прерывания. Как происходит вызов и возврат, куда сохраняются переменные. Как при прерываниях используется стек. Это в первую очередь надо, чтобы просекать атомарные операции, которые на Си совершенно не явные и могут дать жуткие плавающие баги.

      Как работать в ОЗУ и флешем. Работу команд LPM и LD/ST вызов данных и переходы по таблицам.

      Понять систему портов. Что где в контроллере и как это адресуется. Четко понимать сколько нужно команд на занесение, стирание и модификацию битов. ПОнимать разницу между портами старших номеров и младших (они адресуются по разному. Для младших можно биты менять с помощью спец команд sbi cbi а для старших только через IN/OUT а то и STS/LDS через чтение-модификацию-запись и это уже не атомарная операция.

      Как работают битовые операции, битовые маски, логическая математика битовых операций. Типо как изменить один бит в байте.

      Как работают условные операторы, как делаются ветвления и переходы. НАдо чтобы делать более эффективные конструкции на Си, не нагружая процессор лишним гемором.

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

      С++ на МК слишком жирный. На нем можно писать, но надо С++ ОЧЕНЬ ХОРОШО ЗНАТЬ. В частности знать такую вещь как шаблоны С++ тема сложная и нетривиальная, но если достичь тут просветления, то позволяет писать код намного более эффективный чем С, почти на уровне ассемблера.

  13. Вопрос такой — а если знаешь ассемблер для intel и PIC — можно ли в AVR писать сразу на СИ минуя ассемблер? Или на нём тоже лучше сначала изучать ассемблер?

    Что касается PIC контроллеров — то считаю, что СИ — гораздо лучше, потому как один только неверный или пропущенный banksel — и здравствуй глюки… Не говоря уже о простых формулах типа a*b/c+d…

    1. Можно конечно. И будет даже вполне получаться. Но для эффективного кодинга надо знать узкие места системы. Понимать что стоит делать, а что нет и что во что компилится. А иной раз полезно и в ассемблерный листинг заглянуть и проверить правильно ли тебя компилятор понял. Особенно когда дело касается таких неоднозначных с первого взгляда вещей как чтение из флеша в GCC.
      А то многие думают, что поставили квалификатор PROGMEM и усе путем. А потом у них оперативка внезапно кончается :))) И начинают тупить-тормозить. А глянули бы в ассемблер и сразу бы поняли, что все запихивается в оперативку, а не во флеш. И значит что то тут не так и надо уже адресно гуглить.

  14. Елки, хочу начать программировать на асме, но нигде не могу найти систему команд для AVR. Мож кто подскажет, где их можно надыбать?

  15. Цитата: Разумеется для этого надо уметь ПРАВИЛЬНО писать на Си, выделяя все аппаратно зависимые части в HAL.

    А можно с этого места поподробнее?

    Чтобы не быть голословным простой пример — есть проект с динамической индикацией, кнопками и другими обвесками периферии на контроллере. Соответственно код для каждого куска периферии вынесен в соответствующую библиотеку. Итого получается: main.c, digits.h, buttons.h — соответственно основная программа, модуль индикации и кнопок (со своими lib файлами).

    2 последних модуля имеют процедуры для работы с соответствующей периферией. Обычно те пины, к которым я подключаю кнопки и индикаторы — определяю в соответствующих константах.

    Вопрос в том — где хранить эти константы — в тех самых библиотеках (как это делается в модуле для ds18b20) или все #define тащить в модуль HAL.

    Оба этих решения содержат проблемы, т.к. в первом случае при изменении пинов МК начинается беготня по библиотекам и переименование констант. Во втором случае — приходится HAL подключать ко всем библиотекам, что очень неудобно и чревато ошибкой «symbol redefined» (#ifdef/#endif не помогают — ну почему нельзя пошагово препроцессор компилятора посмотреть — мож я косячу?). У меня однажды так одноименная глобальная переменная несколько раз определилась… одна использовалась процедурами в библиотеке, другая — в основном модуле, хотя она должна быть общей для всех.

    Надо бы статью: «Как правильно ‘заворачивать’ модули.»

    1. Дефайны тоже же разные бывают. Есть дефайны аппаратно зависимые, а есть нет. Вот все аппаратно зависимые дефайны вытаскиваются в свой HAL слой. У меня бы это было buttons_hal.h причем сама прога пишется так, чтобы гарантированно можно было перенести в любую архитектуру.

      Т.е. если проверка кнопки, то не какой, нибудь

      1
      
      if (PINPORT<<PINNUMB)...

      А более абстрактно

      1
      
      if (button_push) ...

      А у же в HAL файле расписываешь что такое button_push и что на самом деле оно значит. Получается такая матрешка из макросов.

  16. Можно глянуть тот красивый кусок кода на C++, который компилируется в нечто феерическое? Или на аналогичные примеры правильного использования C++.

  17. Самый большой прикол в том что и ассемблер и си для программирования морально устарели.
    Или большие компании крысят свое ПО для написания программ для чипов или его просто напросто не существует. Почему так? Элементарно .. . Ну во-первых ни там ни там нет классов . ( В большом Си есть, а в мелком нету). Потом нет объекности программирования . Ну и Интегрированной среды с компонентами . Неполноценное что-то есть . Да это должно быть похоже на борландское или типа того.
    И опять же это тоже уже устарело .
    Надо такой пакет чтоб можно было собирать устройство не из 1 чипа , а хотя б из 3 . и отладкой .
    А если чипы станут 2 ядерными или 16 ядерными . Ведь это промышленно уже легко . Просто очень паршивое состояние в стратегии программировании чипов .
    В общем за Объектным Паралельным Ассемблером будущее . Если конечно найдется группа реализующая эту идею . Ведь надо написать семантику языку, нарисовать оболочку и написать учебники к ней . И быть готовым к революции в радиотехнике.

    1. Зачем нужны классы, и обьекты в МК? Они только напрасно усложняют и загромождают. Современный код на ПЦ это какое то нагромождение костылей и такие кучи говна, что ни один разработчик понятия не имеет как оно там ведет себя внизу, почему оно занимает столько места, а жрет столько памяти.

      Какая нахрен среда с компонентами если все МК разные, у всех свои задрочки-заморочки. Разница на уровне архитектуры, железа. Это тебе не PC который стандартизован, работает на стандартной ОС с полной абстракцией от железа. И там бывают приколы.

      Уже есть Parallax Propeller. Но популярности он не обрел. Хотя 8 ядер, 80МГЦ, ассемблер с возможностью параллельного исполнения кода, встроенный, на уровне железа, обьектный язык. Никому не нужен. Короче, революции не будет. Всем похуй.

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

  19. Здравствуйте. Спасибо за статьи.
    Подскажите, а чем в Си принципиальным отличаются int main(void) от void main(void)?
    Смотрю параллельно видео, авторы и то, и другое в одинаковой мере используют, обозначая стартовую точку выполнения главной программы. Это взаимозаменяемые вещи?

    1. Принципиально ничем. Т.к. в МК программа никогда не выйдет из main (да и куда?). Лучше делать void main (void) тогда не будет резервироваться байт возвращаемых данных для main, но компилятор кинет варнинг, но на него можно и нужно забить.

Добавить комментарий

Ваш e-mail не будет опубликован.

Перед отправкой формы:
Human test by Not Captcha