Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЦП та МП лр6 Бег огни (таймер с прерыванием).doc
Скачиваний:
19
Добавлен:
29.08.2019
Размер:
1.93 Mб
Скачать

Програма на Асемблері

Текст можливого варіанту програми на мові Асемблер приведений в лістингу 6.1. У програмі зустрічаються декілька нових для нас операторів.

Зверніть увагу. Використовується новий для нас прапор - прапор глобального дозволу переривань, який називається I.

Ми вже згадували цей прапор в розділі 3. Прапор I, так само, як прапори С і Z, є одним з розрядів регістра SREG. Проте управління прапором I відбувається зовсім по-іншому. На нього не впливають ні арифметичні, ні логічні операції, а тим більше операції порівняння. Для установки і скидання цього прапора в системі команд передбачені дві спеціальні команди (описані нижче). Якщо прапор I скинутий, то всі переривання в мікроконтролері заборонені. Якщо прапор встановлений, робота системи переривань дозволяється. Розглянемо тепер по порядку всі нові для нас оператори.

.dseg

Оператор вибору сегмента пам'яті даних. До цих пір у всіх попередніх ассемблерних програмах ми обов'язково використовували оператор .cseg, який дозволяв нам вибирати програмний сегмент пам'яті. Пора навчитися працювати і з іншими сегментами.

Наступний за значенням після програмного сегмента - це сегмент пам'яті даних, тобто сегмент ОЗП. У програмі (лістинг 1.13) у рядку 6 проводиться вибір саме цього сегмента.

. byte

Оператор резервування пам'яті. Це один з операторів, які діють в сегменті пам'яті даних. Оператор дозволяє зарезервувати один або декілька байтів (комірок ОЗП) для того, щоб потім використати їх у програмі. Ви запитаєте: навіщо це потрібно? Основна мета резервування - облік і розподіл пам'яті.

Якщо програміст буде довільно, на свій розсуд, вибирати адреси комірок ОЗП для тієї або іншої задачі, то йому доведеться уважно стежити за тим, щоб не вибрати повторно одну і ту ж комірку для зберігання різних значень. Інакше програма при записі одного значення зіпсує друге, що призведе до помилки в її роботі.

Механізм резервування пам'яті дозволяє транслятору контролювати використання пам'яті і виключати подвійне використання комірок. Крім того, подібний механізм взагалі позбавляє програміста від необхідності запам'ятовувати адреси. Все відбувається автоматично.

Оператор .byte має всього один параметр - кількість комірок, які потрібно зарезервувати. У нашій програмі застосовується лише одна команда, що резервує пам'ять (рядок 8, лістинг 1.13). У даному випадку резервується всього одна комірка пам'яті. Мітка buf, поставлена ​​перед оператором, використовується для звернення до зарезервованої комірки.

reti

Оператор завершення підпрограми обробки переривання. Дія цього оператора аналогічна дії оператора ret. Він витягає адресу з стеку і передає управління за цією адресою. Різниця полягає в тому, що команда reti ще і встановлює в одиницю прапор глобального дозволу переривань I.

sts

Команда запису вмісту РОН в ОЗП. Має два параметри. Перший параметр - адреса комірки пам'яті, куди записуються дані.

Другий параметр - ім'я регістра джерела даних. У рядку 49 програми вміст регістра rab записується в ОЗП за адресою, що визначається міткою buf.

lds

Команда читання інформації з комірки пам'яті. Прочитана інформація записується в один з РОН. Команда також має два параметри. Перший параметр - ім'я РОН, куди записуються зчитані дані. Другий параметр – адреса комірки пам'яті (джерела даних).

set

Команда дозволу переривань. Ця команда встановлює прапор I. Тобто дозволяє все переривання.

Лістинг 6.1

;#############################################

;## Приклад 7 ##

;## «Біжучі вогні» ##

;## з використанням переривань від таймера ##

;#############################################

;-------------------------------------Псевдокоманди керування

1

.include “tn2313def.inc”

; Приєднання файлу опису

2

.list

; Ввімкнення лістингу

3

.def temp = R16

; Визначення головного робочого регістру

4

.def rab = R17

; Визначення робочого регістру для команд здвигу

5

.equ kdel = 780

;------------------------------------ Резервування комірок пам’яті

6

.dseg

; Обираємо сегмент ОЗП

7

.org

0x60

; Встановлюємо поточну адресу сегменту

8

buf:

.byte

1

; Один байт для збереження робочого значення

;------------------------------------ Початок програмного коду

9

.cseg

; Вибір сегменту програмного коду

10

.org

0

; Встановлення поточної адреси на нуль

