CODE
.def count_VERY_HIGHT = R22
.def count_HIGHT= R21
.def count_LOW = R20 //Перменная счётчик
.def temp = R16
.def NewState= R17 ///Сюда записываем новое состояние
///пинов на которых висит энкодер
.def OldState= R18 //Тут хранится состояние пинов
//предыдущего опроса
.def count_encoder = R23
ENCODER_RAM: .byte 6
; FLASH ======================================================
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////// ТАБЛИЦА ВЕКТОРОВ ПРЕРЫВАНИЙ /////////////////////////////////////
.CSEG
.org $0000 rjmp RESET ; Переход на обработку сброса
.org $0012 jmp TIM2_COMP ; Переход на обработку при выполнении условия сравнения таймера 2
.ORG INT_VECTORS_SIZE ; Конец таблицы прерываний
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////// иницилизация стека/////////////////////////
RESET: ldi r16,low(RAMend)
out SPL,r16
ldi r16,high(RAMend)
out SPH,r16
//
;ENCODER INIT
CLRB DDRE,3,R16 ;DDRE.3 = 0 датчик зенита на вход
CLRB DDRE,4,R16 ;DDRE.4 = 0 датчик зенита на вход
SETB PORTE,3,R16 ;PORTE.3 = 1 Pull-up
SETB PORTE,4,R16 ;PORTE.4 = 1 Pull-up
//
///////////////Инициализация Прерываний//////////////////////
;.......................................................................
.equ XTAL = 16000000
.equ baudrate =115200 /// в реале скорость 115200. т.к. бит удвоенной скорости=1
.equ bauddivider = XTAL/(8*baudrate)-1
.equ frequncy = 1000
.equ encoder_number = (XTAL/(frequncy))/64
outi TCCR2,0<<WGM00|0<<COM01|0<<COM00|1<<WGM01|0<<CS02|1<<CS01|1<<CS00
outi OCR2, encoder_number
//обработка прерывания таймера 2
TIM2_COMP:
PUSHF
PUSH ZL
PUSH ZH
PUSH R17
PUSH R18
PUSH R19
clr R16
clr R17
clr R18
LDS NewState,ENCODER_RAM
LDS OldState,ENCODER_RAM+1
LDS count_LOW,ENCODER_RAM+2
LDS count_HIGHT,ENCODER_RAM+3
LDS count_VERY_HIGHT,ENCODER_RAM+4
LDS count_encoder,ENCODER_RAM+5
;.............................................................
IN NewState,PINE ;Читаем порт к которому подключен энкодер
CBR NewState,0b11100111
LSR NewState
LSR NewState
LSR NewState
cpi OldState,0;OldState,0
brne Cpi1 //Если нет то проверяем другое условие
cpi NewState,2;NewState,2
brne Cpi11
rcall RightShift
;.............................................................
Cpi11:
cpi NewState,1;NewState,1
brne Cpi12
rcall LeftShift
;.............................................................
Cpi12:
mov OldState,NewState;OldState,NewState //То что было новым состоянием энкодера, стало старым...
rjmp EXIT_ENCODER
;.............................................................
Cpi1:
//2) При прошлом опросе Пин А=1 и Пин В=0 ?
cpi OldState,1;OldState,1
brne Cpi2 //Если нет то проверяем другое условие
cpi NewState,0;NewState,0 //
brne Cpi21
rcall RightShift
;.............................................................
Cpi21:
cpi NewState,3;NewState,3
brne Cpi22
rcall LeftShift
;.............................................................
Cpi22:
mov OldState,NewState;OldState,NewState //То что было новым состоянием энкодера, стало старым...
rjmp EXIT_ENCODER
;.............................................................
Cpi2:
//3 ) При прошлом опросе Пин В=1 и Пин А=0 ?
cpi OldState,2;OldState,2
brne Cpi3 //Если нет то проверяем другое условие
cpi NewState,3;NewState,3
brne Cpi31
rcall RightShift
;.............................................................
Cpi31:
cpi NewState,0;NewState,0
brne Cpi12
rcall LeftShift
;.............................................................
Cpi32:
mov OldState,NewState;OldState,NewState //То что было новым состоянием энкодера, стало старым...
rjmp EXIT_ENCODER
;.............................................................
Cpi3:
///4) При прошлом опросе Оба пина=1 ?
cpi OldState,3;OldState,3
brne Cpi4 //Если нет то выходим из процедуры сканирования
cpi NewState,1;NewState,1
brne Cpi41
rcall RightShift
;.............................................................
Cpi41:
cpi NewState,2;NewState,2
brne Cpi42
rcall LeftShift
;.............................................................
Cpi42:
mov OldState,NewState;OldState,NewState //То что было новым состоянием энкодера, стало старым...
;.............................................................
Cpi4:
rjmp EXIT_ENCODER
;.............................................................
RightShift:
clr count_encoder
STS count_Left,count_encoder
LDS count_encoder,count_Right
cpi count_encoder,4;count,4 //Состояние пинов сменилось 4 раза?
brne exitRS
clr count_encoder;count
STS count_Right,count_encoder
ldi R16,1
ADD count_LOW,R16
clr R16
ADC count_HIGHT,R16
ADC count_VERY_HIGHT,R16
rjmp exitRS2
exitRS:
inc count_encoder;count
STS count_Right,count_encoder
exitRS2:
RET
;.............................................................
LeftShift:
clr count_encoder
STS count_Right,count_encoder
LDS count_encoder,count_Left
cpi count_encoder,4;count,4 //Состояние пинов сменилось 4 раза?
brne exitLS
clr count_encoder;count
STS count_Left,count_encoder
LDI R16,1
SUB count_LOW,R16
clr R16
SBC count_HIGHT,R16
SBC count_VERY_HIGHT,R16
rjmp exitLS2
exitLS:
inc count_encoder;count
STS count_Left,count_encoder
exitLS2:
RET
;.............................................................
/// подпрограммы для энкодера
EXIT_ENCODER:
STS ENCODER_RAM,NewState
STS ENCODER_RAM+1,OldState
STS ENCODER_RAM+2,count_LOW
STS ENCODER_RAM+3,count_HIGHT
STS ENCODER_RAM+4,count_VERY_HIGHT
STS ENCODER_RAM+5,count_encoder
POP R19
POP R18
POP R17 ; Корректный выход из прерывания.
POP ZH
POP ZL
POPF
RETI
Идеальная программа для энкодера на АСМе. Разбирайтесь.
P.S. к сожалению, при копировании накрылась медным тазом табуляция.