» » Програмирование в AVR Studio 5 с самого начала. Часть 5

 
 
 

Програмирование в AVR Studio 5 с самого начала. Часть 5

Разместил galrad 24 декабря 2011. Просмотров: 15244

8
Програмирование в AVR Studio 5 с самого начала. Часть 5

Для того чтобы писать более сложные программы, нужно хорошо представлять структуру и взаимодействие разных узлов микроконтроллера между собой, но основные принципы сохраняются независимо от модели контроллера. В принципе человек, который изучил микроконтроллеры PIC, достаточно быстро осваивает AVR или ARM.
Управление микроконтроллером осуществляется изменением логического уровня ячеек (битов) в регистрах, расположенных в оперативной памяти. Конкретному устройству соответствует конкретный регистр, как правило 8-битный (1 байтный), состоящий из 8 ячеек памяти. В любую ячейку можно записать 0 или 1.
Создадим произвольную таблицу, где каждая строка состоит из 8 ячеек и имеет свой порядковый номер, соответствующий одному регистру. Пусть наша таблица состоит из 128 ячеек или из 16 восьмибитных регистров.
Програмирование в AVR Studio 5 с самого начала. Часть 5

В микроконтроллере есть разные функциональные устройства – это порты, таймеры, АЦП, устройства ШИМ, устройства последовательного приема и передачи данных, и много еще чего. Кроме этого функции конкретного устройства могут меняться, например, сначала принять информацию, а затем переключиться на передачу. Как же они работают? Все проще, чем кажется! Функции определенного устройства жестко привязывается к конкретным ячейкам памяти. Например, если нам нужно на какую-то ножку подать напряжение, мы устанавливаем конкретную ячейку в 1.

Пусть, к примеру, за вывод положительного напряжения на 4 ножку отвечает ячейка 9h:3h. Значит, если мы пропишем в ячейку 9h:3h единицу, то на 4- ой ножке получим положительное напряжение. А как мы узнаем, что эта ячейка отвечает за эту функцию? Ячеек много и запомнить номер каждой ячейки очень сложно.

Чтобы было легко работать, производители присвоили каждой строке с определенным порядковым номером, называемым адресом, свое имя, соответствующее устройству. Пусть у нас строка 9h, будет называться регистром PortB, строка 8h регистром PinB, а строка 7h регистром DdrB. Таким образом 7h, 8h, 9h – это адреса регистров с названиями PortB, PinB, DdrB.
Соответствующие регистры указываются в специальном файле с расширением .inc, в самом начале программы. Этот файл становится доступным с помощью директивы .include
Например для attiny2313:
.include "at2313def.inc"


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

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

.CSEGSIZE – размер памяти программ
Устройства AT94K имеют раздел памяти, которую пользователь может присоединить к памяти программ AVR или памяти данных. Программа и данные SRAM подразделены на три блока: 10K x 16 память программ, 4K x 8 память данных и 6K x 16 или 12K x 8 перестраиваемой SRAM, которые могут быть распределены между программной памятью (до 4-х разделов по 2K x 16) и памятью данных (до 8-ми разделов по 4Kx8).
Эта директива используется, чтобы определять размер программного блока памяти.
Синтаксис:
.CSEGSIZE = 10 | 12 | 14 | 16

Пример:
.CSEGSIZE = 12      ; Определить размер памяти программ как 12K x 16. 


.DD – определяет двойное слово(а) в памяти программ и EEPROM.
.DQ – определяет четверное слово(а) в памяти программ и EEPROM.
Эти директивы подобно директиве .DW определяют нужное количест-во слов 32-битных (двойные слова) и 64-битных (четверные слова) соот-ветственно.

Синтаксис:
МЕТКА: .DD список  выражений
МЕТКА: .DQ список  выражений

Пример:
.CSEG 
varlist:  .DD 0, 0xfadebabe, -2147483648,  1 << 30
.ESEG
eevarlst: .DQ 0,0xfadebabedeadbeef, 1 << 62


#define – определить макрос препроцессора
Синтаксис:
1) #define имя [value]
2) #define имя(arg.,...) [value]

Описание:
Определяет макрос препроцессора. Есть две формы макроса: (1) – объект, который в основном определяет константу, и (2) – функция, в которую делают подстановку параметра.
Value – величина (значение) может быть любой строкой, она не определена, пока макрос не будет распакован (расширен). Если величина не определена, она = 1.
Форма (1) макроса может быть определена из командной строки использованием опции -D.
Когда использована форма (2), макрос должен вызываться с тем же количеством аргументов, с которыми он определен. Любые arg. и value будут заменены соответствующими аргументами и значениями, когда макрос расширяется. Отметьте, что левые скобки должны идти сразу после имени (никаких пробелов между ними), в противном случае это будет интерпретировано как часть величины макроса формы (1).
Примеры:
Обратите внимание на размещение первой скобки '(' в примерах, приведенных ниже.
#define EIGHT (1 << 3)
#define SQR(X) ((X)*(X))