;------------------------------------

11

start:

rjmp

init

; Перехід на початок програми

12

reti

; Зовнішнє переривання 0

13

reti

; Зовнішнє переривання 1

14

reti

; Таймер/лічильник 1, захоплення

15

rjmp

prtim1

; Таймер/лічильник 1, співпадіння, канал А

16

reti

; Таймер/лічильник 1, співпадіння по переповненню

17

reti

; Таймер/лічильник 0, співпадіння по переповненню

18

reti

; Переривання UART прийом завершений

19

reti

; Переривання UART регістр даних пустий

20

reti

; Переривання UART передача завершена

21

reti

; Переривання по компаратору

22

reti

; Переривання по зміні на будь-якому контакті

23

reti

; Таймер/лічильник 1, співпадіння, канал В

24

reti

; Таймер/лічильник 0, співпадіння, канал В

25

reti

; Таймер/лічильник 0, співпадіння, канал А

26

reti

; USI готовність до старту

27

reti

; USI переповнення

28

reti

; EEPROM готовність

29

reti

; Переповнення охоронного таймеру

;------------------------------- Модуль ініціалізації

init:

;------------------------------------ Ініціалізація стеку

30

ldi

temp, RAMEND

; Вибір адреси вершини стеку

31

out

SPL, temp

; Запис її в регістр стеку

;------------------------------------ Ініціалізація портів ВВ

32

ldi

temp, 0

; Записуємо нуль в регістр temp

33

out

DDRD, temp

; Записуємо цей нуль в DDRD (порт PD на ввід)

34

ldi

temp, 0xFF

; Записуємо число $FF в регістр temp

35

out

DDRB, temp

; Записуємо temp в DDRB (порт РВ на вивід)

36

out

PORTB, temp

; Записуємо temp в P0RTB (згасити світлодіод)

37

out

PORTD, temp

; Записуємо temp в P0RTD (включаємо внутр. резист.)

;------------------------------------ Ініціалізація таймера T1

38

ldi

temp, 0x05

; Вибір режиму таймеру

39

out

TCCR1B, temp

40

ldi

temp, high(kdel)

; Старший напівбайт коду співпадіння

41

out

OCR1AH, temp

; Запис в регістр співпадіння старшого напівбайту

42

ldi

temp, low(kdel)

; Молодший напівбайт коду співпадіння

43

out

OCR1AL, temp

; Запис в регістр співпадіння молодшого напівбайту

;------------------------------------ Визначення маски переривань

44

ldi

temp, 0b10000000

; Байт маски. Дозволене одне переривання.

45

out

TIMSK, temp

; Записуємо маску.

;------------------------------------ Ініціалізація компаратора

46

ldi

temp, 0x80

; Вимкнення компаратора

47

out

ACSR, temp

;------------------------------------ Початок основної програми

48

main:

ldi

rab, 0b00010000

; Запис початкового значення

49

sts

buf, rab

; Запис вмісту регістру rab в ОЗП

50

sei

; Дозвіл переривань

51

m1:

rjmp

m1

; Пустий нескінченний цикл

;= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

; Підпрограма обробки переривань

;= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

52

prtim1:

push

temp

; Зберігаємо регістр temp

53

push

rab

; Зберігаємо регістр rab

54

lds

rab, buf

; Читаємо вміст rab з ОЗП

55

in

temp, PIND

; Зчитуємо вміст порту PD

56

sbrs

temp, 0

; Перевірка молодшого розряду

57

rjmp

p2

; Якщо не нуль, перейдемо до здвигу вліво

;------------------------------------- Здвиг вправо

58

p1:

lsr

rab

; Здвиг вмісту робочого регістру

59

brcc

p3

; Якщо не дійшло до кінця регістру пропустити

60

ldi

rab, 0b10000000

; Запис початкового значення

61

rjmp

p3

; В кінець

;------------------------------------- Здвиг вліво

62

p1:

lsr

rab

; Здвиг вмісту робочого регістру

63

brcc

p3

; Якщо не дійшло до кінця регістру пропустити

64

ldi

rab, 0b00000001

; Запис початкового значення

;-------------------------------- Кінець процедури обробки переривання

65

p3:

ldi

temp, 0xFF

; Записуємо число $FF в регістр temp

66

eor

temp, rab

; Інверсія вмісту rab (виключаюче АБО)

67

out

PORTB, temp

; Вивід поточного значення в порт РВ

68

sts

buf, rab

; Запис вмісту регістру rab в ОЗП

69

pop

rab

; Відновлюємо регістр rab

70

pop

temp

; Відновлюємо регістр temp

71

reti

Фото програми для перевірки: