Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
388
Добавлен:
23.03.2016
Размер:
322.48 Кб
Скачать

СПРАВОЧНЫЙ МАТЕРИАЛ

Книга по работе

с 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

 

Соседние файлы в папке Книга по работе с WinAVR и AVR Studio