Страница 1 из 75

Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Сб апр 12, 2014 16:38:45
Vova777
1. Как правильно называется язык Си, на котором программируются контроллеры AVR (Atmega8 в частности) через программную среду AVR Studio 4 и 5? Что это - С, С++, С# или какая-то другая разновидность языка Си?

2. Не могу понять синтаксис этого долбаного языка. Например, что значит эта запись:

Код: Выделить всё

while ((PIND& (1<<PD0))==1){}
Ну цикл "while() {}" - это мне понятно.

Я не могу понять условие цикла. Там запись: "((PIND& (1<<PD0))==1)". Судя по всему, это проверяет состояние регистра PIND (в частности бита PD0) на равенство (==) единице. Но ппц, что это за запись у них? Зачем нужен "&"? Зачем нужен "(1<<PD0)"?

Почему бы не написать по-русски: (PIND(PD0) == 1) и поставить это в условие цикла "while"? Помогите мне понять синтаксис этой строки.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Сб апр 12, 2014 17:34:19
oleg110592

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Сб апр 12, 2014 18:27:15
ARV
Vova777 писал(а):Почему бы не написать по-русски: (PIND(PD0) == 1)
потому, что это не русский язык, а язык Си...

PIND - это с точки зрения языка Си обычная переменная
чтобы проверить какой-то бит в обычной переменной, надо выполнить битовую операцию над этой переменно - язык Си других вариантов не предусматривает
& - это битовое И
в результате мы получаем либо 0, либо не ноль. в языке Си "не ноль" для логических операций всегда приравнивается к 1.
== это логическая операция проверки на равенство

все понятно?

то, что написали вы с точки зрения компилятора Си будет означать "вызвать функцию PIND с аргументом PD0 и сравнить ее результат с 1. в сущности, все верно, кроме того, что PIND не функция, а переменная, т.е. это ошибочная запись.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Сб апр 12, 2014 18:46:35
Vova777
oleg110592 писал(а):1 Си Си++
2 http://eugenemcu.ru/publ/2-1-0-53
Искренне Вам благодарен!

Синтаксис двух строк кода на языке Си.

Добавлено: Вс апр 13, 2014 10:57:49
Vova777
Я только изучаю язык Си для микроконтроллеров AVR. Учу его в интернете, сам, у меня нет ни учителей, ни советчиков. Поэтому, у меня есть вопросы по нижеследующему, мне некому их больше задавать я просто хотел бы, чтобы опытные люди посмотрели на примеры моего понимания этого языка и сказали, что я делаю правильно, а что неправильно.

Что значит запись:

Код: Выделить всё

PORTC &= ~(1 << RS);   // RS = 0
Взять число "1" (0b00000001), сдвинуть его влево на заданное кол-во бит ("RS"), инвертировать результат операции ("~"), затем провести над результатом и регистром "PORTC" операцию "побитового И" ("&"), а затем поместить результат в регистр "PORTC" ("=").

1) Т.е., если "RS=0", сдвиг числа "0b00000001" влево на "0" битов в результате даст это же число, т.е. "0b00000001".
2) В результате инверсии, получится число "0b11111110".
3) Побитовое И числа 0b11111110 и регистра PORTC (данный регистр полостью настроен на выход, состояние в данный момент "0b10000001") даст число "0b10000000" - которое и будет записано в регистр PORTC. Т.е., таким образом, я сбросил PC0.

Я все правильно интерпретировал?


- - - - - - - - - -


Что значит еще одна запись:

Код: Выделить всё

PORTC |= (1 << EN);    // EN = 1
Взять число "1" (0b00000001), сдвинуть его влево на заданное кол-во бит ("EN"), затем провести над результатом и регистром "PORTC" операцию "побитового ИЛИ" ("|"), а затем поместить результат в регистр "PORTC" ("=").

