Да простят меня модераторы Вот мой исходник; ;LIST P=16F84, F=INHX8M
#include <p16F630.inc> ; processor specific variable definitions list p=16f630 ; list directive to define processor errorlevel -302 ; suppress message 302 from list file __CONFIG _CP_OFF & _CPD_OFF & _BODEN & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC
;Переменные
TIMERL EQU 0x20 ;Регистры для хранения TIMERM EQU 0x21 ;показаний таймера TIMERH EQU 0x22 ;//зарезервирован
SPEEDL EQU 0x23 ;Регистры для хранения SPEEDH EQU 0x24 ;вычисленного значения скорости
W_TEMP EQU 0x25 ;Состояние регистра W STATUS_TEMP EQU 0x26 ;Состояние регистра STATUS
;Переменные для процедуры деления 24-х разрядного числа на 16-ти разрядное ;Входные и выходные данные: AARGBL EQU 0x27 ;Делимое и частное AARGBM EQU 0x28 AARGBH EQU 0x29
BARGBL EQU 0x2A ;Делитель BARGBH EQU 0x2B
;Временные переменные: LOOPCOUNT EQU 0x2C ;Счётчик REMBL EQU 0x2D ;Остаток REMBH EQU 0x2E
;Переменные для процедуры перевода 24-х разрядного двоичного числа в 24-х разрядное BCD ;Входные данные: ARGBINL EQU 0x2F ;Двоичное число ARGBINM EQU 0x30 ; ARGBINH EQU 0x31 ;
;Временные переменные: POPSCOUNT EQU 0x32 ;Счётчик "выталкиваний" W_TEMP_BCD EQU 0x33 ;Временное хранилище для W
;Выходные данные: RESBCDL EQU 0x34 ; BCD число RESBCDM1 EQU 0x35 ; RESBCDM2 EQU 0x36 ; RESBCDH EQU 0x37 ;
;Переменные для процедуры динамической индикации трёх чисел BCD формата ;Входные данные: DISPU EQU 0x38 ;единицы DISPT EQU 0x39 ;десятки DISPH EQU 0x3A ;сотни
;Переменные для процедуры временной задержки ;Входные данные: CNT1 EQU 0x3B ;пропорция задержки (.11 = 1 секунда) ;Временные переменные: CNT2 EQU 0x3C CNT3 EQU 0x3D
;Переменные для процедуры записи в EEPROM WRADR EQU 0x3E ;Адрес для записи
;Переменные для процедуры записи результата в EEPROM ;Временные переменные SAVEDCNT EQU 0x3F ;Количество сохранённых в EEPROM записей
;Переменные для процедуры записи результата в EEPROM ; переменные CNTVALUE EQU 0x40 ;Текущее показание счётчика
;Переменные для процедуры передачи символа по протоколу RS232, ;Временные переменные: SBYTE EQU 0x41 ;Отправляемый байт POPSCNT EQU 0x42 ;Счётчик "выталкиваний" DELAYCNTR EQU 0x43 ;Счётчик для задержки
;Переменные для процедуры восстанавления из EEPROM значений таймера ;Временные переменные: TMPADR EQU 0x44 ;адрес в EEPROM
;Переменные флагов FLAGS0 EQU 0x5F ;Флаги в банке памяти 0 FLAGS1 EQU 0xDF ;Флаги в банке памяти 1
;Биты флагов GIEF EQU 0x00 ;флаг запрета GIE в процедуре записи в EEPROM (для FLAGS1)
;Константы
TICKS1MPSL EQU 0x20 ;Константа таймера = количество тиков таймера TICKS1MPSM EQU 0xA1 ;при прохождении базового расстояния (100 мм) со TICKS1MPSH EQU 0x07 ;скоростью 1 метр в секунду RESVALADR EQU 0x10 ;Начальный адрес хранения значений результатов в EEPROM RESCOUNT EQU 0x38 ;Количество результатов которое можно сохранить (56 значений)
;Адреса значений хранящихся в EEPROM RESCNTADR EQU 0x00 ;Количество сохранённых замеров ;RESVALADR EQU 0x01 ;Начальный адрес хранения значений результатов в EEPROM TICKS1ADRH EQU 0x02 ;Базовая константа - старший разряд TICKS1ADRM EQU 0x03 ;Базовая константа - средний разряд TICKS1ADRL EQU 0x04 ;Базовая константа - младший разряд CMCONADR EQU 0x05 ;Настройка регистра CMCON VRCONADR EQU 0x06 ;Настройка регистра VRCON TIMER1SETADR EQU 0x07 ;Настройки таймера TIMER1 DISPONDELAYADR EQU 0x08 ;Коэффициент задержки для свечения индикатора DISPOFFDELAYADR EQU 0x09 ;Коэффициент задержки для погасания индикатора
ORG 0 ; Начало программы GOTO init ORG 4
;************************************************************************************** ;Обработчик прерываний
push ;Сохранение состояния перед входом в обработку прерывания BCF INTCON, GIE ;Глобальный запрет прерываний BCF INTCON, PEIE ;Запрет прерываний от периферийных устройств BTFSS STATUS, RP0 ; В банке 0? GOTO RP0clear ; Да BCF STATUS, RP0 ; Нет MOVWF W_TEMP ; Сохранить регистр W SWAPF STATUS, W ; Обменять полубайты в регистре STATUS MOVWF STATUS_TEMP ; и записать в STATUS_TEMP BSF STATUS_TEMP, 5 ; Установить бит RP0 в сохраненном значении STATUS GOTO ISR_Code ; Сохранение регистров завершено RP0clear MOVWF W_TEMP ; Сохранить регистр W SWAPF STATUS, W ; Обменять полубайты в регистре STATUS MOVWF STATUS_TEMP ; и записать в STATUS_TEMP
ISR_Code: ;Процедура обработки прерывания BTFSC INTCON, RAIF ;Проверяем прерывание от кнопки GOTO btn1int ;Обрабатываем прерывание от кнопки BTFSC PIR1, CMIF ;Проверяем прерывание от компаратора GOTO cmpint ;Обрабатываем прерывание от компаратора BTFSC PIR1, TMR1IF ;Проверяем прерывание от TMR1 GOTO tmr1int ;Обрабатываем прерывание от TMR1 GOTO pop
pop ;Восстановление состояния после обработки прерывания SWAPF STATUS_TEMP, W ; Восстановить значение STATUS MOVWF STATUS ; BTFSS STATUS, RP0 ; В банке 0? GOTO restore_WREG ; Нет BCF STATUS, RP0 ; Да SWAPF W_TEMP, F ; Восстановить значение регистра W SWAPF W_TEMP, W ; BSF STATUS, RP0 ; Восстановить банк 1 GOTO returnfie restore_WREG SWAPF W_TEMP, F ; Восстановить значение регистра W SWAPF W_TEMP, W ; Восстановление регистров завершено returnfie BSF INTCON, PEIE ; Разрешаем прерывание от периферийных устройств BSF INTCON, GIE ; Глобальное разрешение прерываний RETFIE
;************************************************************************************** init BSF STATUS, RP0 ;Выбираем банк памяти 1 MOVLW b'11111011' ;RA2-выход, остальные входы MOVWF TRISA ;Инициализируем порт A MOVLW b'11000000' ;RC0-RC5 - выходы MOVWF TRISC ;Инициализируем порт C
MOVLW TIMER1SETADR ;Получаем из EEPROM настройки CALL memread ;таймера TIMER1 BCF STATUS, RP0 ;Выбираем банк памяти 0 MOVWF T1CON ;Настраиваем таймер TIMER1
CLRF PORTC ;Инициализируем PORTC BSF PORTC, 05 ;Подаем сигналы на закрытие BSF PORTC, 04 ;всех транзисторов BSF PORTA, 02 ; NOP
BTFSS PORTA, 03 ;Проверяем состояние нажатости кнопки CALL clearresult ;Если нажата - сбрасываем счётчик записей
CALL sendtoterminal ;Отправляем данные в терминал BCF STATUS, RP0 ;Выбираем банк памяти 0
CLRF CNTVALUE ;Инициализируем счётчик отображённых значений
MOVLW 0x00 ;После загрузки высвечиваем нули MOVWF DISPU ; MOVWF DISPT ; MOVWF DISPH ;
CALL cmpset ;Настройка компаратора CALL intset ;Настраиваем прерывания
GOTO display ;Запускаем циклическую процедуру индикации ;и ждём прерываний
;************************************************************************************** intset: ;Процедура настройки прерываний BCF STATUS, RP0 ;Выбираем банк памяти 0 CLRF PIR1 ;Инициализируем PIR1 CLRF INTCON
BSF STATUS, RP0 ;Выбираем банк памяти 1 CLRF PIE1 ;Инициализируем PIE1 BSF PIE1, CMIE ;Разрешаем прерывание от компаратора BSF IOCA, 3 ;Разрешаем прерывание от кнопки BCF STATUS, RP0 ;Выбираем банк памяти 0 BSF INTCON, RAIE ;Разрешаем прерывание от порта A BSF INTCON, PEIE ;Разрешаем прерывание от периферийных устройств BSF INTCON, GIE ;Глобальное разрешение прерываний RETURN
;************************************************************************************** cmpset: ;Процедура настройки компаратора MOVLW CMCONADR ;Получаем из EEPROM настройки CALL memread ;регистра CMCON BCF STATUS, RP0 ;Выбираем банк памяти 0 ;MOVLW b'00010110' ;Настройка компаратора Инвертирован, подключен к CIN-, Схема подключения 110 MOVWF CMCON ;Настраиваем CMCON
MOVLW VRCONADR ;Получаем из EEPROM настройки CALL memread ;регистра VRCON BSF STATUS, RP0 ;Выбираем банк памяти 1 ;MOVLW b'10001111' ;опорное напряжение MOVWF VRCON ;Настраиваем VRCON
BCF STATUS, RP0 ;Выбираем банк памяти 0 BCF CMCON, CIS ;Подключаем компаратор к CIN- (вывод 12) BTFSS CMCON, COUT ;Проверяем отсутствие сработки компаратора. GOTO pin13check MOVLW 0x0A ;Высвечиваем '[' MOVWF DISPH ; BSF STATUS, RP0 ;Выбираем банк памяти 1 BCF PIE1, CMIE ;Запрещаем прерывание от компаратора BCF STATUS, RP0 ;Выбираем банк памяти 0 pin13check BSF CMCON, CIS ;Подключаем компаратор к CIN+ (вывод 13) BTFSS CMCON, COUT ;Проверяем отсутствие сработки компаратора. GOTO checkfinish MOVLW 0x0B ;Высвечиваем ']' MOVWF DISPU ; BSF STATUS, RP0 ;Выбираем банк памяти 1 BCF PIE1, CMIE ;Запрещаем прерывание от компаратора BCF STATUS, RP0 ;Выбираем банк памяти 0
checkfinish BCF CMCON, CIS ;Подключаем компаратор к CIN- (вывод 12) RETURN
;************************************************************************************** btn1int: ;Процедура обработки прерывания от кнопки BCF STATUS, RP0 ;Банк 0
BSF PORTC, 4 ;Гасим индикаторы, чтобы не было BSF PORTC, 5 ;"зависших" цифр BSF PORTA, 2 ;
MOVLW RESCNTADR ;Читаем из EEPROM значение количества CALL memread ;запомненых измерений MOVWF SAVEDCNT ;И сохраняем его в SAVEDCNT ADDLW 0x00 ;Проверяем на отсутствие записей BTFSC STATUS, Z ; GOTO btnloop ;Если нет записей - никаких вычислений не делаем
MOVFW CNTVALUE ;Проверяем на достижение максимума SUBWF SAVEDCNT, W ;Вычитаем значение счётчика из количества сохранённых BTFSC STATUS, Z ; CLRF CNTVALUE ;Если переполнили - сбрасываем счётчик на начало INCF CNTVALUE, F ;Увеличиваем значение счётчика DECF CNTVALUE, W ;Уменьшаем на 1 (поскольку нумерация идёт с нуля) ;и помещаем вычисленное значение в W CALL gettmrval ;Получаем значения таймера CALL getspeed ;По полученным показаниям таймера вычисляем значение скорости
btnloop BTFSC PORTA, 3 ;Проверяем состояние кнопки GOTO btnfin ; MOVLW 0x01 ;Устанавливаем задержку примерно 100мс CALL delay ;Ждём, пока кнопка не будет отпущена GOTO btnloop ; btnfin MOVFW PORTA ;Перечитываем PORTA, чтобы обновить значение BCF INTCON, RAIF ;Сбрасываем флаг прерывания от кнопки BCF CMCON, COUT ;Сбрасываем компаратор BCF PIR1, CMIF ;Сбрасываем флаг прерывания от компаратора GOTO pop
;************************************************************************************** gettmrval: ;Восстанавливает из EEPROM значения таймера для ;измерения с номером помещённым в W ;Временная переменная TMPADR - адрес в EEPROM BCF STATUS, RP0 ;Банк 0 MOVWF TMPADR ;Сохраняем номер в TMPADR BCF STATUS, C ;Очищаем флаг переноса RLF TMPADR, F ;Умножаем на 2, так как каждое значение занимает 2 байта MOVFW TMPADR ;Помещаем значение в W ADDLW RESVALADR ;И добавляем начальный адрес MOVWF TMPADR ;Сохраняем для чтения следующего байта значения CALL memread ;Читаем младший байт значения MOVWF TIMERL ;Сохраняем INCF TMPADR, W ;Вычисляем адрес старшего байта CALL memread ;Читаем старший байт значения MOVWF TIMERM ;Сохраняем RETURN
;************************************************************************************** tmr1int: ;Процедура обработки прерывания TMR1 BSF STATUS, RP0 ;Банк1 BCF PIE1, TMR1IE ;Запрещаем прерывание от TMR1 BCF STATUS, RP0 ;Банк0 BCF PIR1, TMR1IF ;Сбрасываем флаг прерывания от TMR1 BCF CMCON, CIS ;Подключаем компаратор к CIN- (вывод 12) MOVLW 0x0C ;Высвечиваем uuu MOVWF DISPU MOVWF DISPT MOVWF DISPH MOVLW 0x08 ;Устанавливаем величину задержки CALL delay ;Сделаем паузу перед высвечиванием GOTO pop
;************************************************************************************** cmpint: ;Процедура обработки прерывания компаратора BTFSC CMCON, CIS ;Проверяем к какому выводу подключен компаратор GOTO cinplus ;Подключен к CIN+ (вывод 13) ;Компаратор подключен к CIN- (вывод 12) CLRF TMR1L ;Инициализируем таймер CLRF TMR1H ; BSF CMCON, CIS ;Подключаем компаратор к CIN+ (вывод 13)
MOVLW 0x0F ;Гасим индикатор MOVWF DISPU MOVWF DISPT MOVWF DISPH BCF PIR1, TMR1IF ;Сбрасываем флаг прерывания от TMR1 BSF STATUS, RP0 ;Банк1 BSF PIE1, TMR1IE ;Разрешаем прерывание от TMR1 BCF STATUS, RP0 ;Банк0
GOTO fincmpint
cinplus ;Если компаратор подключен к CIN+ (вывод 13) BSF STATUS, RP0 ;Банк1 BCF PIE1, TMR1IE ;Запрещаем прерывание от TMR1 BCF STATUS, RP0 ;Банк0 MOVF TMR1H, W MOVWF TIMERM ;!!! TMR1H заносим в TIMERM (TIMERH зарезервирован) MOVF TMR1L, W MOVWF TIMERL BCF CMCON, CIS ;Подключаем компаратор к CIN- (вывод 12) MOVLW 0x03 ;Задержка примерно 300мс CALL delay ; CALL getspeed ;Вычисляем скорость CALL saveresult ;Запоминаем результаты в EEPROM
fincmpint CLRF CNTVALUE ;Очищаем значение счётчика перебранных показаний BCF CMCON, COUT ;Сбрасываем компаратор BCF PIR1, CMIF ;Сбрасываем флаг прерывания от компаратора GOTO pop ;Возвращаемся из обработки прерывания
;************************************************************************************** getspeed: ;Процедура расчёта значения скорости и вывода на индикатор BCF STATUS, RP0 ;Банк 0 MOVLW TICKS1ADRL ;Получаем значение базовой константы из EEPROM CALL memread ;и заносим его по разрядам в регистры MOVWF AARGBL ;для делимого MOVLW TICKS1ADRM ; CALL memread ; MOVWF AARGBM ; MOVLW TICKS1ADRH ; CALL memread ; MOVWF AARGBH ;
MOVFW TIMERL ;Заносим значение делителя MOVWF BARGBL ; MOVFW TIMERM ; MOVWF BARGBH ; CALL fxd2416u ;Вычисляем скорость
MOVFW AARGBL ;Поготавливаем данные для процедуры MOVWF ARGBINL ;конвертации в BCD формат MOVFW AARGBM ; MOVWF ARGBINM ; MOVFW AARGBH ; MOVWF ARGBINH ; CALL hex2bcd ;Конвертируем в BCD MOVFW RESBCDL ;Поготавливаем данные для процедуры динамической индикации ANDLW b'00001111' ;Оставляем младший полубайт MOVWF DISPU ;Заносим значение единиц SWAPF RESBCDL, W ;Меняем местами полубайты ANDLW b'00001111' ;Оставляем младший полубайт MOVWF DISPT ;Заносим значение десятков MOVFW RESBCDM1 ; ANDLW b'00001111' ;Оставляем младший полубайт MOVWF DISPH ;Заносим значение сотен RETURN ;Готово - можно отображать данные
;************************************************************************************** clearresult:;Сбрасывает значение счётчика записей BCF STATUS, RP0 ;Банк 0 MOVLW RESCNTADR ;В EEPROM по адресу в котором ;CALL memread ;хранится количество MOVWF WRADR ;запомненных результатов MOVLW 0x00 ;записываем 0 CALL memwrite RETURN ;************************************************************************************** saveresult: ;Записывает полученые результаты скорости в память ;Временная переменная SAVEADR - адрес в EEPROM по которому ;будет записан результат BCF STATUS, RP0 ;Банк 0 MOVLW RESCNTADR ;Читаем значение количества результатов CALL memread ; MOVWF SAVEDCNT ;Сохраняем
MOVFW SAVEDCNT ;Проверяем, чтобы количество записей SUBLW RESCOUNT ;не превысило максимальное BTFSC STATUS, Z ; CLRF SAVEDCNT ;Достигли максимума, обнуляем счётчик INCF SAVEDCNT, F ;Увеличиваем количество сохранённых записей
MOVLW RESCNTADR ;Сохраняем новое количество в EEPROM MOVWF WRADR ;Адрес для записи MOVFW SAVEDCNT ;Записываемое значение CALL memwrite ;
DECF SAVEDCNT, F ;Уменьшаем на 1 так как адресация идёт от нуля BCF STATUS, C ;Очищаем бит переноса RLF SAVEDCNT, W ;Умножаем на 2, так как каждый занимает 2 байта ;перенос не проверяем, потому, что заведомо меньше ADDLW RESVALADR ;И добавляем начальный адрес MOVWF WRADR ;Указываем процедуре в какую ячейку производить запись MOVFW TIMERL ;Записываем младший байт CALL memwrite ; INCF WRADR, F ;Наращиваем адрес MOVFW TIMERM ;Записываем старший байт CALL memwrite ;
RETURN
;************************************************************************************** memread: ;Чтение данных из EEPROM ;Читает по адресу помещённому в W ;Прочитанное значение помещаем в W BSF STATUS, RP0 ;Банк 1 MOVWF EEADR BSF EECON1, RD MOVFW EEDATA BCF STATUS, RP0 ;Банк 0 RETURN
;************************************************************************************** memwrite: ;Запись данных в EEPROM ;Записывает значение помещённое в W ;по адресу помещённому в WRADR BSF STATUS, RP0 ;Банк 1 MOVWF EEDATA ;Подготавливаем записываемый байт BCF STATUS, RP0 ;Банк 0 MOVFW WRADR ;Подготавливаем адрес для записи BSF STATUS, RP0 ;Банк 1 MOVWF EEADR ;Указываем адрес по которому проводится запись
BSF EECON1, WREN ;Разрешаем запись
BCF FLAGS1, GIEF ;Инициализируем признак запрета прерываний BTFSC INTCON, GIE ;Проверяем запрет прерываний BSF FLAGS1, GIEF ;Устанавливаем признак что прерывания не были запрещены BCF INTCON, GIE ;Запрещаем прерывания MOVLW 0x55 ;Специальная последовательность MOVWF EECON2 ;действий, для разрешения MOVLW 0xAA ;записи в EEPROM MOVWF EECON2 ; BSF EECON1, WR ;Начинаем запись BTFSC EECON1, WR ;Проверяем закончилась ли запись GOTO $ - 1 ; BTFSC FLAGS1, GIEF ;Проверяем флаг запрета прерываний BSF INTCON, GIE ;Разрешаем прерывания BCF STATUS, RP0 ;Банк 0 RETURN
;************************************************************************************** display: ;Процедура динамической индикации трёх чисел BCD формата ;Входные данные: ;DISPU - единицы ;DISPT - десятки ;DISPH - сотни
BSF STATUS, RP0 ;Выбираем банк памяти 1 BCF PIE1, CMIE ;Запрещаем прерывание от компаратора BSF PORTC, 5 ;гасим выходные сигналы (наверное можно и не делать) BSF PORTC, 4 ; BSF PORTA, 2 ; MOVLW b'11111011' ; BCF TRISA, 2 ;Конфигурируем порт A, RA2 - выход MOVLW b'11000000' ; MOVWF TRISC ;Конфигурируем порт C BCF STATUS, RP0 ;Банк 0
MOVLW b'00001111' ;очищаем верхние полубайты (на всякий случай) ANDWF DISPU, F ;у единиц MOVLW b'00001111' ;очищаем верхние полубайты ANDWF DISPT, F ;у десятков MOVLW b'00001111' ;очищаем верхние полубайты ANDWF DISPH, F ;у сотен disploop MOVFW DISPU ;загружаем разряд единиц IORLW b'00010000' ; MOVWF PORTC ;и включаем его MOVLW 0x08 ;Коэффициент задержки для свечения CALL dispdelay ;пауза BSF PORTC, 5 ;выключаем разряд единиц MOVLW 0x06 ;Коэффициент задержки для погасания CALL dispdelay ;пауза MOVFW DISPT ;загружаем разряд десятков IORLW b'00100000' ; MOVWF PORTC ;и включаем его MOVLW 0x08 ;Коэффициент задержки для свечения CALL dispdelay ;пауза BSF PORTC, 4 ;выключаем разряд десятков MOVLW 0x06 ;Коэффициент задержки для погасания CALL dispdelay ;пауза
MOVFW DISPH ;загружаем разряд сотен IORLW b'00110000' ; MOVWF PORTC ; BCF PORTA, 2 ;включаем разряд сотен MOVLW 0x08 ;Коэффициент задержки для свечения CALL dispdelay ;пауза BSF PORTA, 2 ;выключаем разряд сотен MOVLW 0x06 ;Коэффициент задержки для погасания CALL dispdelay ;пауза GOTO disploop
;************************************************************************************** delay: ;Процедура задержки ;Входные данные: число, пропорциональное задержке в регистре cnt1. ;Выходные: задержка. ;Используемые регистры: cnt1, cnt2, cnt3. ; Delay 1sec@20MHz: ; cnt1 = Cycles/256/256/7 = (20000000/4)/256/256/7 = 10.899 = 11 ; ;Задержка для этой подпрограммы задается перед обращением к ней как загрузка числа ;в регистр cnt1. Общее число циклов определяется по формуле: 256*256*cnt1*7. ;Для примера, приблизительно 1 секунда при частоте 20 МГц задается загрузкой 11 ;в cnt1. Примечательно, что в каждом цикле одно и тоже количество выполняемых команд. MOVWF CNT1 CLRF CNT2 CLRF CNT3 dloop DECFSZ CNT3,F GOTO $+2 DECFSZ CNT2,F GOTO $+2 DECFSZ CNT1,F GOTO dloop RETURN
;************************************************************************************** dispdelay: ;Кратковременная задержка BCF STATUS, RP0 ;Выбираем банк памяти 0 BCF CMCON, COUT ;Сбрасываем компаратор BSF STATUS, RP0 ;Выбираем банк памяти 1 BSF PIE1, CMIE ;Разрешаем прерывание от компаратора BCF STATUS, RP0 ;Выбираем банк памяти 0 MOVWF CNT1 CLRF CNT2 dshortloop DECFSZ CNT2, F GOTO $+2 DECFSZ CNT1, F GOTO dshortloop BSF STATUS, RP0 ;Выбираем банк памяти 1 BSF PIE1, CMIE ;Запрещаем прерывание от компаратора BCF STATUS, RP0 ;Выбираем банк памяти 0 RETURN
;************************************************************************************** fxd2416u: ;Процедура деления 24-х разрядного числа на 16-ти разрядное ;Входные данные: ; Делимое - AARGBH:AARGBM:AARGBL ; Делитель - BARGBH:BARGBL ;Временные переменные: ; Счётчик - LOOPCOUNT ; Остаток - REMBH:REMBL ;Выходные данные: ; Частное - AARGBH:AARGBM:AARGBL
CLRF REMBH CLRF REMBL MOVLW .24 MOVWF LOOPCOUNT loopu2416 RLF AARGBL, W ;сдвигаем делимое влево, чтобы получить очередной бит в остатке //shift dividend left to move next bit to remainder RLF AARGBM, F ; RLF AARGBH, F ;
RLF REMBL, F ;перенос сдвига (следующего бита делимого) в остаток //shift carry (next dividend bit) into remainder RLF REMBH, F
RLF AARGBL, F ;finish shifting the dividend and save carry in AARGBL.0, ;since remainder can be 17 bit long in some cases ;(e.g. 0x800000/0xFFFF). This bit will also serve ;as the next result bit. ;заканчиваем сдвигать делимое и сохраняем перенос в AARGBL.0, ;так как остаток может быть 17 битов длиной в некоторых случаях ;(например 0x800000/0xFFFF). Этот бит будет также служить ;следующим битом результата. MOVF BARGBL, W ;вычитаем делитель от 16-разрядного остатка //substract divisor from 16-bit remainder SUBWF REMBL, F ; MOVF BARGBH, W ; BTFSS STATUS, C ; INCFSZ BARGBH, W ; SUBWF REMBH, F ;
;here we also need to take into account the 17th bit of remainder, which ;is in AARGBL.0. If we don't have a borrow after subtracting from lower ;16 bits of remainder, then there is no borrow regardless of 17th bit ;value. But, if we have the borrow, then that will depend on 17th bit ;value. If it is 1, then no final borrow will occur. If it is 0, borrow ;will occur. These values match the borrow flag polarity. ;здесь мы ещё должны принять во внимание 17-й бит остатка, который ;находится в AARGBL.0. Если у нас нет заимствования после вычитания от ;16 нижних битов остатка, то есть, не заимствуем независимо от 17-го разрядного ;значения. Но, если у нас есть заимствование, тогда который будет зависеть от 17-ого разряда ;значения. Если это 1, то не конечный заимствуют, произойдет. Если это будет 0, заимствуйте, ;то произойдет. Эти значения соответствуют заимствованной полярности флажка. SKPNC ;if no borrow after 16 bit subtraction BSF AARGBL, 0 ;then there is no borrow in result. Overwrite ;AARGBL.0 with 1 to indicate no ;borrow. ;if borrow did occur, AARGBL.0 already ;holds the final borrow value (0-borrow, ;1-no borrow)
BTFSC AARGBL, 0 ;if no borrow after 17-bit subtraction GOTO uok46ll ;skip remainder restoration.
ADDWF REMBH, F ;restore higher byte of remainder. (w ;contains the value subtracted from it ;previously) MOVF BARGBL, W ;restore lower byte of remainder ADDWF REMBL, F ;
uok46ll
DECFSZ LOOPCOUNT, f ;уменьшаем счётчик цикла на 1 //decrement counter GOTO loopu2416 ;и повторяем цикл, если счётчик не равен нулю //and repeat the loop if not zero. RETURN
;************************************************************************************** hex2bcd: ;Процедура перевода 24-х разрядного двоичного числа ;в 24-х разрядное BCD ;Входные данные: ; Двоичное число - ARGBINH:ARGBINM:ARGBINL ; ;Временные переменные: ; Счётчик "выталкиваний" - POPSCOUNT ; Временное хранилище для W - W_TEMP_BCD ;Выходные данные: ; BCD число RESBCDH:RESBCDM2:RESBCDM1:RESBCDL
CLRF RESBCDH CLRF RESBCDM2 CLRF RESBCDM1 CLRF RESBCDL MOVLW 0x18 MOVWF POPSCOUNT GOTO lab
next MOVF RESBCDL, W CALL corr MOVWF RESBCDL MOVF RESBCDM1, W CALL corr MOVWF RESBCDM1 MOVF RESBCDM2, W CALL corr MOVWF RESBCDM2 MOVF RESBCDH, W CALL corr MOVWF RESBCDH lab RLF ARGBINL, F RLF ARGBINM, F RLF ARGBINH, F RLF RESBCDL, F RLF RESBCDM1, F RLF RESBCDM2, F RLF RESBCDH, F DECFSZ POPSCOUNT, F GOTO next RETURN
corr MOVWF W_TEMP_BCD MOVLW 0x03 ADDWF W_TEMP_BCD, F BTFSS W_TEMP_BCD, 3 SUBWF W_TEMP_BCD, F MOVLW 0x30 ADDWF W_TEMP_BCD, F BTFSS W_TEMP_BCD, 7 SUBWF W_TEMP_BCD, F MOVF W_TEMP_BCD, W RETURN
;************************************************************************************** send2com: ;передача символа находящегося в регистре W по протоколу RS232, ;скорость 9600, data = 8, nonparity, 1 stopbit, 20 Мгц, ; ;Временные переменные: ;Отправляемый байт - SBYTE ;Счётчик "выталкиваний" - POPSCNT ;Счётчик для задержки - DELAYCNTR
BCF STATUS, RP0 ;Банк 0 MOVWF SBYTE MOVLW 0x08 MOVWF POPSCNT BSF PORTC, 0 ; стартовый бит CALL delay_104mks char2rs232 ; данные RRF SBYTE ;в SBYTE-байт на передачу BTFSS STATUS, C BSF PORTC, 0 BTFSC STATUS, C BCF PORTC, 0 CALL delay_102mks DECFSZ POPSCNT, F GOTO char2rs232
BCF PORTC, 0 ; стоповый бит CALL delay_104mks RETURN delay_104mks MOVLW 0x80 MOVWF DELAYCNTR NOP DECFSZ DELAYCNTR, F GOTO $-2 RETURN delay_102mks MOVLW 0x7F MOVWF DELAYCNTR NOP DECFSZ DELAYCNTR, F GOTO $-2 RETURN
;************************************************************************************** ;Процедура отправки сохранённых значений на терминал sendtoterminal: MOVLW 0x76 ;'v' CALL send2com MOVLW 0x31 ;'1' CALL send2com MOVLW 0x2E ;'.' CALL send2com MOVLW 0x30 ;'0' CALL send2com MOVLW 0x0D ;'cr' CALL send2com MOVLW 0x0A ;'lf' CALL send2com
MOVLW 0x53 ;'S' CALL send2com MOVLW 0x68 ;'h' CALL send2com MOVLW 0x6F ;'o' CALL send2com MOVLW 0x74 ;'t' CALL send2com MOVLW 0x73 ;'s' CALL send2com MOVLW 0x3A ;':' CALL send2com MOVLW 0x20 ;' ' CALL send2com
MOVLW RESCNTADR ;Читаем из EEPROM значение количества CALL memread ;запомненых измерений MOVWF SAVEDCNT ;И сохраняем его в SAVEDCNT ADDLW 0x00 ;Проверяем на отсутствие записей BTFSC STATUS, Z ; GOTO endtrans ;Если нет записей - никаких вычислений не делаем
CLRF ARGBINH ;Преобразуем значение количества CLRF ARGBINM ;записей в BCD формат MOVFW SAVEDCNT ; MOVWF ARGBINL ; CALL hex2bcd ;
SWAPF RESBCDL, W ;Меняем полубайты и помещаем BCD значение в W ANDLW b'00001111' ;Отбрасываем верхний полубайт ADDLW 0x30 ;Преобразуем в ASCII CALL send2com ;Выводим десятки MOVFW RESBCDL ;Помещаем BCD значение в W ANDLW b'00001111' ;Отбрасываем верхний полубайт ADDLW 0x30 ;Преобразуем в ASCII CALL send2com ;Выводим единицы
CLRF CNTVALUE ;Инициализируем счётчик
transloop INCF CNTVALUE, F ;Увеличиваем значение счётчика DECF CNTVALUE, W ;Уменьшаем на 1 (поскольку нумерация идёт с нуля) ;и помещаем вычисленное значение в W CALL gettmrval ;Получаем значения таймера CALL getspeed ;По полученным показаниям таймера вычисляем значение скорости
MOVLW 0x0D ;'cr' CALL send2com MOVLW 0x0A ;'lf' CALL send2com MOVFW DISPH ;Передаём сотни ADDLW 0x30 CALL send2com MOVFW DISPT ;Передаём десятки ADDLW 0x30 CALL send2com MOVFW DISPU ;Передаём единицы ADDLW 0x30 CALL send2com
MOVFW CNTVALUE ;Помещаем значение счётчика в W SUBWF SAVEDCNT, W ;Вычитаем значение счётчика из количества сохранённых BTFSS STATUS, Z ;Проверяем на достижение последней записи GOTO transloop ;Если нет превышения - повторяем
MOVLW 0x0D ;'cr' CALL send2com MOVLW 0x0A ;'lf' CALL send2com
MOVLW 0x00 ;'null' CALL send2com endtrans RETURN
; ORG 0xFE ; END ; initialize eeprom locations
ORG 0x2100 DE 0x09 ;0x00 v Количество сохранённых замеров DE 0x10 ;0x01 Начальный адрес хранения значений результатов в EEPROM DE 0x07 ;0x02 v Базовая константа - старший разряд DE 0xA1 ;0x03 v Базовая константа - средний разряд DE 0x20 ;0x04 v Базовая константа - младший разряд DE 0x16 ;0x05 v Настройка регистра CMCON DE 0x8F ;0x06 v Настройка регистра VRCON DE 0x01 ;0x07 v Настройки таймера TIMER1 (делителя нет, таймер запущен, источник тактового сигнала внутренний F=Fосц/4) DE 0x08 ;0x08 Коэффициент задержки для свечения DE 0x06 ;0x09 Коэффициент задержки для погасания DE 0x00 ;0x0A Зарезервировано DE 0x00 ;0x0B Зарезервировано DE 0x00 ;0x0C Зарезервировано DE 0x00 ;0x0D Зарезервировано DE 0x00 ;0x0E Зарезервировано DE 0x00 ;0x0F Зарезервировано DE 0x98 ;0x10 DE 0x11 ;0x11 DE 0xCC ;0x12 DE 0x08 ;0x13 DE 0xDD ;0x14 DE 0x05 ;0x15 DE 0x66 ;0x16 DE 0x04 ;0x17 DE 0x84 ;0x18 DE 0x03 ;0x19 DE 0xEE ;0x1A DE 0x02 ;0x1B DE 0x83 ;0x1C DE 0x02 ;0x1D DE 0x33 ;0x1E DE 0x02 ;0x1F DE 0xF5 ;0x20 DE 0x01 ;0x21 END
|