.UNDEF – отменить определение символьного имени регистра
Описание:
Отмена определения имени, которое прежде определялось директивой .DEF или #define. Это позволит избежать сообщений об ошибке при многократном использовании регистра. Если имя прежде не определено, директива .undef будет проигнорирована, это в соответствии со стандартом ANSI C. То же можно сделать из командной строки, используя опцию -U.
Синтаксис:
.UNDEF символ
Пример:
.DEF var1 = R16 
ldi var1, 0x20
...; сделает что-то с использованием var1.
.UNDEF var1
.DEF var2 = R16; теперь использование R16 не будет вызывать предупреж-дения.


#ifdef или .IFDEF – директива условной компиляции
Синтаксис:
#ifdef имя
Описание:
Сокращение от #if defined. Все следующие строки до соответствующего #endif, #else или #elif условно ассемблируются, если имя определено прежде.
Пример:
#ifdef FOO
……….. // делает что-то.
#endif

#ifndef – директива условной компиляции
Синтаксис:
#ifndef имя
Описание:
Сокращенная запись от #if not defined. Противоположность #ifdef. Все следующее строки до соответствующих #endif, #else или #elif условно ассемблируются, если имя не определено.

#if
#elif – директивы условной компиляции
Синтаксис:
#if условие
#elif

Описание:
Все следующие строки до соответствующего #endif, #else или #elif условно ассемблируются, если условие является истиной (не равно 0). Условие – любое целое выражение, включая макросы препроцессора, которые расширены (распакованы). Препроцессор распознает оператор defined(name), который возвращает 1, если имя определено, и 0 – в противном случае. Любые не определенные символы, использованные в условии по умолчанию, = 0.
Условие может быть вложенным на произвольную глубину.
#elif оценивает условие так же, как #if, за исключением того, что только что оценено, и если никакой предшествующей ветвлению командой #if … #elif данное условие не было оценено как истина.
Примеры:
#if 0
………..     // Здесь код никогда не компилируется.
#endif
#if defined(__ATmega48__) || defined(__ATmega88__)
………….   // код специфичный для этих устройств.
#elif defined (__ATmega169__)
…………   // код специфичный для ATmega169.
#endif

