; кварц на 16 мгц ; внутренний делитель отключен ; не работает .include "tn2313adef.inc" ; используем tiny2313a .def Temp=R16 .def Temp1=R17 .def Temp2=R18 .def Temp3=R19 .def Temp4=R20 ; регистр сохранения регистра SREG .def Temp5=R21 .def Temp6=R22 ; флаг .def Temp7=R23 ; .def Temp8=R24 .def Temp9=R25 ;****************************************************************************** ; оперативка ;****************************************************************************** .dseg ; оперативка ch_count: .byte 1 ; номер импульса // 0,1,2 каналы ; если = 3, то это синхроимпульс ; если = 4, то это рассинхронизация или старт МК impuls_len: .byte 2 ; зарезервируем 2 байта в ОЗУ = переменная для хранения данных считаных с таймера ;****************************************************************************** ; константы ;****************************************************************************** .EQU Chastota_const=0x9C40 ; вершина ШИМ для серопривода ( частота 50 Гц ) ; 50Гц=0,02сек ; 1 тик таймера = 0,0000005 сек ; 0,02/0,0000005=40000 ( 0x9C40 ) ;****************************************************************************** ; программный сегмент ;****************************************************************************** .cseg .org 0 rjmp RESET ; External Pin, Power-on Reset, Brown-out Reset, and Watchdog Reset .org ICP1addr ; = 0x0003 Timer/Counter1 Capture Event ( прерывание по захвату ) rjmp ICP1_interruption .org INT_VECTORS_SIZE ;****************************************************************************** ; старт *********************************************************************** ;****************************************************************************** reset: ; включение микроконтроллера cli ; глобальный запрет на прерывания ldi Temp,low(RamEnd) ; инициализации стека out SPL,Temp ; ldi Temp,0b11111111 ; настроили порт "В" (0-ввод, 1-вывод) out DDRB,Temp ; ldi Temp,0b00000000 ; выводим лог_0 out PortB,Temp ; ldi Temp,0b00111111 ; настраиваем порт "D" (0-ввод, 1-вывод) out DDRD,Temp ; 0х000000 - вход с приемника (ICP) ldi Temp,0b00000000 ; выводим лог_0 out PortD,Temp ; RCALL LCD_INIT ; инициализация дисплея ;****************************************************************************** ; настраиваем таймер_1 ;****************************************************************************** ; ШИМ для сервы ( аппаратный ) ; ICP для измерения длительности импульса. ldi Temp,(0<Y ( сейчас число больше чем в прошлый раз ) ;************************************************************************************************************** ; вычисление длины импульса, если таймер был переполнен ;************************************************************************************************************** menshe_2: SUB ZL, XL ; из большего вычитаем меньшее SBC ZH, XH ; ldi XH, high(Chastota_const) ; загружаем число 40000 ldi XH, low(Chastota_const) SUB XL, ZL ; вычисляем длительность импульса SBC XH, ZH ; длительность канала находится в "Х" rjmp prodolzaem ; ;************************************************************************************************************** ; вычисление длины импульса, если таймер НЕ БЫЛ переполнен ;************************************************************************************************************** bolshe_2: SUB XL, ZL ; вычисляем длительность импульса SBC XH, ZL ; длительность канала находится в "Х" rjmp prodolzaem ; ;************************************************************************************************************** ; проверка синхронизации ( а так-же нужно при включении мк ) ;************************************************************************************************************** prodolzaem: LDS Temp, ch_count ; читаем номер импульса cpi Temp, 4 ; флаг рассинхронизации установлен ? brne work ; флаг снят, Все сихронизировано!!!! rjmp sinhro ; флаг установлен, требуется синхронизация ;********************************************************************************* ; сравниваем полученную длительность с 13 мс ( 0b110010110010000 ) ( 0x6590 ) ;********************************************************************************* sinhro: mov Temp,XH ; копируем "Х" mov Temp1,XL ldi YH,0x65 ; записываем в регистровую пару "Y" 13мс 0x6590 ldi YL,0x90 rcall compare_XY16 ; сравниваем... breq bolshe ; переход на обработку когда X=Y brcs menshe ; переход на обработку когда XY ;***************************************************************************************** ; ;***************************************************************************************** bolshe: ; это синхроимпульс! ldi Temp, 0 ; снимаем флаг включения_МК, устанавливаем флаг 0-го канала sts ch_count, Temp rjmp out_1 ; выход menshe: ; это был не синхроимпульс! rjmp out_1 ; выход ;***************************************************************************************** ; все синхронизировано, можно работать ;***************************************************************************************** work: ; channal_check_0: ; проверка канала_0 LDS Temp, ch_count ; читаем номер импульса cpi Temp, 0 ; это 0-ой канал ? brne channal_check_1 ; нет rjmp channal_0 ; да channal_check_1: ; проверка канала_1 LDS Temp, ch_count ; читаем номер импульса cpi Temp, 1 ; это 1-ый канал ? brne channal_check_2 ; нет rjmp channal_1 ; да channal_check_2: ; проверка канала_2 LDS Temp, ch_count ; читаем номер импульса cpi Temp, 2 ; это 2-ой канал ? brne channal_check_sinhro ; нет rjmp channal_2 ; да channal_check_sinhro: ; синхроимпульс ( если это не канал, значит - синхроимпульс ) ldi Temp, 4 ; если рассинхронизировалось, то ждем синхронизацию sts ch_count, Temp rjmp out_1 ; выход ;***************************************************************************************** ; РАБОТА С КАНАЛАМИ ;***************************************************************************************** channal_0: ; канал_0 ( газ ) ldi Temp, 1 ; следующим будет канал_1 sts ch_count, Temp rjmp out_1 ; выход ;********************************************************************************************** channal_1: ; канал_1 ( курс ) ldi Temp, 2 ; следующим будет канал_2 sts ch_count, Temp rjmp out_1 ; выход ;********************************************************************************************** channal_2: ; канал_2 ( сервопривод тангажа ) ldi Temp, 4 ; следующим будет СИНХРОИМПУЛЬС sts ch_count, Temp ; OUT OCR1BH,XH ; зададим длину импульса ; OUT OCR1BL,XL ; и выведем ее в порт сравнения ;******************************************************************************* ; вывод на диспдей ;******************************************************************************* rcall out_disp ; выводим на дисплей LDI R16,0x10 ; печать пробела RCALL LCD_CHAR LDI R16,0 ; печать нуля RCALL LCD_CHAR cicle: rjmp cicle ; БЕСКОНЕЧНЫЙ ЦИКЛ ;************************************************************************************************************** ; Выход из прерывания ;************************************************************************************************************** out_1: pop temp4 ; извлекаем "SREG" //////////////////////////////////////////////////// out SREG, temp4 RETI ; точка выхода из прерывания ;************************************************************************************************************** ; подготовка информации для вывода на экран ;************************************************************************************************************** out_disp: mov r16, XL ; берем младший байт TCNT1L push r16 ; сохраняем его на стеке mov r16, XH ; берем старший байт TCNT1H rcall printhex ; переходим печатать старший байт pop r16 ; извлекаем стек printhex: push r16 ; сохраняем на стеке swap r16 ; меняем местами старший полубайт и младший полубайт (SWAP - поменять нибблы местами) rcall printhex1 ; переходим на маску печати pop r16 ; берем данные из стека printhex1: ; маска печати andi r16, 0x0f ; маска 00001111 (печатаем младший полубайт) rcall lcd_char ; переходим на печать цифры ret ;***************************************************************************************** ; подпрограмма сравнения ;***************************************************************************************** compare_XY16: cp Temp,YH ; сравниваем старшие части регистров breq xh_eq_yh ; значения старших регистров равны, нужно сравнить младшие xl и yl ; флаг С - установлен когда XY ret xh_eq_yh: cp Temp1,YL ; сравниваем младшие части регистров ; флаг Z=1 когда X=Y ; флаг С - установлен когда XY ret ;************************************************************************************************************** ; подключаемые модули ;************************************************************************************************************** .include "lcd5110mini.asm" ; подключение драйвера дисплея