1) Т.е., если "EN=1", сдвиг числа "0b00000001" влево на "1" битов в результате даст число "0b00000010".
2) Побитовое ИЛИ числа 0b00000010 и регистра PORTC (данный регистр полостью настроен на выход, состояние в данный момент "0b10000001") даст число "0b10000011" - которое и будет записано в регистр PORTC. Т.е., таким образом я установил PC1.

Тут я тоже все правильно интерпретировал?

Re: Синтаксис двух строк кода на языке Си.

Добавлено: Вс апр 13, 2014 15:13:35
ARV
вы все интерпретировали правильно. первая запись служит для сброса в порту (переменной) бита RS, вторая для установки. в AVR-GCC, так же известном как WinAVR или AVR Toolchain, для выбора нужного бита используется макрос "Bit Value":

Код: Выделить всё

#define _BV(x) (1<<(x))
то есть ваши записи более кратко записываются так:

Код: Выделить всё

PORTC &= ~_BV(RS);
PORTC |= _BV(RS);

Re: Синтаксис двух строк кода на языке Си.

Добавлено: Вс апр 13, 2014 20:09:50
Alkul
ARV писал(а):вы все интерпретировали правильно.
Вы невнимательно прочли то, что написал тредстартер.
То, что у него "совпал" ответ - случайность.
Вы пишете совершенно верно:
ARV писал(а):первая запись служит для сброса в порту (переменной) бита RS
А автор-то пишет совсем иное! Он какими-то сдвигами занимается. Получается, что эта команда влияет на ВСЕ биты регистра, к которому применяется? Но это ведь не так!

Vova777 писал(а):Я все правильно интерпретировал?
Нет.
Не происходит в этих операциях никаких сдвигов.
Запись (1 << RS) означает, что в бит RS (который должен быть определен заранее) заносится лог.1
Эта запись имеет смысл только с командой побитового ИЛИ (ассемблерная команда ori), так как значение остальных бит при этом равно нулю, только при команде or остальные биты не исказятся.
Например, запись:

Код: Выделить всё

.equ RS=4

ori R16,(1<<RS)
означает установку (запись лог.1) именно в 4-ый бит регистра R16, на остальные биты это не оказывает совершенно никакого влияния.

Запись ~(1<<RS) означает, что бит RS обнуляется. Запись имеет смысл только с командой побитового И (ассемблерная команда andi)
Например, запись

Код: Выделить всё

.equ RS=6

andi R16,~(1<<RS)
означает обнуление шестого бита регистра R16, остальные биты при этом не меняются.

Еще раз обращаю внимание, что при записи (1 << RS) значение остальных бит, кроме четвертого (если бит RS определен как четвертый) равно нулю. Именно поэтому запись

Код: Выделить всё

ori R16,(1<<RS)
корректна, а запись

Код: Выделить всё

andii R16,(1<<RS)
приведет к сбросу всех бит, кроме бита RS

Совершенно также обстоит и с записью ~(1<<RS), при которой бит RS сброшен (равен лог.0), а остальные биты установлены (равны лог.1).

Добавлю, что эти записи можно комбинировать (покажу на примере ассемблера):

Код: Выделить всё

ori R16,(1<<RS)|(1<<EN)
Данная запись установит в регистре R16 биты RS и EN. Повторюсь, что биты RS и EN должны быть заранее определены командой Все, написанное выше, неверно. См. мое сообщение ниже.
Vova777 писал(а):Я только изучаю язык Си для микроконтроллеров AVR.
Я рекомендовал бы Вам обратить свой взгляд на ассемблер. Для 8-ми разрядных контроллеров применение Си не оправдано.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Вс апр 13, 2014 20:28:42
Flasher
Alkul, не навязывайте свое недопонимание остальным участникам.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Вс апр 13, 2014 20:41:54
zero648
Не происходит в этих операциях никаких сдвигов.
Здрасте, приехали..., а что тогда означают стрелки ">>" и "<<", если подумать логически? Это и есть сдвиг, и двигает это все препроцессор, в результате всех логических операций в выражении, согласно приоритетам, получается некое число, которое и присваивается в конечном итоге операнду.
Запись (1 << RS) означает, что в бит RS (который должен быть определен заранее) заносится лог.1
Интересно, что произойдет, если записать так (0b101<<RS)?, получается, что в бит RS Я могу запихать такое число? Как раз эта запись означает сдвинуть число 0b101 влево на RS бит.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Вс апр 13, 2014 21:19:15
Alkul
zero648 писал(а):Интересно, что произойдет, если записать так (0b101<<RS)?, получается, что в бит RS Я могу запихать такое число? Как раз эта запись означает сдвинуть число 0b101 влево на RS бит.
Согласен.
выполнение