Препроцессор AVRASM2 не делает отдельный проход до вызова Ассемблера, он встроенная часть Ассемблера. Это может вызвать некоторую неразбериху, если препроцессор и Ассемблер создают аналогичные разнотипные объекты (например, #if и .if условия). Это также вызывает сбои препроцессора при использовании условий в макросах Ассемблера, которые нужно оценивать, когда макрос распакован, а не когда он определен. Условные выражения не могут распределять начало или конец макроопределения (но могут распределить целое макроопределение, включая начало и окончание).

.ENDIF – директива условного ассемблирования
Завершает условный блок кода после директив .IF, .IFDEF или .IFNDEF. Условные блоки (.IF...ELIF... .ELSE...ENDIF) могут быть вложенными, но все они должны быть выполнены до конца файла (условные блоки не могут работать в нескольких файлах).
Синтаксис:
.ENDIF
.IFDEF  |.IFNDEF


.ELIF, .ELSE– директивы условного ассемблирования
.ELIF включит в процесс ассемблирования код, следующий за ELIF, до соответствующего ENDIF или следующего ELIF, если expression явля-ется истиной. В противном случае этот код будет пропущен.
.ELSE включит код до .ENDIF, если условия в директиве .IF и условия во всех .ELIF были ложными.
Синтаксис:
.ELIF
.ELSE
.IFDEF |.IFNDEF
...
.ELSE | .ELIF
...
.ENDIF
Пример:
.IFDEF DEBUG
.MESSAGE "Debugging.."
.ELSE
.MESSAGE "Release.."
.ENDIF

#else – директива условной компиляции
Синтаксис:
#else
Описание:
Все следующие строки до соответствующего #endif условно ассемблируются, если никакая предшествующая ветка в составе последовательности #if... #elif... не оценена как истина.
Пример:
#if defined(__ATmega48__) || defined(__ATmega88__)
………….    // код специфичный для этих МК
#elif defined (__ATmega169__)
…………..    // код специфичный для ATmega169
#else
#error "Unsupported part:" __PART_NAME__   // сообщение об ошибке.
#endif

.IF, .IFDEF, .IFNDEF – директивы условного ассемблирования
Условное ассемблирование включает команды из исходного кода в процесс ассемблирования выборочно. Директива IFDEF включит код до соответствующей директивы ELSE, если определен. Символ должен быть определен директивами EQU или SET (не будет работать с директивой DEF). Директива IF, если отлично от 0, включит код до соответствующей директивы ELSE или ENDIF. Возможны до пяти уровней вложенности.
Синтаксис:
.IFDEF
.IFNDEF
.IF
.IFDEF |.IFNDEF
...
.ELSE | .ELIF
...
.ENDIF

Пример:
.MACRO SET_BAT
.IF @0>0x3F
.MESSAGE "Адрес больше, чем 0x3f"
lds @2, @0
sbr @2, (1<<@1)
sts @0, @2
.ELSE
.MESSAGE " Адрес меньше или равен 0x3f"
.ENDIF
.ENDMACRO

.ERROR – вывод строки с сообщением об ошибке.
.WARNING – вывод строки с предупреждением.
.MESSAGE – вывод строки с сообщением.
Синтаксис:
.ERROR “строка”
.WARNING “строка”
.MESSAGE “строка”
Описание:
.ERROR – (ошибка) выдает сообщение об ошибке, останавливает компиляцию и увеличивает счетчик ошибок Ассемблера, тем самым помогает успешному ассемблированию программы. #error определена в стандарте ANSI C.

Пример:
.IFDEF TOBEDONE
.ERROR "Still stuff to be done.."
.ENDIF


.WARNING – (предупреждение) выдает предупреждающее сообщение и увеличивает счетчик предупреждений Ассемблера. В отличие от error не останавливает компиляцию. Директива .warning не определена в стандарте ANSI C, но обычно реализована в препроцессорах, как, например, в препроцессоре GNU C.
Пример:
.IFDEF EXPERIMENTAL_FEATURE
.WARNING "This is not properly tested, use at own risk."

.ENDIF
.MESSAGE – (сообщение) выдает сообщение и не влияет на счетчики ошибок и предупреждений Ассемблера. .message не определено в стандарте ANSI C.

Пример:
.IFDEF DEBUG
.MESSAGE "Debug mode"
.ENDIF

Для всех директив сообщения включают файловое имя и номер строки, подобно нормальным сообщениям об ошибках и предупреждениях.
Макросы препроцессора распаковываются, кроме заключенного внутри двойных кавычек (").
Пример:
.error "Неподдерживаемый МК:" __PART_NAME__

#include или .INCLUDE – включение другого файла
Синтаксис:
1) " file "
2) #include
Описание:
Включение файла. Две формы отличаются тем, что (1) ищет сначала текущий рабочий директорий и функционально эквивалентна директиве .include Ассемблера. (2) ищет в установленном месте – обычно в директории C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes. Обе формы ищут включаемые файлы в известном месте установленным Ассемблером.
Лучше использовать абсолютные имена пути к файлу в директивах #include, так как поиск файлов затрудняется при перемещении проектов между другими директориями/компьютерами. Используйте опцию -I командной строки, чтобы определять путь, или установите его в AVR Studio - Project - Assembler Options, в окошке Additional include path.
Примеры:
#include; Ищет в каталоге Appnotes.
#include "mydefs.inc"  ; Ищет в рабочем каталоге.
; iodefs.asm:
.EQU sreg   = 0x3f      ; Status register.
.EQU sphigh = 0x3e    ; Stack pointer high.
.EQU splow  = 0x3d    ; Stack pointer low.
; incdemo.asm
.INCLUDE iodefs.asm  ; Include I/O definitions.
        in r0,sreg    ; Read status register.

.OVERLAP – перекрытие
.NOOVERLAP – неперекрытие
Эти директивы нужны для проектов со специфическими особенностями и не должны использоваться в обычных случаях. Они к настоящему времени влияют только на активный сегмент (cseg/dseg/eseg).
Директивы .overlap/nooverlap выделяют секцию кода/данных, которой будет позволено перекрываться с кодом/данными, определенными где-нибудь еще, без генерации сообщения об ошибке или предупреждения. Это полностью независимо от того, что установлено с использованием директивы перекрытия #pragma. Атрибут допустимого перекрытия останется эффективным по директиве .org, но не последует по директивам .cseg/.eseg/.dseg (каждый сегмент выделяется отдельно).

