Разработка программы на языке ассемблер
Прежде чем приступить к написанию программы необходимо учесть спецификацию ПЗУ микроконтроллера. Организация ПЗУ изображена на рисунке 5.1
Рисунок 5.1 – Организация ПЗУ PIC16C71
Из рисунка видно, что начало программы пользователя может быть расположено ниже адреса 0004h. Адрес 0000h – вектор сброса, 0004h – вектор прерывания. По этим адресам перед началом программирования, как правило, прописывают безусловный переход на программу пользователя и безусловный переход на программу обработки прерывания соответственно. Так как в случае нашей системы устройство, осуществляющее запрос прерывания, одно, то по адресу 0004h можно прописывать начало программы обработки прерывания.
Также при программировании обязательно нужно учесть спецификацию банков ОЗУ. Структура ОЗУ изображена на
рисунке 5. При обращении к регистрам ОЗУ каждый раз необходимо программно переключаться между банками ОЗУ, в зависимости от того в каком банке находится регистр. Ассемблер, поставляемый производителем, позволяет вначале всем регистрам присвоить вместо адреса определенное имя. Это удобно для составления программы.
Рисунок 5.2 – Организация ОЗУ PIC16C711
Сначала напишем программу обработки прерывания. Занесем программу в таблицу - 1 с адресами ПЗУ и комментариями.
Таблица 5.1
Адрес | Метка | Мнемонический код | Комментарии | Циклы |
ORG 0x004 | Директива | |||
0004h | MOVWF W_TEMP | Сохранение содержимого W в W_TEMP | ||
0005h | MOVF STATUS, 0 | Пересылка содержимого STATUS в W | ||
0006h | MOVWF STATUS_TEMP | Сохранение W в STATUS _TEMP | ||
Продолжение таблицы 5.1 | ||||
0007h | BCF STATUS, RP0 | Выбор банка 0 | ||
0008h | MOVF ADRES, 0 | Пересылка результата АЦП в W | ||
0009h | MOVWF UM | Пересылка W в UM | ||
000Ah | MOVF STATUS_TEMP, 0 | Пересылка STATUS_TEMP в W | ||
000Bh | MOVWF STATUS | Пересылка W в STATUS | ||
000Ch | MOVF W_TEMP, 0 | Пересылка W_TEMP в W | ||
000Dh | RETFIE | Возврат прерывания |
Программу, реализующую математическую модель фильтра начнем с адреса 000Eh и разместим в таблицу 5, 2.
Таблица 5.2
Адрес | Метка | Мнемонический код | Комментарии | Циклы |
ORG 0x00E | Директива | |||
000Eh | MOVLW 0xFF | Пересылка 0xFF в аккумулятор | ||
000Fh | BSF STATUS, RP0 | Выбор банка 1 | ||
0010h | MOVWF TRISA | Порт А – Вход | ||
0011h | CLRF TRISB | Порт В – Выход | ||
0012h | MOVLW 0x18 | Организация счетчика СOUNT | ||
0013h | BCF STATUS, RP0 | Выбор банка 0 | ||
0014h | MOVWF COUNT | Организация счетчика | ||
0015h | MOVLW 0x0C | Адрес начальной ячейки в ОЗУ | ||
0016h | MOVWF FSR | Пересылка адреса начальной ячейки в FSR | ||
0017h | M1: | CLRF INDF | Обнуление текущей ячейки памяти | |
0018h | INCF FSR, 1 | Адрес + 1 | ||
0019h | DECF COUNT | Счетчик – 1 | ||
001Ah | BTFSS STATUS, Z | Условный переход по 1 значению флага нулевого результата | 1(2) | |
001Bh | GOTO M1 | |||
001Ch | M2: | BSF STATUS,RP0 | Выбор банка 1 | |
001Dh | CLRF ADCON1 | RA0-RA3 Входы АЦП | ||
001Eh | MOVLW 0xC1 | |||
001Fh | BCF STATUS,RP0 | Выбор банка 0 | ||
0020h | MOVWF ADCON0 | АЦП включен, работает канал0 (RA0), частота 32Tosc. | ||
0021h | BSF INTCON ADIE | Разрешить прерывание АЦП | ||
0022h | BSF INTCON GIE | Разрешить глобальное прерывание | ||
0023h | BSF ADCON0, GO | Запустить АЦП | ||
0024h | BCF STATUS, C | Очистка триггера переноса | ||
0025h | RRF UM1, 0 | Циклический сдвиг вправо через триггер переноса | ||
0026h | BCF STATUS, C | Очистка триггера переноса | ||
0027h | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
0028h | MOVWF A11UM1 | W® A11UM1 | ||
0029h | BCF STATUS, C | Очистка триггера переноса | ||
002Ah | RRF YN1, 0 | Циклический сдвиг вправо через триггер переноса | ||
002Bh | BCF STATUS, C | Очистка триггера переноса | ||
002Ch | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
002Dh | BCF STATUS, C | Очистка триггера переноса | ||
002Eh | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
Продолжение таблицы 5.2 | ||||
002Fh | BCF STATUS, C | |||
0030h | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
0031h | MOVWF B11YN1 | W® B11YN1 | ||
0032h | BCF STATUS, C | Очистка триггера переноса | ||
0033h | RRF YN1, 0 | Циклический сдвиг вправо через триггер переноса | ||
0034h | ADDWF W, 0 | W=W+W | ||
0035h | ADDWF W, 0 | W=W+W | ||
0036h | ADDWF B11YN1 | W=W+ B11YN1 | ||
0037h | SUBWF A11UM1, 0 | W= A11UM1- W | ||
0038h | MOVWF YNN | W® YNN | ||
0039h | BCF STATUS, C | Очистка триггера переноса | ||
003Ah | RRF UM1, 0 | Циклический сдвиг вправо через триггер переноса | ||
003Bh | MOVWF A21UM1 | W® A21UM1 | ||
003Ch | BCF STATUS, C | Очистка триггера переноса | ||
003Dh | RRF YK1, 0 | Циклический сдвиг вправо через триггер переноса | ||
003Eh | BCF STATUS, C | Очистка триггера переноса | ||
003Fh | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
0040h | BCF STATUS, C | Очистка триггера переноса | ||
0041h | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
0042h | SUBWF A21UM1, 0 | W= A21UM1- W | ||
0043h | MOVWF YK | W® YK | ||
0044h | MOVF YN1, 0 | YN1®W | ||
0045h | ADDWF YK1 | W=W+ YK1 | ||
0046h | BCF STATUS, C | Очистка триггера переноса | ||
0047h | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
0048h | BCF STATUS, C | Очистка триггера переноса | ||
0049h | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
004Ah | BCF STATUS, C | Очистка триггера переноса | ||
004Bh | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
004Ch | BCF STATUS, C | Очистка триггера переноса | ||
004Dh | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
004Eh | MOVWF A31YN1YK1 | W® A31YN1YK1 | ||
004Fh | MOVF YN2, 0 | YN2®W | ||
0050h | ADDWF YK2 | W=W+ YK2 | ||
0051h | BCF STATUS, C | Очистка триггера переноса | ||
0052h | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
0053h | BCF STATUS, C | Очистка триггера переноса | ||
0054h | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
0055h | BCF STATUS, C | Очистка триггера переноса | ||
0056h | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
0057h | MOVWF A32YN2YK2 | W® A32YN2YK2 | ||
0058h | BCF STATUS, C | Очистка триггера переноса | ||
0059h | RRF YL1, 0 | Циклический сдвиг вправо через триггер переноса | ||
Продолжение таблицы 5.2 | ||||
005Ah | ADDWF W, 0 | W=W+W | ||
005Bh | ADDWF W, 0 | W=W+W | ||
005Ch | SUBWF A32YN2YK2, 0 | W= A32YN2YK2- W | ||
005Dh | ADDWF A31YN1YK1 | W=W+ A31YN1YK1 | ||
005Eh | MOVWF YLL | W® YLL | ||
005Fh | BCF STATUS, C | Очистка триггера переноса | ||
0060h | NOP | Ничего не выполнять | ||
0061h | NOP | |||
0062h | NOP | |||
0063h | NOP | |||
0064h | NOP | |||
0065h | NOP | |||
0066h | NOP | |||
0067h | NOP | |||
0068h | NOP | |||
0069h | NOP | |||
006Ah | NOP | |||
006Bh | NOP | |||
006Ch | NOP | |||
006Dh | NOP | |||
006Eh | NOP | |||
006Fh | NOP | |||
0070h | NOP | |||
0071h | NOP | |||
0072h | NOP | |||
0073h | NOP | |||
0074h | MOVF YK1, 0 | YK1®W | ||
0075h | MOVWF YK2 | W® YK2 | ||
0076h | MOVF YK, 0 | YK ®W | ||
0077h | MOVWF YK1 | W® YK1 | ||
0078h | RRF UM, 0 | Циклический сдвиг вправо через триггер переноса | ||
0079h | ADDWF YNN | W=W+ YNN | ||
007Ah | MOVWF YN | W® YN | ||
007Bh | ADDWF YK | W=W+ YK | ||
007Ch | BCF STATUS, C | Очистка триггера переноса | ||
007Dh | RRF W, 0 | Циклический сдвиг вправо через триггер переноса | ||
007Eh | ADDWF W, 0 | W=W+W | ||
007Fh | ADDWF YLL | W=W+ YLL | ||
0080h | MOVWF YL | W® YL | ||
0081h | MOVWF PORTB | W® PORTB | ||
0082h | MOVF YN1, 0 | YN1®W | ||
0083h | MOVWF YN2 | W® YN2 | ||
0084h | MOVF YN, 0 | YN ®W | ||
0085h | MOVWF YN1 | W® YN1 | ||
0086h | MOVF YL, 0 | YL ®W | ||
0087h | MOVWF YL1 | W® YL1 | ||
0088h | MOVF UM, 0 | UM ®W | ||
0089h | MOVWF UM1 | W® UM1 | ||
008Ah | GOTO M2 | Безусловный переход на метку | ||
END | ||||
Всего вместе с программой обработки прерывания |
Время выполнения программы 56 мкс.
Операции NOP предназначены для синхронизации работы АЦП с программой. Также для этой цели было добавлено 4 команды перед операциями над текущим значением отсчета. В составленном алгоритме данные коррекции небыли предусмотрены. Время выполнения программы, реализующей цифровой фильтр, равно 49 мкс. Интервал дискретизации сигнала равен 24,6 мкс, соответственно частота дискретизации равна 41000Гц. В программе используются два перехода: один для обнуления ОЗУ, другой – для возврата программы на место запуска АЦП. При использовании более современных PIC процессоров возможно исключение операций NOP.