Код: Выделить всё

ldi R16,(0b101<<2)
дает результат 0x14
Значит, Вы правы. Действительно сдвиг числа 0b101 (т.е., 0x05) влево на 2 как раз и даст результат 0x14 (0b00010100).
Согласен, был не прав.

"Век живи, век учись",- сказал поручик Ржевский. :))

P.S. Моё предыдущее сообщение ошибочно, но радикально править я его не буду, дабы не нарушать понимаемость всей ветки.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Вс апр 13, 2014 21:28:10
Flasher
Последний пункт тоже не верен.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Вс апр 13, 2014 21:35:35
Alkul
Flasher писал(а):Последний пункт тоже не верен.
Это вопрос спорный. Сможете доказать?

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Вс апр 13, 2014 22:54:24
ARV
если последнее замечание касается вот этого "пункта"
Flasher писал(а):Я рекомендовал бы Вам обратить свой взгляд на ассемблер. Для 8-ми разрядных контроллеров применение Си не оправдано.
то я могу обосновать его "спорность" :)

в частности, я давно и успешно применяю Си для AVR, причем даже для малютки attiny13 (а есть примеры применения Си даже для attiny15, в котором нет ОЗУ!), при этом задачи я решаю не самые примитивные. Си позволяет сосредоточиться на алгоритме, что помогает при решении сложных задач.

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

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт май 01, 2014 13:38:31
AIpp
На ассемблере полезно и нужно начинать программировать, чтобы понимать во что в итоге скомпилится Си-шный код. Но писать на ассемблере постоянно - это непроизводительно и только ради искусства. Поддержка и модификация такого кода требует слишком дофига времени. Есть у меня такой многолетний проект, начиналось с малого - в итоге почти полностью заняло память программ в 16-й меге (писалось при том очень аккуратно и продумано). Какие-то глобальные изменения в этом шедевре (особенно когда не прикасался полгода-год) - это стон и слёзы, ну и приличное количество времени а значит и денег заказчика. Правда, не уверен что будучи написан на Си этот проект в его нынешнем виде влез бы в 16-ю мегу. Возможно только за счёт большей степени абстракции в каких-то местах.
В итоге, когда стали попадаться проекты где стоимость (=время) разработки софта критична - перешёл на Си, чем весьма доволен. Даже для мелких процев и простых проектов (в них играет большую роль переносимость кода - когда например решал подобную задачу для AVR, а нужно написать под 51-й или ПИК - код копипастится с минимальными изменениями). Да и держать в голове весь зоопарк ассемблеров лениво.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Пт май 02, 2014 10:43:07
Jack_A
AIpp писал(а): Какие-то глобальные изменения в этом шедевре (особенно когда не прикасался полгода-год) - это стон и слёзы
Думается, дело не только в языке программирования. На Си тоже можно наворотить дикие конструкции, которые 7 мудрецов не разберут.
Структурировать прогу ( уж не 10-метровую простыню листинга без единого call ), не скупиться на комментарии ( "Ну здесь все и так понятно" - это сегодня, а завтра ? ), применять интуитвно понятные макросы - и АСМовый текст будет так же легко ( или почти так же ) читаем человеком, знающим данную архитектуру. А уж если не полениться, отмазываясь нехваткой времени, нарисовать схемы алгоритмов - то солнышко и благодать . :)

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Пт май 02, 2014 10:56:28
Леонид Иванович
Vova777 писал(а):