Синтаксис:
.OVERLAP
.NOOVERLAP
Пример:
.overlap
.org 0                      ; Секция #1.
    rjmp    default
.nooverlap.org 0        ; Секция #2.
    rjmp    RESET      ; Здесь нет ошибки.
.org 0                        ; Секция #3.
    rjmp    RESET      ; Ошибка, так как есть перекрытие с секцией #2.

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

#pragma общего назначения
Синтаксис:
1) #pragma warning range byte option – предупреждение о байтовом диапазоне;
2) #pragma overlap option – перекрытие;
3) #pragma error instruction – ошибки инструкций;
4) #pragma warning instruction – предупреждения по поводу инструкций.
Описание:
1. Ассемблер оценивает постоянные целые выражения как 64 - битные знаковые целые. Когда такие выражения использованы как непосредственные операнды, они должны быть включены в количество битов, требующихся команде. Для большинства операндов выход из диапазона вызовет сообщение ошибки "операнд из диапазона". Тем не менее непосредственные байтовые операнды для команд ldi, cpi, ori, andi, subi, sbci имеют несколько возможных интерпретаций, в зависимости от опции (option):
option = integer: операнд непосредственно оценен как целое, и если его значение за пределами диапазона (-128 ... 255), будет дано предупреждение. Ассемблер не знает, что предполагает пользователь: операнд целым, со знаком или без знака, следовательно, он допускает любое значение со знаком или без знака, которое умещается в байт.
option = overflow (умолчание): операнд оценивается как байт без знака, и любые биты знака будут проигнорированы. Эта опция пригодна при работе с битовыми масками, когда интерпретация целого должна вызывать массу предупреждений, подобно ldi r16, ~ ((1 << 7) | (1 << 3)).
option = none: не выводится никаких предупреждений о диапазоне для байтовых операндов. Не рекомендуется.
2. Если две секции кода, размещенные в памяти директивой .org, перекрываются, передается сообщение об ошибке. Опции модифицируют это поведение следующим образом:
option = ignore: игнорирует условия перекрытия и не выдаются никакие ошибки, никакие предупреждения. Не рекомендуется.
option = warning: при обнаружении перекрытия выдается предупреждение.
option = error: считает перекрытие как ошибку, это рекомендовано устанавливать по умолчанию.
3. Использование инструкций, которые не поддерживаются на выбранном устройстве, вызывает ошибку Ассемблера (поведение по умолчанию).
4. Использование инструкций, которые не поддерживаются на выбранном устройстве, вызывает предупреждение Ассемблера.
Исключён фрагмент. Полный вариант статьи доступен только полноправным членам сообщества и подписчикам.
Пожалуйста, ознакомьтесь с условиями доступа.


Продолжение следует!
Дальше разберем выражения и функции ассемблера AVRASM2 и
определимся с инициализацией программ.

Об авторе

Радик (galrad)
РФ. Республика Башкортостан. г.Уфа
1964г.р. Специальность - врач. Должность - доцент кафедры. Ученая степень - кандидат медицинских наук. Радиоэлектроника - увлечение с детства (с 15 лет). Приоритетные направления - микроконтроллеры, цифровая электроника, измерения, ремонт компьютеров и сотовых телефонов, и т.п. Второе высшее образование - инженер-электроник.
 

Понравилось? Палец вверх!

  • всего лайков: 11

Поделись с друзьями!


Связанные материалы:


Несколько функций для програмной реализации протокола I2C на AVR

Добрый день, дорогие друзья! Решил поделиться с вами несколькими функция для работы...

Программирование микроконтроллеров в AtmelStudio 6. Часть 2. Одна программа на

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

Ремонт вызывного устройства телефонных аппаратов

Вызывное устройство современных телефонных аппаратов может быть собрано как на транзисторах так и...

Програмирование в AVR Studio 5 с самого начала. Часть 8

Перейдем к изучению встроенных таймеров. Изучение прерываний и особенно таймеров в...

Програмирование в AVR Studio 5 с самого начала. Часть 7

Поговорим о прерываниях. Слово прерывание говорит само за себя, происходит остановка...

Програмирование в AVR Studio 5 с самого начала. Часть 6

Продолжим разбор теоретических основ, без которых невозможно полноценное создание программ....

Програмирование в AVR Studio 5 с самого начала. Часть 4

Сегодня рассмотрим программу “бегущих огней” и “бегущих теней”. Примеры “бегущих огней” можно найти...

Програмирование в AVR Studio 5 с самого начала. Часть 3

