Микропроцессорная система дрессировочного стана
5. Программа для работы микропроцессорного контроллера на языке ассемблер
DPPDATA84h; адрес указателя страницы данных (data; page ponter)
ADCCON1 DATA0EFH; регистр управления АЦП
ADCCON2 DATA 0D8H; регистр управления АЦП
ADCCON3 DATA 0F5H; регистр управления АЦП
ADCDATALDATA 0xD9; регистр младшего байта оцифрованных; данных АЦП
ADCDATAH DATA0xDA; регистр старшего байта оцифрованных данных; АЦП
DACCON DATA0xFD; регистр управления ЦАП
DAC0L DATA0xF9; младший регистр данных ЦАП содержат
DAC0H DATA0xFA; старший регистр данных ЦАП содержат
PLLCONDATA0D7H; регистр управления частотой контроллера
TIMECONDATA0A1H; адрес счетчика временных интервалов
T3FD DATA0x9D; регистры настройки Таймера 3
T3CON DATA0x9E; регистр управления таймером 3
ORG0000h; начало области, в которой будет располагаться код
JMPSTART; переход на инициализацию системы
ORG0023H; вектор прерывания от последовательного порта (UART)
JMPPOSL_PORT; переход на подпрограмму обработки прерывания
START:
MOVPLLCON,#3; настраиваем частоту ядра
MOVTMOD,#00H; T/C0 -таймер, режим0
MOVT3CON,#83H; устанавливаем скорость
MOVT3FD,#2DH; передачи - 9600 бод
MOVSCON,#50H; настройка последовательного порта; 0101 0000 (01 - 8-битный режим, 01 - режим 0, прием разрешен, 00 - биты используемые в режимах 1 и 2, 0 - флаг передачи; последов. порта, устанавливается; аппаратно после передачи 8-го бита, д.б. сброшен программно, 0 - флаг приема; последов порта, установливается аппаратно после приема 8-го бита, д.б. сброшен; программно)
MOVIE,#00010000B; разрешение прерывания от UART
SETBEA; разрешение прерываний
MAIN:; основная программа
CLRF0;
MOVR3,#0;
SCAN:; сканирование и проверка регистра R3;
K0:
CJNER3, #2,K1; если R3=2, то
CALLDAC_ADC; перейти на подпрограмму ЦАП-АЦП,
MOVR3,#0; затем записать в R3 0; иначе перейти на метку К1
K1:
CJNER3,#1, SCAN; если R3=1, то дальше сканировать клавиши 1,2 и 3, в портивном случае перейти на метку SCAN;
MOV R5,#0FEH;
MOV R7,#00H; нам нужен 0-й байт 8-й страницы 08"00"00"Н
MOV R6,#00H; 08"00"00
CALLWRITE;
CALLCHECK123;
CJNE A,#00H,K2; если клавиша 1 не нажата, сканировать клавишу 2
CALLWAIT_CHECK1; проверка на "залипание" клавиши 1
MOVSBUF,#01111000b; записываем в буфер значение символа;"x", бит TI устанавливается в 1,; инициируя прерывание по посл. порту
CALL DELAY; задержка
K2:; проверка нажатия клавиши 2
MOVR5,#0FDH;
MOV R7,#00H; нам нужен 0-й байт 8-й страницы 08"00"00"Н
MOV R6,#00H; 08"00"00
CALLWRITE;
CALLCHECK123;
CJNE A,#00H,K3; если клавиша 2 не нажата, сканировать клавишу 3
CALLWAIT_CHECK2; проверка на "залипание" клавиши 2
MOVSBUF,#01111001b; записываем в буфер значение символа; "y", бит TI устанавливается в 1,; инициируя прерывание по посл. порту
CALL DELAY; задержка
K3:; проверка нажатия клавиши 3
MOVR5,#0FBH;
MOV R7,#00H; нам нужен 0-й байт 8-й страницы 08"00"00"Н
MOV R6,#00H; 08"00"00
CALLWRITE;
CALLCHECK123;
CJNE A,#00H,SCAN; если клавиша 3 не нажата, перейти на; метку SCAN
CALLWAIT_CHECK3; проверка на "залипание" клавиши 2
MOVSBUF,#01111010b; записываем в буфер значение символа; "z", бит TI устанавливается в 1,; инициируя прерывание по посл. порту
CALLDELAY; задержка
JMP SCAN; переход на метку SCAN
CHECK123:; функция определения, нажата ли клавиша (1,2 или 3)
CALL READ; читаем байт по адресу 080000Н
ANLA,#10H
RET
WAIT_CHECK1:
CALL READ;
CJNE A,#0FEH,WAIT_CHECK1; ждать, если клавиша 1 зажата
RET
WAIT_CHECK2:
CALL READ;
CJNE A,#0FDH,WAIT_CHECK2; ждать, если клавиша 2 зажата
RET
WAIT_CHECK3:
CALL READ;
CJNE A,#0FBH,WAIT_CHECK3; ждать, если клавиша 3 зажата
RET
BUZZ:; Для управления динамиком в процедуре использованы таймер и регистр ПЛИС ENA (адрес;080004h).;2-4 биты регистр ENA управляют величиной напряжения на динамике, т.е. позволяют; задавать громкость звука. ;Для формирования звука генерируются прямоугольные импульсы с заданным периодом.
MOVPLLCON,#5;
MOVR1,#255; задаем продолжительность сигнала
MOVR2,#5;
AGAIN:
CLRTR0; выключаем таймер
MOVTH0,#00H;инициализация таймера
MOVTL0,#00H;
SETBTR0; включаем таймер
MOVR5,#010H; записываемое число в регистр DPTR,
;соответствует высокому уровню напряжения
MOVR7,#04H; нам нужен 4-й байт 8-й страницы 0800"04"Н
MOVR6,#00H; 08"00"04
REP1:
CALLWRITE; включаем сигнал
JNBTF0,REP1; удерживаем значение в течение полупериода
CLRTR0; выключаем таймер
MOVTH0,#00H; инициализация таймера
MOVTL0,#00H;
SETBTR0; включаем таймер
MOVR5,#08H; записываемое число в регистр DPTR,; соответствует низкому уровню напряжения
MOVR7,#04H; нам нужен 4-й байт 8-й страницы 08"00"04"Н
MOVR6,#00H; 08"00"04
REP2:
CALLWRITE; Выключаем сигнал, 0-е напряжение
JNBTF0,REP2; удерживаем значение в течение полупериода
CLRTR0; выключаем таймер
DJNZR1,AGAIN;
DJNZR2,AGAIN;
MOVPLLCON,#3;
RET;
LCD_Putch:; вывод символа на дисплей, код которого
;передается через регистр R5
MOVR7,#01H; DATA_IND ( 080001H)
MOVR6,#00H;
CALLWRITE; устанавливаем данные на шине данных ЖКИ
MOVR5,#05H; 0-й бит C_IND отвечает за строб, 1-й бит -
;запись/чтение , 2-й бит за данные/команды, 05H=0000 0101B - запись данных и;установка строба
CALLSTROBE; строб
RET;
STROBE:; подача сигнала Е интерфеса ПЛИС <-> ЖКИ на; время не менее 500 нс, одновременно подается; сигнал R/W=0 запись, RS=1 - данные
MOVR7,#06H; C_IND ( 080006H)
MOVR6,#00H;
CALLWRITE; установка строба
MOVR5,#0FEH
MOVR7,#06H; C_IND ( 080006H)
MOVR6,#00H;
CALLWRITE; сброс строба
CALLDELAY; задержка на время исполнения команды
RET;
DELAY:; процедура задержки
MOVR0,#100;
L1:
MOVR1,#100;
L2:
DJNZR1,L2;
DJNZR0,L1;
RET;
CLEAR:; очистка дисплея
MOVR5,#01H;
MOVR7,#01H; DATA_IND ( 080001H)
MOVR6,#00H;
CALLWRITE; устанавливаем данные на шине данных ЖКИ
MOVR5,#01H; команда очистки дисплея
CALLSTROBE; строб
MOVR7,#07H; нам нужен 7-й байт 8-й страницы 0800"07"Н
MOVR6,#00H; 08"00"07
MOVR5,#00000000B; инициализация светодиодов через один
CALLWRITE;
CLRF0;
RET;
POSL_PORT:; наступило прерывание, бит TI или RI равен 1
JBRI,WAIT_IN; если бит RI - принимаем данные
JBTI,WAIT_OUT; если бит TI - пересылаем данные
WAIT_IN:
CLRRI; сбрасываем флаг
MOVR5,SBUF; записываем в буфер значение R5
CJNER5,#61H,E1; если пришел символ a, то
MOVR3,#1; записать в R3 1
JMPE; переход на метку Е
E1:
CJNER5,#70H,E2; если пришел символ р, то
MOVR3,#2; записать в R3 2
JMPE; переход на метку Е
E2:
CJNER5,#73H,E3; если пришел символ s, то
CALLCLEAR; очистить дисплей и погасить светодиоды
JMPE; переход на метку Е
E3:; если не пришел ни символ a, ни p, ни s, то
MOVA,R5; это означает, что последовательно начали передаваться
MOVR4,A; значения, составляющие разность между текущим и заданным значениями деформаций
JBF0,E3a; если бит F0=0, тогда однократный
CALLSTOP; вывод информации: "Деформация Превышение: %"
E3a:
SETBF0;
CALLLCD_NA; вывод символов, определяющих отклонение от; заданной деформации
E:
RETI;
WAIT_OUT:; подпрограмма пересылки значения в послед. порт
CLR TI;
RETI;
DAC_ADC:
CALLDELAY;
MOVDACCON,#01101101B; настройка регистра ЦАП; 0-12 битный режим,; 11-бит выбора диапазона, 0-Vdd(в); 01-выход ЦАП1=0 в, выход ЦАП0-; соответствует коду; 1-выходы ЦАПов изменяются сразу, как; только данные попадают в регистры; 01-ЦАП1 выключен, ЦАП0 включен
MOVADCCON1,#10101100B;10-дежурный режим, если не выполняется; преобразование; 10-коэф. деления тактовой частоты на 4; 11-число тактов задержки=4; 0-Бит запуска преобразования от Таймера 2; 0-бит разрешения внешнего запуска АЦП
MOVDAC0H,#00000011B;переслать значение в старший байт ЦАП
MOVDAC0L,#10000100B;переслать значение в мл. байт; (т.е. 1.1/5*4095 = 909, т.е. 00000011 10000100)
MOVADCCON2,#00010000B;SCONV=1-Бит однократного преобразования; После того, как цикл завершился, бит; автоматически сбрасывается в 0
ADC_WAIT:
MOVA,ADCCON3;
JBACC.7,ADC_WAIT;Флаг занятости ЦАП (только для чтения).; Устанавливается аппаратно на; время цикла преобразования или; калибровки. Автоматически сбрасывается; ядром в конце преобразования или; калибровки.
MOV A, ADCDATAH; записать данные из старшего регистра АЦП в А
ANL A,#00001111B;стереть код канала АЦП, хранящегося; в старшем байте
MOV SBUF, A; переслать значение
CALL DELAY; задержка
MOV A,ADCDATAL; записать данные из младшего регистра АЦП в А
MOV SBUF, A; переслать значение
CALL DELAY; задержка
RET;
STOP:; подпрограмма окончания процесса
MOV R5,#11100000B; Д
CALLLCD_Putch;
MOV R5,#01100101B; е
CALLLCD_Putch;
MOV R5,#11100100B; ф
CALLLCD_Putch;
MOV R5,#01101111B; о
CALLLCD_Putch;
MOV R5,#01110000B; р
CALL LCD_Putch;
MOV R5,#10111100B; м
CALLLCD_Putch;
MOV R5,#01100001B; а
CALLLCD_Putch;
MOVR5,#11100101B; ц
CALLLCD_Putch;
MOVR5,#10111000B; и
CALLLCD_Putch;
MOVR5,#11000111B; я
CALLLCD_Putch;
MOVR5,#0C0H; сдвиг курсора на следующую строку
MOVR7,#01H; DATA_IND ( 080001H)
MOVR6,#00H;
CALLWRITE; устанавливаем данные на шине данных ЖКИ
MOVR5,#01H; команда очистки дисплея
CALLSTROBE; строб
MOVR5,#10101000B; П
CALLLCD_Putch;
MOVR5,#01110000B; р
CALLLCD_Putch;
MOVR5,#01100101B; е
CALLLCD_Putch;
MOVR5,#10110011B; в
CALLLCD_Putch;
MOVR5,#11000011B; ы
CALLLCD_Putch;
MOVR5,#11000001B; ш
CALLLCD_Putch;
MOVR5,#01100101B; е
CALLLCD_Putch;
MOVR5,#10111101B; н
CALLLCD_Putch;
MOVR5,#10111000B; и
CALLLCD_Putch;
MOVR5,#01100101B; е
CALLLCD_Putch;
MOVR5,#00111010B;:
CALLLCD_Putch;
MOVR5,#0CFH;; установка крайнего правого положения во второй строке ЖКИ
MOVR7,#01H; DATA_IND ( 080001H)
MOVR6,#00H;
CALLWRITE; устанавливаем данные на шине данных ЖКИ
MOVR5,#01H; команда очистки дисплея
CALLSTROBE; строб
MOVR5,#00100101B; %
CALLLCD_Putch;
MOVR5,#0CBH;установка положения после : во второй строке ЖКИ
MOVR7,#01H; DATA_IND ( 080001H)
MOVR6,#00H;
CALLWRITE; устанавливаем данные на шине данных ЖКИ
MOVR5,#01H; команда очистки дисплея
CALLSTROBE; строб
MOVR7,#07H; нам нужен 7-й байт 8-й страницы 0800"07"Н
MOVR6,#00H; 08"00"07
MOVR5,#10101010B; инициализация светодиодов через один
CALLWRITE;
CALL BUZZ; звуковой сигнал
RET;
LCD_NA:; вывод символов на дисплей, составляющий отклонение текущей деформации от заданного значения
MOVR7,#01H; DATA_IND ( 080001H)
MOVR6,#00H;
MOVA,R4;
MOVR5,A;
CALLWRITE; устанавливаем данные на шине данных ЖКИ
MOVR5,#05H; 0-й бит C_IND отвечает за строб, 1-й бит -; запись/чтение , 2-й бит за данные/команды,; 05H=0000 0101B - запись данных и;; установка строба
CALLSTROBE; строб
RET;
WRITE:; запись значения по адресу передаваемому в;R6 и R7, записываемое значение находится в R5
MOV DPL,R7; загружаем адрес в младший байт DPTR
MOV DPH,R6; загружаем адрес в старший байт DPTR
MOV R7,DPP; временно сохраним содержимое dpp в R7
MOV DPP,#08H; переключаемся на 8-ю страницу - 080007Н
MOV A,R5;
MOVX@DPTR,A; записываем значение
MOV DPP,R7; возвращаем страницу
RET;
READ:; чтение значения по адресу передаваемому в; регистрах R6 и R7, прочитанное значение записываем в А
MOV DPL,R7; загружаем адрес в младший байт DPTR
MOV DPH,R6; загружаем адрес в старший байт DPTR
MOV R7,DPP; временно сохраним содержимое dpp в R7
MOV DPP,#08H; переключаемся на 8-ю страницу - 080007Н
MOVX A,@DPTR; пересылаем в аккумулятор значение ячейки
MOV DPP,R7; возвращаем страницу
RET;
END.