Asm(код: список_выходных_операндов, список_входных_операндов)
Пример 4.3. Ассемблерная вставка.
asm(“in %0, %1” : “=r” (value) : “I” (_SFR_IO_ADDR(PORTD)));
В этой ассемблерной вставке описаны:
ассемблерная команда “in %0, %1”;
список выходных операндов “=r” (value);
список входных операндов “I” (_SFR_IO_ADDR(PORTD)).
Вторая и третья части оператора asm предназначены для определения связи между регистрами микроконтроллера и операндами C. В самих ассемблерных инструкциях ссылки на операнды создаются с помощью символа “%” и порядкового номера операнда (начиная с нуля). В примере 5.1 ссылке %0 соответствует входной операнд “=r” (value), а ссылке %1 – выходной операнд “I” (_SFR_IO_ADDR(PORTD)). В результате может быть получена инструкция in r24, 12. Если ассемблерные инструкции не используют операндов, то соответствующие части оператора asm могут быть опущены, например, asm (“cli”::). Во избежание исключения ассемблерной вставки в результате оптимизационной стратегии компилятора, к оператору asm следует добавить атрибут volatile, например:
asm volatile (“in %0, %1” : “=r” (value) : “I” (_SFR_IO_ADDR(PORTD)));
Заголовочные файлы для программ в WinAVR находятся в папках:
\WinAVR\avr\include\,
\WinAVR\avr\include\avr\,
\WinAVR\avr\include\compat\,
\WinAVR\avr\include\util\.
В папке \WinAVR\avr\include\avr\ содержатся заголовочные файлы с определениями, специфичными для микроконтроллеров AVR. Например, там есть набор файлов, определяющих адреса портов, биты управляющих регистров и другие элементы конкретных микроконтроллеров. В примере 4.4 показан фрагмент заголовочного файла io2313.h, который облегчает работу с микроконтроллером AT90S2313.
Пример 4.4. Фрагмент файла определения микроконтроллера.
/* I/O registers */
/* Analog Comparator Control and Status Register */
#define ACSR _SFR_IO8(0x08)
/* UART Baud Rate Register */
#define UBRR _SFR_IO8(0x09)
/* UART Control Register */
#define UCR _SFR_IO8(0x0A)
/* UART Status Register */
#define USR _SFR_IO8(0x0B)
/* UART I/O Data Register */
#define UDR _SFR_IO8(0x0C)
Использование таких файлов позволяет при обращении к регистрам микроконтроллера в программе на языке C WinAVR использовать их мнемонические обозначения, например, DDRB или TCCR1A.
В примере 4.5 приведена программа, с помощью которой организуется ежесекундное мигание индикатора. При ее написании предполагается, что светодиодный индикатор подключен к выводу 0 порта B. Мигание индикатора задается с помощью прерывания при переполнении таймера, например таймера/счетчика Timer/Counter1. С помощью разрядов CS10 – CS12 регистра TCCR1B устанавливается коэффициент деления частоты системной синхронизации для тактирования таймера, например, коэффициент 1024 соответствует значению 5 в разрядах CS10 – CS12. Таким образом, в случае рабочей частоты микроконтроллера 4 МГц значение счетного регистра TCNT1 будет увеличиваться через каждые 1024/4000000 = 0.000256 с. Следовательно необходимо установить такое стартовое значение счетчика, чтобы до его переполнения отсчитывалось 1/0.000256 = 3906 импульсов. Поскольку с помощью 16 разрядов счетчика можно получить максимальное значение 65535, то он должен инициализироваться величиной
65536 – 3906 = 61630.
Реализация рассмотренного алгоритма приведена в примере 5.4.
Пример 4.5. Программа мигающего индикатора.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#define Freq 4000000
INTERRUPT(SIG_OVERFLOW1)
{
TCNT1 = 0x10000 - (Freq / 1024);
PORTB ^= 0x01;
}
int main (void)
{
DDRB = 0x01;
TCCR1A = 0;
TCCR1B = 5;
TCNT1 = 0x10000 - (Freq / 1024);
TIFR = 0;
TIMSK = 0x04;
GIMSK = 0;
sei();
while(1) ;
}
