Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Уч. пос. МПТ (2.04.12).pdf
Скачиваний:
403
Добавлен:
22.03.2015
Размер:
10.95 Mб
Скачать

2.5.5 Пример простой программы

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

Впрограмме используется прерывание от таймера 0 и глобальная переменная счетчик Counter. Вначале счетчику присваивается значение 20. При каждом достижении таймером порога значение счетчика декрементируется, формируется перепад на портовой линии P0.7. Генерирование импульсов не производится, если счетчик больше десяти. При достижении счетчиком нуля ему снова присваивается значение 20 и цикл повторяется.

IO0PIN

 

EQU

0xE0028000

IO0DIR

 

EQU

0xE0028008

T0IR

 

EQU

0xE0004000

T0TCR

 

EQU

0xE0004004

T0MCR

 

EQU

0xE0004014

T0MR0

 

EQU

0xE0004018

VICIntEnable EQU

0xFFFFF010

VICVectAddr

EQU

0xFFFFF030

VICVectAddr0

EQU

0xFFFFF100

VICVectCntl0 EQU

0xFFFFF200

MACRO

 

 

 

LoadConst

$Val, $Reg, $Length

LDR

 

R0, =$Reg

IF "$Length" == "Short"

MOV

 

R1, #$Val

ELSE

 

 

 

LDR

 

R1, =$Val

ENDIF

 

 

 

STR

 

R1, [R0]

MEND

 

 

 

AREA

STACK, DATA

StackBottom

SPACE 1024

AREA

Vars, DATA

Counter

SPACE 4

 

AREA

RESET, CODE

ENTRY

 

 

 

B

Start

 

SPACE

16

 

 

150

DCD

0x77BFA08A

LDR

PC, [PC, #-0x0FF0]

SPACE

4

Start

 

MSR

CPSR_c, #0x12

LDR

SP, =StackBottom+1024

MSR

CPSR_c, #0x10

LoadConst 0x80, IO0DIR, Short

LoadConst 1000000, T0MR0, Long

LoadConst 0x03, T0MCR, Short

LoadConst 0x01, T0TCR, Short

LoadConst Timer0Int, VICVectAddr0, Long

LoadConst 0x24, VICVectCntl0, Short

LoadConst 0x10, VICIntEnable, Short

LoadConst 20, Counter, Short

Loop

B

Loop

 

Timer0Int

 

 

 

STMDB

SP!, {R0-R3}

 

LDR

R0, =Counter

 

LDR

R1, [R0]

 

SUBS

R1, R1, #1

 

MOVEQ

R1, #20

 

STR

R1, [R0]

 

CMP

R1, #10

 

BGT

Skip

 

 

LDR

R0, =IO0PIN

 

LDR

R1, [R0]

 

EOR

R1, R1, #0x80

 

STR

R1, [R0]

Skip

LoadConst

0x01, T0IR, Short

 

LoadConst

0x00, VICVectAddr, Short

 

LDMIA

SP!, {R0-R3}

 

SUBS

PC, R14, #4

END

151

Дадим некоторые пояснения. Текст программы начинается с объявления имен регистров. Стандартным именам присваиваются соответствующие адреса директивой EQU.

Далее объявлен макрос LoadConst, содержащий команды загрузки команды в управляющий регистр. Макрос имеет три параметра: загружаемая числовая константа (Val), адрес регистра (Reg) и модификатор (Length). С помощью директив IF…ELSE…ENDIF загрузка осуществляется либо командой MOV, либо LDR. Если константа может быть предоставлена в виде сдвигового 12-разрядного операнда, передается параметр Length = Short и выполняется команда MOV, иначе загрузка выполняется командой LDR.

Директива AREA…DATA определяет область памяти для стека. А SPACE резервирует под стек 1024 байта. Начало этой области получает имя StackBottom.

Аналогично создается глобальная переменная Counter размером 4 байта.

Область кода программы объявляется директивой AREA…CODE. Первой инструкцией программы является команда безусловного пере-

хода на точку входа, обозначенную ниже меткой Start.

В области векторов прерываний занята командой передачи управления процедуре обработки прерываний (LDR PC, [PC, #-0x0FF0]), а также контрольной суммой (директива DCD). Директивы SPACE заполняют пустые пространства.

Основная программа начинается после метки Start. Первые три строки: перевод ядра в режим IRQ; инициализация указателя стека (SP) режима IRQ; перевод ядра в режим User. Здесь инициализация стека выполняется путем загрузки в него суммы базового адреса стека и объема стека (1024 байта), зарезервированного ранее.

С помощью макроса LoadConst выполняется настройка портовой линии, таймера и системы прерываний; присваивается начальное значение пе- ременной-счетчику Counter.

Основная программа завершается командой вечного цикла (переход на метку Loop).

Ниже размещается подпрограмма обработки прерываний (метка Timer0Int). Вначале сохраняются в стек регистры R0–R3 (команды STMDB).

Далее выполняется декремент счетчика и присваивание начального значения (20) в случае равенства нулю.

Следующий блок пропускается (метка Skip), если счетчик больше 10. Блок содержит команды инверсии портовой линии.

Далее выполняется обычная процедура возврата из прерывания: с помощью макроса LoadConst снимается флаг запроса прерывания и обнуляется регистр VICVectAddr. Регистры общего назначения восстанавливаются из стека, выполняется возврат командой SUB с участием счетчика команд.

152