Книга по работе с WinAVR и AVR Studio / AVR_01-2010
.pdf
СПРАВОЧНЫЙ МАТЕРИАЛ
Книга по работе
с WinAVR и AVR Studio
Роман Абраш
г. Новочеркасск E-mail: arv@radioliga.com
ПРЕДИСЛОВИЕ |
бесплатно – WinAVR, а так же применению его в интеграции с бес- |
Последние годы заметен среди радиолюбителей резкий всплеск |
платной IDE фирмы Atmel – AVR Studio. Краткое описание основ |
интереса к конструкциям на микроконтроллерах (МК). Обусловле- |
языка Си, которое не может быть полноценным учебником, но дол- |
но это их чрезвычайной универсальностью и гибкостью при более |
жно послужить основой для первых шагов в программировании. |
чем демократичных ценах. Наибольшей популярностью продолжа- |
Книга так же содержит подробный справочник по функциям, входя- |
ют пользоваться 8-разрядные МК, среди которых выделяются мо- |
щим в библиотеку AVR-LIBC, являющуюся частью комплекта |
дели семейства AVR фирмы Atmel. |
WinAVR, руководство по разработке модулей на ассемблере для |
Но микроконтроллер без программы – это мертвый компонент, |
Си-программ. Достаточно подробно рассмотрен необходимый ми- |
его функциональность даже меньше, чем у обычного инвертора. |
нимум команд компилятора GCC, являющегося «сердцем» WinAVR, |
Процесс разработки программного обеспечения для микроконтрол- |
а так же описаны некоторые утилиты сторонних разработчиков. В |
лера – это наиболее сложная часть конструирования, именно это |
книге имеется ряд практических примеров программ и программ- |
вызывает наибольшие сложности у любителей. Не обладая доста- |
ных «заготовок» для решения задач, являющихся типовыми: обмен |
точными навыками в программировании, они вынуждены занимать- |
с компьютером по RS-232, организация динамической индикации, |
ся лишь копированием чужих разработок. Совпадение целей и ин- |
работа с ЖКИ и т.п. В книгу включен FAQ – ответы на часто задава- |
тересов у автора-разработчика и человека, решившего повторить |
емые вопросы, составленный на основе Интернет-форумов и дру- |
конструкцию, происходит редко, и это порождает множество воп- |
гих источников. |
росов, криков о помощи на Интернет-форумах и, порой, отталкива- |
Чего вы не найдете в этой книге? Главное: вы не найдете |
ет радиолюбителя от микроконтроллеров – дескать, легче сделать |
сведений об архитектуре и периферии микроконтроллеров AVR – |
что-то на десятке микросхем жесткой логики, чем уговорить кого- |
об этом написано множество книг и повторяться нет никакого смыс- |
то подкорректировать программу. |
ла. Так же в книге не рассмотрен ряд утилит и средств, входящих в |
Но зачем кого-то уговаривать? Перефразируя известное детс- |
комплект WinAVR – в основном, это утилиты для программирова- |
кое стихотворение: не надо ждать, не надо звать, а надо взять и… |
ния и отладки, а так же вспомогательные утилиты (binutils), работа- |
написать! Т.е. речь идет о собственноручном написании программ |
ющие в консольном режиме. Сделано это вполне осознанно: в сре- |
для микроконтроллеров. Это не так сложно, как кажется, во всяком |
де Windows более привычным и удобным является графический |
случае, под силу каждому технически грамотному человеку, овла- |
интерфейс, который для работы с WinAVR обеспечивает AVR Studio, |
девшему компьютером и электроникой, пусть даже не цифровой. |
делая тем самым ненужными консольные средства. |
Как известно, программы разрабатываются на языках програм- |
Что потребуется для того, чтобы воспользоваться инфор- |
мирования, среди которых наибольшей популярностью пользуется |
мацией из этой книги? Для работы будет необходим компьютер, |
Си. Благодаря основам, заложенным в этот язык, разработка про- |
желательно, подключенный к Интернет. Потребуется, скорее всего, |
грамм для микроконтроллеров мало отличается от разработки про- |
кое-что из аппаратуры: рекомендуется один из комплектов разра- |
грамм для обычных компьютеров. Поэтому проще всего переклю- |
ботчика, предлагаемых фирмой Atmel или другими фирмами. В край- |
читься на микроконтроллеры смогут те, кто уже умеет хоть немного |
нем случае, можно ограничиться наличием одного из микроконт- |
программировать для персонального компьютера. А все остальные |
роллеров AVR и самодельным программатором. Все необходимое |
желающие могут прочесть специальные книги, посвященные как |
для работы программное обеспечение (в том числе инсталляцион- |
самому языку Си, так и процессу алгоритмизации. Литературы на |
ные пакеты AVR Studio и WinAVR), рассматриваемые в книге при- |
этот счет достаточно, равно как и литературы об аппаратном стро- |
меры программ, а так же большое количество документации и сво- |
ении микроконтроллеров. А вот книг, которые целенаправленно рас- |
бодно распространяемых любительских библиотек и разработок |
сматривали бы аспекты «сопряжения» языка программирования и |
имеется на сайте [1]. |
микроконтроллера, явно недостаточно. Восполнить этот пробел хоть |
|
в какой-то мере – вот главная цель и задача этой книги. |
РАЗРАБОТКА ПРОГРАММ |
И при восполнении упомянутого пробела сделан упор на бес- |
Разработка программного обеспечения для микроконтроллеров |
платное программное обеспечение. Дело в том, что ценность име- |
AVR мало отличается от разработки любых иных программ, разве |
ющихся книг, рассказывающих о программных пакетах стоимос- |
что от программиста требуется чуть более глубокие знания элект- |
тью в сотни и даже тысячи долларов, очень сомнительна. Любите- |
роники – хотя бы на уровне понимания действия логических эле- |
лей, способных выложить такие суммы, найдется в нашей стране |
ментов и триггеров. Разумеется, чем лучше программист владеет |
исчезающе мало, и даже не всякие фирмы рискнут пойти на такие |
электроникой, тем более качественные программы он сможет со- |
траты. Выходит, что подобные книги косвенно стимулируют пират- |
здать. Тесная связь «софта и железа» по сути требует, чтобы про- |
ство. В то же время есть альтернативный, абсолютно бесплатный |
граммист был электронщиком или же электронщик был програм- |
софт, по качеству вполне соперничающий с коммерческими паке- |
мистом. В настоящее время обе ситуации имеют место. |
тами. Его применение абсолютно законно, и более того – часто дает |
Существует три более-менее устоявшихся подхода к разработ- |
лучшие результаты, нежели иные коммерческие. Но бесплатные |
ке микроконтроллерных устройств: |
пакеты порой грешат недостаточно качественной документацией, |
- от схемы к программе |
а то и полным ее отсутствием, тем более на русском языке. Ликви- |
- от программы к схеме |
дация этого недостатка – вторая задача данной книги. |
- смешанный. |
Кому может быть полезна эта книга? Прежде всего, тем, кто |
Деление, конечно, условное. В первом случае электронщик раз- |
занимался «компьютерным» программированием и испытывает же- |
рабатывает схему, представляя микроконтроллер неким «черным |
лание или необходимость приступить к разработке программ для |
ящиком», т.е. устройством, которое «как-то само» выполняет опре- |
микроконтроллеров, например, в связи со сменой работы. Книга |
деленные действия, формируя выходные сигналы в зависимости |
будет полезна и студентам, изучающим микроконтроллеры и ра- |
от входных. После того, как схема готова, составляется задание |
диолюбителям, желающим освоить новую для себя стезю. Полез- |
программисту, в котором указывается, на каких выводах контрол- |
ное для себя наверняка извлекут и профессионалы, желающие пе- |
лер какие сигналы должен получать или формировать. Порой на |
рейти на бесплатное программное обеспечение. Несомненно, по- |
этом этапе требуется корректировка схемы, т.к. далеко не любой |
лезной книга будет для всех, кто владеет английским языком в не- |
вывод контроллера способен выполнить нужную функцию. По за- |
достаточной мере, чтобы изучать фирменную документацию. |
данию программист пишет программу, после чего следует этап от- |
Что можно найти в этой книге? Прежде всего, практические |
ладки «в железе», т.е. в реальной схеме. После этого этапа часто |
рекомендации по установке и использованию пакета разработ- |
следуют корректировки как схемы, так и программы. В общем, про- |
ки программ для микроконтроллеров AVR, распространяемому |
цесс итеративно повторяется до достижения требуемого результата. |
5 8 |
Радиолюбитель – 01/2010 |
|
СПРАВОЧНЫЙ МАТЕРИАЛ
При втором подходе программист получает задание на разра- |
первые 32 символа1 , т.е. два идентификатора с одинаковыми пер- |
|||||||
ботку программы первым. В процессе работы он сам выбирает, |
выми 32-символами будут считаться одинаковыми, даже если в |
|||||||
какой вывод МК будет выполнять то или иное действие (для чего, |
33-ем символе они различаются. |
|||||||
несомненно, он должен знать архитектуру выбранного контролле- |
Разделитель – это символ или несколько слитно написанных |
|||||||
ра). Когда, как минимум, сделано «распределение выводов», за- |
символов, которые служат для отделения одной лексемы от дру- |
|||||||
дание на разработку схемы получает и электронщик. Теперь уже он |
гой. Об одном разделителе – пробеле – уже было сказано, однако |
|||||||
должен рисовать схему с учетом отсутствия свободы выбора выво- |
более важным является точка с запятой. Так же важными раздели- |
|||||||
дов микросхемы-микроконтроллера. После того, как программа и |
телями являются скобки2 (обязательно в паре – открывающая и зак- |
|||||||
схема готовы, следуют этапы отладки, которые не отличаются от |
рывающая). Разделителем является и пустая строка, т.е. символ |
|||||||
предыдущего варианта. |
перевода строки, а так же символ табуляции. |
|||||||
Наконец, при третьем подходе программист и электронщик – |
Существует особый вид разделителя – комментарий. В Си оп- |
|||||||
это одно и то же лицо, которое по ходу составления схемы пишет |
ределено два вида комментария: многострочный и однострочный. |
|||||||
и программу. В этом случае этот специалист, зная все нюансы |
Многострочный комментарий начинается с пары символов «/*» |
|||||||
электроники и программирования, «по ходу пьесы» подстраивает |
и завершается парой «*/». Все символы, находящиеся между этими |
|||||||
одно под другое, т.е. добивается наиболее оптимального взаи- |
парами символов, игнорируются, т.е. не воспринимаются компиля- |
|||||||
модействия всех частей. Ведь не секрет, что желания програм- |
тором. |
|
|
|
||||
миста и электронщика часто взаимопротивоположны, и поиск |
Однострочный комментарий начинается с пары символов «//» и |
|||||||
компромиссов в первых двух рассмотренных вариантах чреват |
продолжается до конца текущей строки, т.е. все символы, следую- |
|||||||
лишними препираниями, в то время как третий подход все тре- |
щие за этой парой до конца строки, игнорируются компилятором. |
|||||||
ния исключает. |
Программа на языке Си представляет собой последователь- |
|||||||
Так как настоящая книга посвящена программным средствам, |
ность лексем и разделителей, записанных в текстовом файле. Если |
|||||||
дальнейшее изложение будет вестись, как будто имеет место вто- |
отдельную законченную мысль человек при письме завершает точ- |
|||||||
рой вариант, т.е. от программы к схеме – так, не обращая излишне- |
кой, то в языке Си каждая законченная мысль (т.е. последователь- |
|||||||
го внимания на схемотехнику, проще разобраться в процессе про- |
ность лексем, имеющая самостоятельное смысловое значение) за- |
|||||||
граммирования. При этом неизбежные обращения взгляда на схе- |
вершается особым разделителем – точкой с запятой. Хотя нет ни- |
|||||||
мотехнику будут происходить в предположении, что читатель обла- |
каких ограничений на способ записи программы, все же следует по |
|||||||
дает необходимыми знаниями и навыками в области электроники, |
мере возможности выделять каждую осмысленную запись програм- |
|||||||
т.е. он – электронщик, желающий стать программистом. |
мы, начиная ее с новой строки. Кроме этого есть и другие рекомен- |
|||||||
|
|
|
дации – см. «О стиле программирования». |
|||||
Основы Си |
|
|
|
|
|
|||
Эта глава посвящается введению в язык Си. Это не учебник, |
Служебные слова |
|
||||||
скорее – это упрощенный краткий справочник с пояснениями и при- |
Ключевое или служебное слово – это идентификатор, зарезер- |
|||||||
мерами. К сожалению, последовательность изложения может по- |
вированный для особого использования. В Си стандартно опреде- |
|||||||
казаться нелогичной: это объясняется тем, что невозможно совме- |
лены следующие служебные слова3 : |
|||||||
стить краткость и простоту с логичностью и последовательностью |
break |
enum |
long |
struct |
||||
при рассмотрении такой сложной системы, как язык программиро- |
case |
extern |
public |
switch |
||||
вания. Поэтому часть упоминаемых терминов получает объясне- |
char |
float |
register |
typedef |
||||
ние в последующем тексте, иногда даже в другом разделе. |
const |
for |
return |
union |
||||
|
|
|
continue |
goto |
short |
unsigned |
||
Общие сведения |
do |
if |
signed |
void |
||||
Назначение языка программирования – предоставить програм- |
double |
inline |
sizeof |
volatile |
||||
мисту средства для изложения алгоритма решения какой-либо за- |
else |
int |
static |
while |
||||
дачи в форме, воспринимаемой компилятором (специальной про- |
В сущности, этих служебных слов достаточно, чтобы реализо- |
|||||||
граммой, служащей для «перевода» с одного языка на другой, по- |
вать любую программу. Часть из этих слов являются операторами |
|||||||
нятный конкретной аппаратной платформе, т.е. процессору или мик- |
(см. далее), часть используется в составе других конструкций, часть |
|||||||
роконтроллеру). |
соответствует обозначению стандартных типов. Далее все служеб- |
|||||||
Основу любого языка составляет алфавит, т.е. определенный |
ные слова будут рассмотрены в соответствующем контексте по |
|||||||
набор допустимых символов, из которых затем составляются лек- |
назначению. |
|
|
|
||||
семы, т.е. элементы языка, уже означающие конкретные понятия. |
|
|
|
|
|
|||
Любой язык программирования – это «письменный» язык, т.е. |
Типы данных |
|
|
|||||
он существует в виде символов текста. Запись средствами языка |
Любой алгоритм, так или иначе, сводится к неким действиям |
|||||||
алгоритма в файле называется исходным текстом программы (или |
над данными, будь то числа, буквы, звуки, сигналы и т.п. Так как |
|||||||
просто программой). |
язык программирования служит для реализации алгоритма, он имеет |
|||||||
Алфавит языка Си составляют: |
все необходимые средства для манипулирования данными. Для раз- |
|||||||
1. Буквы латинского алфавита |
деления их по видам, введено понятие тип данных. Так как тип не |
|||||||
2. Цифры от 0 до 9 |
может существовать без данных, а данными в языке Си может быть |
|||||||
3. Специальные знаки: |
очень много совершенно разных объектов, далее будем использо- |
|||||||
|
|
|
вать термин объект для обозначения абстрактных данных. |
|||||
“ { } , | [ ] ( ) + - / % \ ; ‘ : ? < = > _ ! & # ~ ^ . * |
|
|||||||
|
Тип – это идентификатор, обозначающий принадлежность |
|||||||
Пробел не является языковым элементом, он служит лишь для |
объекта к некой категории, однозначно определяющей содержи- |
|||||||
разделения отдельных лексем. |
мое и набор действий, которые можно выполнить над ним. Напри- |
|||||||
Из элементов алфавита составляются лексемы: |
мер, все числа можно разделить на ряд категорий – целые, дей- |
|||||||
• |
Идентификаторы, называемые |
ствительные, комплексные, отрицательные и т.п. |
||||||
|
иногда символами |
Таккакработапроцессораимикроконтроллераестьпроцессциф- |
||||||
• Зарезервированные (ключевые) служебные слова |
ровой обработки данных, поэтому так или иначе все разнообразие |
|||||||
• |
Знаки операций |
данных сводится к числам. Даже буквы есть не что иное, как числа, |
||||||
• |
Разделители |
|
|
|
|
|
||
1 Значение может отличаться в зависимости от стандарта, которому соответствует |
||||||||
Идентификатор – это последовательность из символов ла- |
||||||||
компилятор. |
|
|
|
|||||
тинского алфавита, десятичных цифр и символов подчеркива- |
|
|
|
|||||
|
2 Разделителями считаются любые скобки – круглые, фигурные и квадратные, одна- |
|||||||
ния, начинающаяся не с цифры. Прописные и строчные символы |
ко не всегда и не все из них могут использоваться произвольно – существует ряд ограни- |
|||||||
различаются, т.е. Run и RUN – разные идентификаторы. Длина иден- |
чений, которые будут упомянуты по мере изложения основ языка. |
|||||||
|
3 Список служебных слов может несколько отличаться в зависимости от конкретного |
|||||||
тификатора принципиально не ограничена, но анализируются только |
компилятора (как правило в сторону расширения). |
|||||||
|
|
|
5 9 |
Радиолюбитель – 01/2010 |
|
|
|
|
|
|
СПРАВОЧНЫЙ МАТЕРИАЛ
сопоставленные им (грубо говоря, это номер буквы по порядку в |
восьмеричной и шестнадцатеричной. Система счисления опреде- |
||||||
алфавите). По этим причинам в языке Си основным видом данных |
ляется компилятором следующим образом: если лексема, опреде- |
||||||
являются числа, которые для удобства разделены на ряд стандарт- |
ленная как константа, начинается с символов «0b» – принимается, |
||||||
ных типов4 : |
что это запись числа в двоичной системе; если лексема начинается |
||||||
char – символ, то есть число, занимающее один байт (т.е. |
с символов «0x» – принимается шестнадцатеричное представле- |
||||||
8-битное число) |
ние числа. Восьмеричная система подразумевает, что число все- |
||||||
int – целое число, занимающее 2 байта (т.е. 16-битное число) |
гда начинается с нуля. Если же ни один из рассмотренных призна- |
||||||
long – длинное целое число, занимающее 4 байта (т.е. 32-бит- |
ков не обнаружен – принимается десятичная система. |
||||||
ное число) |
|
Вот пример записи константы (числа 307) в разных системах |
|||||
long long – двойное длинное целое число, занимающее 8 байт |
счисления: |
|
|
||||
(т.е. 64-битное число) |
|
307 – десятичная запись |
|
||||
float – действительное число, т.е. число с плавающей точкой |
|
0b100110011 – двоичная запись |
|||||
double – действительное число удвоенной точности |
|
0463 – восьмеричная запись |
|
||||
При помощи дополнительных служебных слов определяются |
|
0x133 – шестнадцатеричная запись. |
|||||
разновидности типов целых чисел: |
|
По значению константы компилятор определяет наименьший |
|||||
signed – обозначает, что целое число имеет знак (т.е. может |
подходящий для нее тип данных. Однако часто необходимо зада- |
||||||
принимать и отрицательные значения) |
вать константы так, чтобы они заранее соответствовали конкрет- |
||||||
unsigned – обозначает, что целое число не имеет знака, т.е. |
ному типу, например, нужно определить константу long равную 2. |
||||||
может быть только нулем или более |
Если просто написать 2, то компилятор посчитает, что для констан- |
||||||
short – обозначает, что фактический размер целого числа вдвое |
ты достаточно типа char, и будет его и использовать (далее будет |
||||||
меньше |
показано, к чему это может привести). Чтобы принудительно ука- |
||||||
Таким образом, получаются следующие типы: |
зать размер константы, используются специальные суффиксы, при- |
||||||
unsigned char – число от 0 до 255 |
писываемые к константе справа: |
|
|||||
signed char – число от -127 до 127 |
|
L – для обозначения long (можно и прописную букву «l» исполь- |
|||||
unsigned int – число от 0 до 65535 |
зовать) |
|
|
||||
signed int – число от -32767 до 32764 |
|
U – для обозначения unsigned (можно и прописную букву «u» |
|||||
unsigned long – число от 0 до 4294967295 |
использовать). |
|
|
||||
signed long – число от -2147483648 до 2147483648 |
|
Суффиксы могут использоваться по отдельности или вместе в |
|||||
и т.д. |
любых комбинациях. Таким образом, ранее упомянутая константа |
||||||
Следует отметить, что слово signed, как правило, нет смысла |
должна быть записана в виде 2L или 2ul. |
||||||
использовать, так как по умолчанию все типы целых чисел имеют |
|
Константы действительного типа определяются компилятором |
|||||
знак. |
по наличию точки в записи лексемы или по наличию символа «e» |
||||||
Примечание: тип char стоит особняком – многие версии стан- |
(или «E»), отделяющего мантиссу7 от показателя степени числа 10. |
||||||
дарта Си допускают, что этот тип по умолчанию не имеет знака, что |
Вот пример констант этого типа: |
|
|||||
является причиной многих ошибок. Обычно имеется возможность |
66.2 .1 0. |
2.14e-7 |
|
||||
управлять компилятором, переключая тип char со знакового на без- |
|
Количество байтов, выделенное компилятором для хранения |
|||||
знаковое по умолчанию. Но, чтобы никогда не зависеть от особен- |
константы, в этом случае определяется формой представления |
||||||
ностей компилятора, рекомендуется всегда явно указывать signed |
чисел с плавающей точкой, т.е. может быть разным для разных ком- |
||||||
или unsigned при использовании типа char. |
пиляторов. При помощи служебного слова sizeof можно получить |
||||||
Так же ключевое слово short используется достаточно редко5 в |
константу, равную количеству байтов для хранения константы: |
||||||
программировании для микроконтроллеров. |
|
sizeof(3) будет равно 1 (1 байт); |
|||||
Программист имеет возможность определять новые типы на |
|
sizeof(3L) будет равно 4 (4 байта), |
|||||
основе уже определенных, для этого служит ключевое слово typedef, |
|
и т.д. |
|
|
|||
например: |
|
Символьная константа – это разновидность целочисленной |
|||||
typedef unsigned char byte – определение нового типа byte |
константы, служащей для определения кода алфавитно-цифрово- |
||||||
для обозначения однобайтного числа без знака. То есть сначала |
го символа. Для обозначения такой константы используется запись |
||||||
следует ключевое слово typedef, затем указывается уже опреде- |
символа, окруженного апострофами: |
||||||
ленный тип, а завершает все идентификатор нового типа. |
|
′F′ ′5′ ′.′ |
|
|
|||
После такого определения программист может использовать |
|
Очевидно, что далеко не любой символ можно ввести таким |
|||||
byte наравне с другими типами, в том числе и для нового определе- |
образом. Снять проблему позволяет особый символ «обратная чер- |
||||||
ния типа. |
та» (или back-slash): этот символ (называется escape-символ) по- |
||||||
Все рассмотренные типы считаются простыми типами. Кроме |
зволяет ввести неотображаемые символы, символы «апостроф», |
||||||
них, имеются и сложные, например, массивы (см. далее), структу- |
«кавычки», «вопрос» и «обратная черта», а так же любой другой |
||||||
ры и объединения (см. далее) – они рассмотрены отдельно. Однако |
символ, указав его код. |
|
|||||
все сказанное относится и к ним, т.е. любой сложный тип может |
|
Определение символа при помощи escape называется escape- |
|||||
использоваться для определения нового типа пользователя. |
последовательностью8 : |
|
|||||
|
|
|
|
|
|
||
Константы |
Escape-последовательность Код символа |
Наименование символа |
|||||
\a |
0x07 |
Звуковой сигнал |
|||||
Константа – это лексема языка, представляющая какое-либо |
\b |
0x08 |
«Забой» (возврат на символ) |
||||
фиксированное числовое или иное значение. |
\f |
0x0c |
Перевод страницы |
||||
\n |
0x0a |
Перевод строки |
|||||
Константы делятся на несколько групп: целочисленные, действи- |
|||||||
\r |
0x0d |
Возврат каретки |
|||||
тельные, символьные и строковые. В зависимости от значения кон- |
\t |
0x09 |
Горизонтальная табуляция |
||||
станты, компилятор относит ее к одному из известных типов дан- |
\v |
0x0b |
Вертикальная табуляция |
||||
\\ |
|
0x5c |
Обратная черта |
||||
ных, выделяя для нее соответствующее количество байтов памяти. |
|
||||||
\′ |
0x27 |
Апостроф |
|||||
Целочисленные константы представляют собой запись чисел |
\” |
0x22 |
Кавычки |
||||
в одной из допустимых систем счисления: десятичной, двоичной6 , |
\? |
|
0x3f |
Знак вопроса |
|||
\000 |
000 |
Любой восьмеричный код символа |
|||||
|
|
|
|||||
|
|
|
\0x00 |
0x00 |
Любой шестнадцатеричный код символа |
||
4 Приведены типы, являющиеся стандартными в версии Си для микроконтроллеров |
|||||||
|
|
|
|
||||
AVR |
|
|
|
|
|||
|
|
|
|
||||
5 Ключевое слово short имеет важную роль в системах, для которых тип int не являет- |
|
7 Подразумевается, что читатель знаком с показательной формой записи действи- |
|||||
ся 16-битным числом (например, для PC-компьютеров). В этом случае тип char соответ- |
етльных чисел. |
|
|
||||
ственно может быть 16-битным, и тогда для получения однобайтного типа необходимо |
|
8 Escape-последовательности ведут свое начало с тех времен, когда работа велась |
|||||
использование short char. |
через консольные текстовые терминалы – эти последовательности управляли положени- |
||||||
6 Двоичные константы определены для GNU-расширений Си. |
ем «курсора» на терминале или печатающем устройстве. |
||||||
6 0 |
Радиолюбитель – 01/2010 |
|
СПРАВОЧНЫЙ МАТЕРИАЛ
При вводе символов по их кодам в escape-последовательнос- |
unsigned long var; |
||||
ти следует помнить, что код не может быть больше 255 (в десятич- |
int a, b, c; |
||||
ном представлении). |
|
|
char ch; |
||
Наконец, строковая константа – это последовательность сим- |
Пример демонстрирует определение переменной var, имеющей |
||||
волов, заключенная в кавычки. Среди символов строковой констан- |
|||||
ты могут быть и escape-последовательности. Если введены под- |
тип «беззнаковое длинное целое», трех переменных a, b и с типа |
||||
ряд несколько строковых констант, разделенных лишь пробелами, |
«целое число со знаком» и одну переменную ch типа «символ». |
||||
табуляциями, переводами строки или комментариями – они объе- |
Встретив определение переменных, компилятор резервирует |
||||
диняются в одну строковую константу. Длинные строки можно пе- |
необходимое количество ячеек памяти, которые затем будут исполь- |
||||
реносить со строки на строку при помощи символа переноса – той |
зованы в программе по усмотрению программиста. Использование |
||||
же самой «обратной черты». |
|
|
неописанных переменных в программе не допускается. По умолча- |
||
Есть несколько особенностей слияния и переноса строк, свя- |
нию каждой из описанных переменных сразу присваивается нуле- |
||||
занных с обработкой пробелов: |
вое значение – говорят «переменная проинициализирована значе- |
||||
1. Если происходит слияние строк – результирующая строка |
нием по умолчанию» (инициализация по умолчанию характерна не |
||||
будет содержать последовательно все символы обеих строк (это |
для всех переменных, о чем будет сказано далее). Далее будет по- |
||||
очевидно). |
|
|
казано, как можно инициализировать переменные другими значе- |
||
2. Если строка переносится при помощи символа переноса, |
ниями. |
||||
то в результирующую строку будет включены все пробелы от пос- |
Программист должен знать, что память для хранения перемен- |
||||
леднего символа до символа переноса и все пробелы от начала |
ных выделяется в порядке их описания, т.е. для вышеприведенного |
||||
следующей строки до константы. |
примера в ОЗУ сразу после 4-го байта переменной var будут сле- |
||||
Вот примеры, поясняющие сказанное: |
довать 2 байта переменной a и т.д. Порядок байтов, составляющих |
||||
|
|
|
|
переменную, определяется платформой, для которой компилиру- |
|
“простая строковая константа” |
|
|
|||
”слияние строк ” |
”123” |
|
ется программа. Для микроконтроллеров AVR принято, что много- |
||
”перенос строки |
\ |
|
байтные переменные хранятся в памяти «от младшего байта к стар- |
||
123” |
|
|
шему», т.е. первым размещается младший байт (наименее знача- |
||
”еще один вариант\ |
переноса строки” |
|
щие биты числа), а затем все более старшие, вплоть до последнего |
||
”вариант\ |
|
||||
|
|
(наиболее значащие биты числа). |
|||
переноса” |
|
|
При описании переменных могут дополнительно использовать- |
||
Компилятор преобразует эти константы в следующие: |
ся ключевые слова static, register, extern и volatile. Эти слова мо- |
||||
|
|
|
|
гут располагаться как до определения типа переменной, так и пос- |
|
“простая строковая константа” |
|
|
|||
|
|
ле него, однако обязательно до указания идентификатора. Если |
|||
”слияние строк 123” |
123” |
|
|||
”перенос строки |
|
переменная объявлена с использованием слова register, это озна- |
|||
”еще один вариант |
переноса строки” |
|
чает, что компилятор поместит ее в один из доступных регистров |
||
”вариантпереноса” |
|
|
микроконтроллера. Не стоит надеяться, что регистровые перемен- |
||
Важной особенностью строковых констант заключается в том, |
ные каким-то образом помогут создать более быстродействующую |
||||
что компилятор всегда добавляет к явно введенным программис- |
программу: для большинства случаев результат будет скорее об- |
||||
том символам еще один – символ завершения строки, код которого |
ратный, хотя в некоторых случаях положительный эффект может |
||||
0х00 (так называемый null-символ или завершающий ноль). Этот |
быть. |
||||
символ никак не виден в тексте программы, но обрабатывается |
Ключевое слово volatile – очень важное. Дословно оно озна- |
||||
компилятором и программой. |
чает «изменяемая», что на первый взгляд излишне для перемен- |
||||
|
|
|
|
ной, само наименование которой означает изменение значения. |
|
Переменные |
|
|
Однако, дело тут в другом. Компилятор в процессе своей работы |
||
В процессе работы любая программа не только использует кон- |
анализирует написанный программистом текст программы и ста- |
||||
станты, т.е. фиксированные значения, но и получает, изменяет и |
рается убрать из него те части, которые явно не несут никакого |
||||
выводит данные различных типов, т.е. оперирует изменяющимися |
смысла (подробнее об этом см. в главе «Об оптимизаторе про- |
||||
числами (как было сказано ранее, все данные, в конце концов, есть |
грамм»). В частности, компилятор может исключить все участки |
||||
числа). |
|
|
программы, которые обрабатывают переменные, не изменяющие |
||
Изменяемые величины хранятся в ОЗУ, каждое отдельное чис- |
(с точки зрения компилятора) значения. Разумеется, далеко не |
||||
ло в отдельных ячейках. Для обозначения таких ячеек введена осо- |
всегда это соответствует замыслам программиста. Ключевое |
||||
бая лексема – переменная. |
|
|
слово volatile, использованное при объявлении переменной, |
||
Переменная – это идентификатор, обозначающий строго оп- |
укажет компилятору, что эта переменная все-таки изменяется, |
||||
ределенную область памяти, содержащую данные конкретного типа. |
пусть даже и неизвестным компилятору способом. Можно счи- |
||||
Для определения любых переменных не допускается использовать |
тать, что volatile есть синоним слова «неприкосновенный», т.е. |
||||
идентификаторы, совпадающие с ключевыми словами языка или |
объявленную таким образом переменную нельзя трогать при |
||||
уже определенными ранее (например, введенных программистом |
оптимизации. |
||||
типов). |
|
|
Назначение остальных ключевых слов будет рассмотрено |
||
Из определения переменной следует ее неразрывная связь с |
далее. |
||||
одним из определенных типов, т.е. переменные могут быть типа |
|
||||
char, int, float и т.д. В программе каждая переменная должна быть |
Массивы |
||||
обязательно определена, т.е. описана. Описание переменной осу- |
Массив – это последовательно хранимый набор нескольких |
||||
ществляется по следующему шаблону9 : |
«пронумерованных» переменных одинакового типа, называемых |
||||
<тип> <список идентификаторов>; |
элементами массива. |
||||
Здесь тип – это один из ранее определенных типов, а список |
Для определения массива используется следующий шаблон: |
||||
идентификаторов – это один или более идентификаторов, разде- |
<тип> <идентификатор>[<размер>]; |
||||
ленных запятыми. Завершать определение должна традиционная |
Здесь тип – как и ранее, любой из определенных типов, обо- |
||||
точка с запятой. Запятая – это особый разделитель, используе- |
значающий тип каждого элемента массива, идентификатор – это |
||||
мый для разделения элементов списка, т.е. таких элементов, ко- |
собственно имя переменной-массива, а размер (который может и |
||||
торые должны восприниматься компилятором как некая недели- |
отсутствовать) – это константа, ограничивающая количество эле- |
||||
мая группа. |
|
|
ментов массива. |
||
|
|
|
|
Обратите внимание на то, что квадратные скобки должны при- |
|
|
9 Здесь и далее, если иное не оговорено, используется традиционный формат опи- |
||||
|
сутствовать всегда, независимо от того, задается ли размер или |
||||
сания шаблонов выражений: в угловых скобках указываются обязательные элементы, в |
|||||
нет – это признак массива. |
|||||
квадратных – опциональные, все прочие символы вне скобок являются обязательными. |
|||||
|
|
|
6 1 |
Радиолюбитель – 01/2010 |
|
|
|
|
|
|
СПРАВОЧНЫЙ МАТЕРИАЛ
Из определения массива следует, что, во-первых, все элемен- |
обрабатывая список сотрудников, удобно объединить в одну груп- |
|||||
ты массива находятся в памяти друг за другом, а во-вторых, имеют |
пу фамилию, имя и отчество сотрудника, и хранить такие группы в |
|||||
одинаковый тип. Чем же это отличается от обычного последова- |
массиве. Это, с одной стороны, позволило бы при подсчете обще- |
|||||
тельного определения нескольких однотипных переменных? |
го количества сотрудников просто считать такие группы, но с дру- |
|||||
|
|
|
|
гой стороны, в любой момент можно получить имя любого из со- |
||
int a[5]; |
// массив a[] из 5-и элементов типа int |
|
||||
|
трудников по его номеру. Для подобной группировки введено по- |
|||||
int a1, a2, a3, a4, a5; // 5 отдельных переменных типа int |
|
нятие структуры. |
||||
Отличие принципиальное. Определенные во второй строке пе- |
Структура – это особая форма слияния нескольких перемен- |
|||||
ременные независимы друг от друга, для обращения к каждой из |
ных, называемых полями структуры, в единое целое. |
|||||
них программист обязан использовать уникальный идентификатор. |
Для определения структуры используется ключевое слово struct. |
|||||
У массива же идентификатор единственный, а для обращения к |
Шаблон определения структуры следующий: |
|||||
его элементам используется индекс, т.е. номер элемента: a[0] – |
struct {<поле 1>; <поле 2>; … ; <поле N>;}; |
|||||
первый элемент массива, a[4] – пятый элемент. Обратите внима- |
Здесь в фигурных скобках перечисляются поля структуры, ко- |
|||||
ние, что нумерация элементов массива начинается с нуля. Преиму- |
торые есть ничто иное, как объявления переменных. Обратите вни- |
|||||
щество массивов перед отдельными переменными бросается в глаза |
мание, на точки с запятой, завершающие определение каждого поля |
|||||
на простом примере. Если представить себе строку символов в виде |
структуры. Структура – это разновидность типа, поэтому опреде- |
|||||
массива и в виде нескольких отдельных символьных переменных, |
ление переменной типа структура осуществляется аналогично ра- |
|||||
сразу становится ясно, что работа со строкой уже из десятка сим- |
нее рассмотренному объявлению простых переменных: |
|||||
волов становится неразумно сложной, в то время как каждый их |
|
|
||||
struct {int a; long b; char c;} st; |
||||||
элементов массива-строки может быть обработан одним и тем же |
||||||
способом. |
|
|
Этот пример показывает, как объявляется переменная st типа |
|||
В качестве указателя размера массива при описании может |
структура с полями а (типа int), b (типа long) и с (типа char). Обра- |
|||||
использоваться любая целочисленная константа, а при обраще- |
щение к переменным-полям структуры осуществляется через так |
|||||
нии – константа или переменная соответствующего типа. В Си |
называемую точечную нотацию, когда поле структуры отделяется |
|||||
никак не контролируется допустимость индекса при обращении к |
от ее идентификатора точкой: st.a позволит обратиться к полю, а |
|||||
элементу массива, т.е. обращение к a[12] будет воспринято ком- |
переменной st, а st.c – к полю ее полю с. |
|||||
пилятором, как безошибочное, однако результат в этом случае не |
Ничто не препятствует объявить массив таких структур: |
|||||
предсказуем. |
|
|
|
|
||
|
|
struct {int a; long b; char c;} st[5]; |
||||
Рассмотренный пример массива – одномерный, т.е. его мож- |
||||||
но представить в виде «линейки» с делениями – элементами. Од- |
Этот пример определяет массив st, состоящий из 5-и элемен- |
|||||
нако нередко требуется оперировать массивами-«плоскостями», |
тов, каждый из которых имеет поля a, b и с соответствующих типов. |
|||||
«кубами» и более многомерными10 «фигурами». Такая возмож- |
Точечная нотация продолжает действовать и при обращении к эле- |
|||||
ность предусмотрена в Си: многомерный массив описывается так |
ментам массива структур: st[1].a – поле a второго элемента масси- |
|||||
же, как и одномерный, только количество квадратных скобок (с |
ва, st[4].c – поле с последнего элемента. |
|||||
возможно указанным размером «измерения») соответствует чис- |
Так же ничто не препятствует определить структуру как тип, и |
|||||
лу измерений: |
|
|
использовать для определения новых переменных уже этот тип: |
|||
|
|
|
|
|
|
|
int a1[5]; |
// 1-мерный массив из элементов int |
|
|
|
||
|
typedef struct { int a; long b; char c;} strc; |
|||||
int a2[][]; |
// 2-мерный массив элементов int |
|
strc st; |
|||
|
|
// с неопределенными размерами |
|
strc arr_st[5]; |
||
int a3[3][3][3]; |
// 3-мерный массив элементов int |
|
Язык Си считается самым низкоуровневым языком среди вы- |
|||
|
|
// с определенными размерами |
|
сокоуровневых. Под этим следует понимать, что язык позволяет |
||
Подобные записи «читаются» слева направо, например, третья |
получить возможность практически так же манипулировать данны- |
|||||
строка примера читается так: массив из трех элементов, каждый из |
ми, как и ассемблер. Одной из таких «низкоуровневых» возможно- |
|||||
которых представляет собой массив из трех элементов, элемента- |
стей являются объединения. |
|||||
ми которого являются массивы из трех элементов типа int. «Трех- |
По виду описания объединение (определяемое ключевым сло- |
|||||
мерный массив» звучит куда проще, но это неудобное описание |
вом union) очень похоже на структуру: |
|||||
помогает понять, как именно следует обращаться к многомерному |
|
|
||||
union { int a; long b; char c;} uni; |
||||||
массиву: |
|
|
||||
|
|
|
|
Однако, принципиальное отличие от структуры в том, что все |
||
a3[0] – это массив двумерный |
|
|||||
|
поля объединения физически соответствуют одной и той же |
|||||
a3[0][0] – это массив одномерный |
|
|||||
|
области памяти! Размер области памяти, выделяемой компилято- |
|||||
a3[0][0][0]– это элемент массива (не массив!) типа int |
|
ром, определяется так, чтобы поместилось поле наибольшего раз- |
||||
Кстати, фактически многомерные массивы – это лишь форма |
мера, т.е. для вышеприведенного примера будет выделено 4 байта |
|||||
сокращенной (и, возможно, более удобной) записи одномерного мас- |
для переменной uni. При этом при обращении к uni.b будет задей- |
|||||
сива, размер которого определяется произведением размеров по |
ствована вся эта область, при обращении к uni.a - только первые 2 |
|||||
его «измерениям». Т.е. рассмотренный массив a3 можно предста- |
байта этой области, а uni.c позволит оперировать лишь первым |
|||||
вить в виде одномерного массива с размером 27 элементов. Имен- |
байтом. То есть налицо обращение к одной и той области памяти, |
|||||
но как одномерный и хранится в памяти многомерный массив, при- |
как к переменным разного типа. |
|||||
чем «развертка измерений» происходит по измерениям справа на- |
Объединение, так же как и структура, может использоваться в |
|||||
лево, т.е. самым первым в памяти будет элемент a3[0][0][0], затем |
описании нового типа, быть элементом массива и полем структу- |
|||||
a3[0][0][1], затем a3[0][0][2], затем a3[0][1][0] и т.д. |
ры. Действует правило: все, что уже определено, может быть ис- |
|||||
Как и любые переменные, массивы в момент описания инициа- |
пользовано. Разумеется, все равнее сказанное в отношении пере- |
|||||
лизируются значением по умолчанию. Кроме того, как и для любой |
менных, применимо и к структурам и объединениям. |
|||||
переменной, для объявления массива возможно использование |
|
|
||||
ключевых слов extern, static и volatile. |
Литература, Интернет-ссылки |
|||||
|
|
|
|
1. http://www.arv.radioliga.com/ |
||
Структуры и объединения |
|
|
||||
Часто требуется объединить несколько переменных или ти- |
|
|
||||
пов данных (одинаковых или разных) в некую группу. Например, |
|
|
||||
|
|
|
|
|
||
10 Вспоминается шутка математиков: «представьте себе проекцию семимерного куба |
|
|
||||
|
Продолжение в №2/2010 |
|||||
на пятимерную плоскость»… |
|
|
|
|||
|
|
|
|
|||
6 2 |
Радиолюбитель – 01/2010 |
|