Код: Выделить всё

while ((PIND& (1<<PD0))==1){}
Так писать нежелательно. Пока там PD0, это работает. Но стоит заменить PD0 на PD1, как работать перестанет - в этом случае значение выражения будет равно или 0, или 2, но никогда 1. Лучше написать так:

Код: Выделить всё

while (PIND & (1 << PD0)) {}

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Пт май 02, 2014 12:40:38
AIpp
Jack_A писал(а): Думается, дело не только в языке программирования. На Си тоже можно наворотить дикие конструкции, которые 7 мудрецов не разберут.
Структурировать прогу ( уж не 10-метровую простыню листинга без единого call ), не скупиться на комментарии ( "Ну здесь все и так понятно" - это сегодня, а завтра ? ), применять интуитвно понятные макросы - и АСМовый текст будет так же легко ( или почти так же ) читаем человеком, знающим данную архитектуру. А уж если не полениться, отмазываясь нехваткой времени, нарисовать схемы алгоритмов - то солнышко и благодать . :)
Всё вышеописанное было сделано, комментарии почти в каждой строке, процедуры использованы по-полной, макросы имеют место, и папочка с блок-схемами (правда от руки) лежит в тумбочке. Просто структура и алгоритма и окружения весьма сложная. Не очень удачные архитектурные решения там тоже есть, но они связаны с тем что функциональность от исходной разраслась в несколько раз, причём изначально это не планировалось. А рефакторить асмовый код этот тоже тот ещё вынос мозга.
Допускаю, что задавшись целью можно было сделать несколько лучше, но это потребовало бы кучу времени на изобретение велосипедов, которые в Си имеются из коробки.
В общем, можно - но не выгодно.
По наблюдениям, ASM очень хорошо воспринимается теми, кто пришёл в программирование МК из электроники и мыслит больше сигналами и последовательностями, чем структурами и алгоритмами. Мне как человеку, пришедшему от настольных компов - он кажется недостаточно абстрактным, слишком мало структуры и слишком много реализации.
Естественно, что есть места, где и ассемблерные вставки нужны, есть процессоры где использование Си в лоб малоэффективно (те же мелкие ПИКи без полноценных ветвлений - хотя если знать систему команд, то становится понятным и как писать программу на Си так, чтобы она не скомпилировалась в тормозного монстра) - но в общем и целом считаю Си для коммерческих разработок, особенно крупных более эффективным инструментом. Однако ассемблер знать и понимать для разработчика под МК совершенно необходимо. Как для анализа листингов, так и для написания правильного, эффективного и предсказуемого сишного кода.
Наворотить можно на любом языке, здесь вы правы. Но вот сложность НЕ наворотить везде разная.

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Пт май 02, 2014 12:44:10
AIpp
В данном случае более наглядно:

Код: Выделить всё

while ((PIND&(1<<PD0))!=0){}

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт май 22, 2014 11:03:09
WishMasterMax
Доброго времени суток всем! Темы не нашел подходящей поэтому напишу тут, подскажите хорошую IDE и компилятор для AVRок под С, писал на cvavr, но ограничении эволюционки и зачастую непонятность ошибок заставили подумать о том на что можно пересесть другое, смотрю в сторону студии но встречал плохие отзывы о ней. Что посоветуете?

Re: Нескольно простых вопросов о программировании AVR на Си.

Добавлено: Чт май 22, 2014 11:13:11
ARV
Хорошая и бесплатная IDE - это Eclipse
Хороший и бесплатный компилятор - это WinAVR или более новая врсия Atmel AVR Toolchain (то же самое, но обновленное). Еще есть разновидности avr-gcc - которые местами превосходят и AVR Toolchain, но их надо искать в сети

Есть еще монстр Atmel Studio 6 - лично я с нею дел не имел, потому не могу советовать.