Мы научились включать и выключать светодиоды, а как сделать, чтобы они сами заморгали? Понятно, что...

Програмирование в AVR Studio 5 с самого начала. Часть 2

Пишем первую программу!Большинство начинают с мигания светодиодов, и мы не исключение. Если...

Програмирование в AVR Studio 5 с самого начала. Часть 1

Каждый человек, который только начинает осваивать программирование микроконтроллеров,...

TDA7442D+ATmega8. Микропроцессорный регулятор громкости

Привет ВСЕМ!!! Интересно, кому бы не хотелось, чтобы его усь обладал сервисом промышленных...

Электронные устройства для дома. Евсеев А. Н.

Евсеев Андрей Николаевич Электронные устройства для дома. — М.: Радио и связь, 1994г. — 144 с: ил....
<
  • Гражданин
24 декабря 2011 17:12

Максим / makc

  • Регистрация: 23.06.2008
  • Публикаций: 0
  • Комментариев: 39
 
  • 0
ГЕНИАЛЬНАЯ СТАТЬЯ!!! АВТОРУ БОЛЬШОЕ СПАСИБО!

<
  • Прохожий
24 декабря 2011 21:29

/ ALEXIN88

  • Регистрация: --
  • Публикаций: 0
  • Комментариев: 0
 
  • 0
ну наконец то продолжение. учимся учимся.преподавателю большой респект

<
  • Гражданин
26 декабря 2011 12:49

Евгений / emw

  • Регистрация: 28.01.2009
  • Публикаций: 0
  • Комментариев: 22
 
  • 0
Спасибо, очень познавательно.

<
  • Прохожий
29 декабря 2011 21:52

/ Ryan

  • Регистрация: --
  • Публикаций: 0
  • Комментариев: 0
 
  • 0
Дай Вам Бог здоровья. С наступающим Новым годом!

<
  • Гражданин
1 января 2012 18:33

Григорий / faers

  • Регистрация: 20.09.2008
  • Публикаций: 2
  • Комментариев: 25
 
  • 0
Спасибо автору, очень познавательная статья. Правда дочитал только до половины. Потом в голове всё смешалось с венегретом. blush Всех с праздником. Когда голова просветлеет будем изучать hi

<
  • Гражданин
1 января 2012 21:14

Игорь / AudioKiller

  • Регистрация: 10.01.2012
  • Публикаций: 3
  • Комментариев: 293
 
  • 0
Вопрос: в некоторых радиолюбительских конструкциях используются контроллеры, имеющие достаточно большое "набортное" ПЗУ. Тем не менее, устройства оснащаются внешней микросхемой памяти, куда и записываются программы. Почему?

<
  • Гражданин
2 января 2012 20:48

Радик / galrad

  • Регистрация: 23.08.2011
  • Публикаций: 12
  • Комментариев: 84
 
  • 0
Поздравляю Всех читателей с Наступившим НОВЫМ 2012 годом!

Цитата: AudioKiller
в некоторых радиолюбительских конструкциях используются контроллеры, имеющие достаточно большое "набортное" ПЗУ. Тем не менее, устройства оснащаются внешней микросхемой памяти, куда и записываются программы. Почему?


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

2.Один из способов кодирования данных, кодирующая-раскодирующая программа прописана во внутренней SRAM, внешнее устройство содержит данные в кодированной форме - на этом принципе работают электронные SMART-карты, банковские, спутниковые и т.п.

3.Как вариант подключения дополнительного интерфейса - устройств ввода-вывода.

4.Создание дополнительных библиотек инструкций в виде подключаемых модулей во внешней SRAM.

<
  • Гражданин
4 января 2012 01:29

Игорь / AudioKiller

  • Регистрация: 10.01.2012
  • Публикаций: 3
  • Комментариев: 293
 
  • 0
Дык, нет же. Такое я и сам могу сообразить. Там программы небольшие, а внутренняя память микроконтроллера вообще не используется. Я даже подумал, что она менее надежна, чем внешнее ПЗУ. Например, с контроллером 2313, имеющем набортную флэш 1Кх16 используют память АТ24С01 с организацией 1Кх8. Это как раз для управления аудиоустройствами: регулятором громкости, тембра и т.п. по I2C.

Информация
Вы не можете участвовать в комментировании. Вероятные причины:
— Администратор остановил комментирование этой статьи.
— Вы не авторизовались на сайте. Войдите с паролем.
— Вы не зарегистрированы у нас. Зарегистрируйтесь.
— Вы зарегистрированы, но имеете низкий уровень доступа. Получите полный доступ.