Пособие HCS12 & Elvis II v.7.01
.pdf
|
BCS |
CHK3 |
;Если результат отрицательный, то перейти на CHK4. |
||
|
CMPB |
#20 |
;Иначе сравнить полученную разность с числом 20. |
||
|
BCS |
RES2 |
;Если меньше 20, то перейти на RES2. |
||
|
BSET Result,$10 |
|
;Иначе Data2 − Data1 ≥ 20, значит надо |
||
|
JMP |
quit |
|
;установить бит 4 результирующей ячейки в 1. |
|
RES2 |
|
|
|||
BSET Result,$04 |
|
;Если 0 < Data2 − Data1 < 20, то установить бит 2 |
|||
|
JMP |
quit |
|
;результата в 1. |
|
CHK3 |
;Загрузка в аккумулятор A данных из ячейки Data1. |
||||
LDAA |
Data1 |
||||
|
SUBA |
Data2 |
;Вычитание из Data1 и значения ячейки памяти Data2. |
||
|
CMPA |
#20 |
;Сравнение полученной разности с числом 20. |
||
|
BCS |
RES1 |
;Если меньше 20, то переход по метке RES1. |
||
|
BSET Result,$08 |
|
;Иначе Data1 − Data2 ≥ 20, значит надо |
||
|
JMP |
quit |
|
;установить бит 3 результирующей ячейки в 1. |
|
RES1 |
|
|
|||
BSET |
Result,$02 |
;Если 0 < Data1 − Data2 < 20, то установить бит 1 |
|||
quit |
JMP |
quit |
|
;результата в 1. |
|
|
|
||||
|
ORG |
StartVector |
|
||
|
DC.W |
EX_5_1 |
|
|
Пример 5.2. Дан массив однобайтовых чисел без знака. Начальный адрес – $110, количество элементов – 15. Переписать массив, начиная с адреса $130, заменив числа, у которых младший бит равен нулю, а старший – единице, кодом $A9. Определить количество таких чисел.
RAMStart |
EQU |
$0000 |
ROMStart |
EQU |
$E000 |
StartVector |
EQU |
$FFFE |
INITRG |
EQU |
$0011 |
Array1 |
EQU |
$0110 |
;Адрес первого элемента исходного массива. |
Array2 |
EQU |
$0130 |
;Адрес первого элемента конечного массива. |
N |
EQU |
$0150 |
;Ячейка памяти, в которую помещается количество |
CNT |
EQU |
RAMstart |
;элементов, подвергшихся замене. |
;Ячейка памяти для счёта циклов. |
|||
EXC |
EQU |
$A9 |
;Код, на который необходимо заменить элементы |
|
|
|
;массива, удовлетворяющие заданному условию. |
|
ORG |
ROMstart |
|
EX_5_2 |
MOVB |
#$08, INITRG |
|
|
CLR |
N |
;Очистка ячейки с количеством изменённых элементов. |
|
MOVB #15,CNT |
;Загрузка счётчика циклов начальным значением. |
|
|
LDX |
#Array1 |
;Загрузка в регистр X адреса первого элемента |
CHK |
LDAB ,X |
;исходного массива. |
|
;Загрузка в аккумулятор B значения ячейки с адресом, |
|||
|
ANDB #$81 |
;находящимся в X. |
|
|
;Выделение старшего и младшего битов. |
||
|
CMPB #$80 |
;Сравнение с желаемым значением. |
|
|
BNE |
INIT |
;Если не равны, то перейти по метке INIT. |
|
|
|
131 |
|
INC |
N |
;Иначе увеличить счётчик заменённых элементов на 1. |
|
LDAB |
#EXC |
;Загрузить код для замены. |
INIT |
BRA |
SAVE |
;Безусловный переход на SAVE. |
LDAB |
,X |
;Загрузка в аккумулятор A элемента исходного массива. |
|
SAVE |
STAB |
$20,X |
;Сохранение элемента нового массива. |
|
INX |
CNT |
;Увеличение адреса, хранящегося в регистре X, на 1. |
|
DEC |
;Уменьшение счётчика циклов. |
|
|
BNE |
CHK |
;Если обработаны не все элементы, то перейти по метке |
|
JMP |
* |
;CHK. |
|
|
||
|
ORG |
StartVector |
|
|
DC.W |
EX_5_2 |
|
Предложенный способ решения имеет ряд особенностей.
Во-первых, для проверки разрядов чисел мы воспользовались универсальным методом, который не зависит от местонахождения в памяти чисел первого массива. Метод заключается в выделении с помощью маски и команды “AND” значимых разрядов числа, т.е. тех, которые необходимо проверить по условию задачи. Элемент массива, ранее находившийся в аккумуляторе, при этом перестает соответствовать значению, записанному в ячейке памяти. Далее значение аккумулятора сравнивается с эталонной константой, которая гарантирует совпадение выделенных разрядов с заданными значениями. Обратите внимание, для переноса элемента из первого массива во второй, элемент необходимо заново восстановить в аккумулятор. Чтобы этого не приходилось делать, для анализа условий можно использовать команды битового процессора.
Во-вторых, мы воспользовались тем фактом, что все элементы первого массива и все элементы второго массива находятся в пределах одной страницы памяти. Поэтому возможно использование команды “INX” вместо “LEAX 1,X”.
Задачи для самостоятельной работы
1.Дан массив однобайтовых чисел со знаком. Начальный адрес – $200, количество элементов массива – 27. Начиная с адреса $100, переписать только положительные четные числа, определить количество отрицательных чисел.
2.Дан массив однобайтовых чисел со знаком. Начальный адрес – $120, код последнего элемента – $Е1. Найти среднее арифметическое максимального и минимального положительных чисел и количество положительных чисел.
3.Дан массив однобайтовых чисел со знаком. Начальный адрес – $E200, код последнего элемента – $Е1. Найти среднее арифметическое максимального и минимального положительных чисел и количество отрицательных чисел.
4.Произвести сортировку по возрастанию чисел, расположенных в ячейках $100..$120.
5.Произвести сортировку по убыванию чисел, расположенных в ячейках $50..$70.
6.Дан массив двухбайтовых чисел в прямом коде со знаком. Начальный адрес – $120, код последнего элемента – $1А24. Начиная с адреса $150 переписать только положительные чётные числа, определить количество отрицательных чисел.
7.Дан массив двухбайтовых чисел без знака. Начальный адрес – $E300, количество элементов массива – 11. Определить максимальное чётное число.
8.Дан массив однобайтовых чисел со знаком. Начальный адрес – $80, код последнего элемента – $12. Определить минимальное положительное нёчетное число и его адрес.
132
9.Дан массив двухбайтовых чисел без знака. Начальный адрес – $100, код последнего элемента – $3724. Начиная с адреса $120 записать только чётные числа, определить количество нечётных чисел.
10.Дан массив двухбайтовых чисел без знака. Начальный адрес – $120, количество элементов массива – 8. Определить максимальное число и его адрес.
133
Лабораторная работа № 6
Порты ввода/вывода и работа с ними
Содержание
В данной лабораторной работе изучаются порты ввода/вывода микроконтроллера. При работе с периферийными модулями в отладчике необходимо работать не в пошаговом режиме, а в режиме реального времени.
Подготовка к работе
При подготовке к данной работе необходимо повторить систему команд.
Схемотехника учебного стенда
Рис. 9. Схема подключения периферии к портам МК
Практическая часть
Пример 6.1. Написать программу вывода следующих значений на порт B (светодиоды) в зависимости от кода выставленного на переключателях 1,2 (PRTB0, PRTB1): код 00 – значение $7, код 01 – значение $8, код 10 – значение $F, код 11 – значение $3.
В этой лабораторной работе и последующих мы не будем инициализировать начальный адрес пространства регистров специальных функций. Тогда он будет по умолчанию равен $0000. Т.е. эта область памяти расположится в начале всего адресного пространства. Оперативная память же будет следовать за ней по адресам $0400..$0FFF. Такая карта памяти устанавливается автоматически после сброса микроконтроллера и является конфигурацией по умолчанию. Именно она рассматривается в технической
134
документации при описании работы с встроенными периферийными модулями (порты ввода/вывода, таймер, аналого-цифровой преобразователь и др.). Поэтому также будем пользоваться ей.
RAMStart |
EQU |
$0400 |
;Теперь ОЗУ располагается по адресам $400..$FFF. |
|
ROMStart |
EQU |
$E000 |
|
|
StartVector |
EQU $FFFE |
|
|
|
PRTB |
EQU |
$01 |
;Адрес регистра данных порта B. |
|
DDRB |
EQU |
$03 |
;Адрес регистра направления передачи данных через |
|
PUCR |
EQU |
$0C |
;порт B. |
|
;Адрес регистра контроля подтягивающих резисторов. |
||||
|
ORG |
$E800 |
|
|
|
DC.B $80,$70,$00,$С0 |
;Запись в память массива значений, |
||
|
|
|
|
;выводимых на порт B. Взяты значения в |
|
|
|
|
;обратном коде, т.к для светодиодов |
|
|
|
|
;активным уровнем является логический |
|
|
|
|
;ноль. |
|
ORG |
ROMstart |
|
|
|
MOVB #$F0,DDRB |
|
;Инициализация младших четырёх битов |
|
|
|
|
|
;порта B на ввод, остальных старших – на |
|
BSET PUCR,$02 |
|
;вывод. |
|
|
|
;Включение подтягивающих резисторов |
||
|
|
|
|
;порта В. |
EX_6_1 |
LDAA #$E8 |
|
;Загрузка в аккумулятор A старшего байта |
|
|
LDAB PRTB |
|
;адреса заданного массива. |
|
|
|
;Считывание данных из порта B. |
||
|
ANDB #$03 |
|
;“Отсечка” ненужных старших разрядов. |
|
|
|
|
|
;Таким образом, в аккумуляторе D сформирован |
|
|
|
|
;адрес ячейки памяти, данные из которой нужно |
|
XGDX |
|
|
;вывести на порт B. |
|
|
|
;Посылка адреса в индексный регистр X. |
|
|
LDAB ,X |
|
;Побитная инверсия значения аккумулятора B. |
|
|
COMB |
|
|
|
|
STAB PRTB |
|
|
|
|
JMP |
EX_6_1 |
|
;Возвращение в начало программы. |
|
|
|
|
;Т.к. цикл бесконечный, то порт B будет |
|
|
|
|
;постоянно опрашиваться микроконтроллером. |
|
ORG |
StartVector |
|
|
|
DC.W |
EX_6_1 |
|
|
Комментарий к примеру:
•В микроконтроллере лабораторного стенда к каждому выводу порта можно программно подключать или отключать «подтягивающие вверх» (pull-up) резисторы. Эти сопротивления нужны для того, чтобы на ножку микроконтроллера, если она настроена на ввод, стабильно приходила логическая единица. Если не использовать эти резисторы, то на выводе порта в режиме ввода и отсутствии на нём внешнего сигнала будет
135
присутствовать некоторый уровень напряжения. Его величина не будет однозначно определяться, а будет зависеть от сопротивления каналов внутренних закрытых КМОПтранзисторов, работающих как делитель напряжения.
Пример 6.2. Реализовать двоичный 4-разрядный счётчик с отображением его текущего значения на светодиодах. Тактовым входом счётчика является кнопка SW1 (PRTP0).
RAMStart |
|
EQU |
$0400 |
|
|
|
ROMStart |
|
EQU |
$E000 |
|
|
|
StartVector |
EQU |
$FFFE |
|
|
||
PRTB |
|
EQU |
$01 |
;Адрес регистра данных порта B. |
||
DDRB |
|
EQU |
$03 |
;Адрес регистра направления передачи данных через |
||
PUCR |
EQU |
$0C |
|
;порт B. |
||
|
;Адрес регистра контроля подтягивающих резисторов. |
|||||
PRTP |
EQU |
$0258 |
;Адрес регистра данных порта P. |
|||
DDRP |
EQU |
$025A |
;Адрес регистра направления передачи данных через |
|||
PERP |
EQU |
$025C |
;порт P. |
|||
;Адрес регистра контроля подтягивающих резисторов |
||||||
|
|
|
|
|
;ножек порта P. |
|
CT |
EQU |
RAMstart+$10 |
;Ячейка памяти ОЗУ для счётчика. |
|||
TMP |
EQU |
CT+$1 |
|
;Ячейка памяти для временных данных. |
||
|
ORG |
ROMstart |
|
|
||
|
MOVB #$F0,DDRB |
;Инициализация порта B: младший ниббл на |
||||
|
MOVB #$F0,PRTB |
|
;ввод, старший – на вывод. |
|||
|
|
;Потушить все светодиоды. |
||||
|
BSET PUCR,$02 |
|
;Включение подтягивающих резисторов |
|||
|
BCLR DDRP,$03 |
|
;порта В. |
|||
|
|
;Установка двух младших разрядов порта P |
||||
|
BSET PERP,$03 |
|
;на ввод. |
|||
|
|
;Включение подтягивающих резисторов на |
||||
|
|
|
|
|
|
;двух младших разрядах порта P. |
|
CLR |
CT |
|
|
|
;Установка начального значения счётчика в 0. |
|
LDX |
#PRTP |
|
;Загрузка адреса порта P в индексный регистр X. |
||
EX_6_2 |
LDY |
#$4500 |
|
|
||
|
BRSET |
,X,$01,* |
|
;Ожидание логического нуля на ножке 0 |
||
DL1 |
NOP |
|
|
|
|
;порта B. |
|
|
|
|
;Цикл для создания временной задержки для |
||
|
NOP |
|
|
|
|
;подавления дребезга. Команда NOP не |
|
NOP |
|
|
|
|
;выполняет никаких действий (No Operation), |
|
DEY |
DL1 |
|
|
;лишь увеличивает задержку. |
|
|
BNE |
|
|
|
||
|
LDY |
#$4500 |
|
|
||
|
BRCLR |
,X,$01,* |
|
;Ожидание логической единицы на ножке 0 |
||
DL0 |
NOP |
|
|
|
|
;порта B. |
|
|
|
|
;Цикл для создания временной задержки для |
||
|
NOP |
|
|
|
|
;подавления дребезга. |
|
|
|
|
|
|
136 |
NOP |
|
|
DEY |
DL0 |
|
BNE |
|
|
INC |
CT |
;Увеличение значения счётчика на 1. |
MOVB CT,TMP |
;Выгрузка значения счётчика во временную |
|
COM |
TMP |
;ячейку памяти. |
;Побитная инверсия значения ячейки TMP. |
||
LSL |
TMP |
;Четыре сдвига влево содержимого временной |
LSL |
TMP |
;ячейки памяти. |
LSL |
TMP |
|
LSL |
TMP |
|
MOVB TMP,PRTB |
;Перемещение данных из временной ячейки в |
|
|
|
;порт B. |
JMP |
EX_6_2 |
;Возврат в начало, бесконечный цикл. |
ORG StartVector
DC.W ROMstart
Комментарии к примеру:
•Любой механический переключатель или кнопка подвержены дребезгу. Дребезг – это переходный процесс из одного установившегося состояния в другое. Обычно он имеет колебательный характер. Максимальная амплитуда колебаний достигает разности между уровнями первоначального и конечного установившихся состояний (логические 0 и 1). Поэтому микроконтроллер при непрерывном мониторинге входных воздействий будет реагировать на этот паразитный процесс. Для устранения такого эффекта можно подавить дребезг программным путём: ввести задержки. Длительность переходных колебаний зависит от двух основных факторов: тип переключателя или кнопки, срок эксплуатации. Обычно продолжительно дребезга составляет от десятых долей миллисекунд до десяти миллисекунд. В рассмотренном примере при обнаружении перехода из одного состояния в другое создаётся программная задержка, примерно равная 1мс.
Задачи для самостоятельной работы
1.Дан массив символов: фамилия, представленная в ASCII-коде. При переключении переключателя SW3-1 (PRTB0) из 0 в 1 в прямом порядке циклически отображать элементы массива на светодиодах. Т.е. сначала старший ниббл первого элемента, потом младший ниббл первого элемента, затем старший ниббл второго элемента и т.д.
2.Дан массив символов: фамилия, представленная в ASCII коде. При переключении переключателя SW3-2 (PRTB1) из 1 в 0 в обратном порядке циклически отображать элементы массива на светодиодах. Т.е. сначала младший ниббл последнего элемента, потом старший ниббл последнего элемента, затем младший ниббл предпоследнего элемента и т.д.
3.Дан массив символов: фамилия, представленная в ASCII-коде. Если переключатель SW3-2 в положении 0, то при переключении переключателя SW3-1 из 0 в 1 выводить на светодиоды поочерёдно младшие нибблы массива, а если переключатель SW3-2 в положении 1, то при переключении переключателя SW3-1 из 0 в 1 выводить на светодиоды поочерёдно старшие нибблы.
4.Дан массив символов: имя и фамилия, представленных в ASCII коде. При переключении переключателя SW3-3 (PRTB2) из 0 в 1 в прямом порядке отображать элементы массива на светодиодах. При переключении переключателя SW3-4 (PRTB3) из 1 в 0 в обратном порядке отображать элементы массива на светодиодах.
137
5.Реализовать реверсивный двоичный 4-разрядный счётчик с отображением значения на светодиодах. Тактовым входом для направления счёта вверх является переключатель SW3-1, тактовым входом для направления счёта вниз является переключатель SW3-2.
6.Реализовать реверсивный двоичный 4-разрядный счётчик с отображением значения на светодиодах. Тактовым входом является кнопка SW1 (PRTP0). Направление счёта определяется переключателем SW3-3: если 1 то вверх, если 0 то вниз. У счётчика должен быть также вход синхронного сброса: если переключатель SW3-4 установлен в 0, то по тактовому импульсу происходит сброс, если 1, то счётчик работает в нормальном режиме.
7.Реализовать сдвиговый регистр. Параллельный код с выхода регистра отображается на светодиодах. Входом данных регистра является положение переключателя SW3-3 (PRTB2). Тактовым входом регистра является кнопка SW2 (PRTP1).
138
Лабораторная работа № 7
Подсистема счётчика временных интервалов
Содержание
В лабораторной работе изучается периферийный модуль микроконтроллера – счётчик временных интервалов (таймер), а также каналы выходного сравнения таймера.
Подготовка к работе
При подготовке к данной работе необходимо повторить систему команд, а также регистры порта B. Ознакомиться с подсистемой таймера.
Схемотехника учебного стенда
Рис. 10. Схема подключения периферии к портам МК
Практическая часть
Пример 7.1. Написать программу создания «бегущего огня» на светодиодах LED1..LED4 слева направо.
RAMStart |
|
EQU |
$0400 |
ROMStart |
|
EQU |
$С000 |
StartVector |
EQU |
$FFFE |
|
PRTB |
EQU |
$01 |
;Адрес регистра данных порта B. |
DDRB |
EQU |
$03 |
;Адрес регистра направления передачи данных через |
PUCR |
EQU |
$0C |
;порт B. |
;Адрес регистра контроля подтягивающих резисторов. |
|||
TSCR1 |
EQU |
$46 |
;Адрес регистра управления таймером TSCR1. |
139
TSCR2 |
EQU |
$4D |
;Адрес регистра управления таймером TSCR2. |
|
TFLG2 |
EQU |
$4F |
;Адрес регистра флагов прерываний TFLG2 таймера. |
|
TMP |
EQU |
RAMstart+$10 |
;Ячейка памяти для временных данных. |
|
|
ORG |
ROMstart |
|
|
EX_7_1 |
LDS |
#$0FFF |
|
;Инициализация верхушки стека. В качестве неё |
|
|
|
|
;взят адрес последней ячейки оперативной |
|
MOVB #$F0,DDRB |
|
;памяти. |
|
|
|
;Инициализация порта B: младший ниббл на |
||
|
BSET PUCR,$02 |
|
;ввод, старший – на вывод. |
|
|
|
;Включение подтягивающих резисторов |
||
|
MOVB #$E0,PRTB |
|
;порта В. |
|
|
|
;Зажечь светодиод LED1. |
||
|
MOVB #$10,TMP |
|
;Установка начального значения временной |
|
|
BSET TSCR2,$83 |
|
;ячейки в 1. |
|
|
|
;Разрешение прерываний по переполнению |
||
|
|
|
|
;таймера, установка частоты его тактирования |
|
BSET TSCR1,$80 |
|
;равной fBUS/8. |
|
|
|
;Включение таймера. |
||
|
CLI |
|
|
;Разрешение прерываний. |
|
JMP |
* |
|
;Бесконечный пустой цикл, ожидание |
|
|
|
|
;прерываний. |
|
ORG |
ROMstart+$100 |
|
|
TOF_INT |
BSET TFLG2,$80 |
|
;Сброс флага переполнения таймера (TOF). |
|
|
LSL |
TMP |
|
;Логический сдвиг влево содержимого |
|
|
|
|
;временной ячейки памяти. Старший разряд |
|
BCC |
OUT |
|
;помещается в бит переноса C. |
|
|
;Если бит, значение которого равно 1, не был |
||
|
MOVB #$10,TMP |
|
;помещён в бит C, то перейти по метке. |
|
|
|
;Иначе восстановить исходное значение |
||
OUT |
LDAB TMP |
|
;временной ячейки (значение $10). |
|
|
;Загрузка в аккумулятор B содержимого |
|||
|
COMB |
|
|
;временной ячейки памяти. |
|
|
|
;Поразрядная инверсия данных в регистре B. |
|
|
|
|
|
;Производится, потому что активным уровнем, |
|
|
|
|
;зажигающим светодиод порта B, является |
|
STAB PRTB |
|
;логический ноль. |
|
|
|
;Сохранение данных в порт B. |
||
|
RTI |
|
|
;Возврат из подпрограммы прерывания. |
|
ORG |
$FFDE |
|
;Запись вектора прерывания по переполнению |
|
DC.W |
TOF_INT |
|
;таймера. |
|
ORG |
StartVector |
;Запись вектора начального пуска. |
|
|
DC.W |
EX_7_1 |
|
|
|
|
|
|
140 |