Re: Пропорциональное управление на МК (Знание=Сила)
Добавлено: Чт сен 27, 2012 22:05:03
вот схему накидал
Здесь можно немножко помяукать :)
https://radiokot.ru/forum/
Код: Выделить всё
.def Temp=R16
.def Temp1=R17
.def Temp2=R18
.def Temp3=R19
.def Temp4=R20
.def Temp5=R21
.def Temp6=R22
.def Temp7=R23
.def Temp8=R24
.def Temp9=R25
.dseg ;оперативка
key_buff: .byte 5 ; зарезервируем 5 байт в ОЗУ
;******************************************************************************
.EQU ImpLen=0xCE4 ; длина импульса
.EQU OneLen=0xCE4 ; длина паузы для единицы
.EQU NulLen=0x19C8 ; длина паузы для нуля
;******************************************************************************
.cseg
.org 0
rjmp RESET ; External Pin, Power-on Reset, Brown-out Reset, and Watchdog Reset
.org OC1Aaddr ; (=0x0004) Timer/Counter1 Compare Match A
rjmp OCR1A_COMP
.org INT_VECTORS_SIZE
;******************************************************************************
;старт
;******************************************************************************
reset: ; включение микроконтроллера
cli ; глобальный запрет на прерывания
ldi Temp,low(RamEnd) ; инициализации стека
out SPL,Temp ;
ldi Temp,0b00001111 ; настроили порт "В" (0-ввод, 1-вывод)
out DDRB,Temp ; 0000х000 - "вывод" на передатчик (PB3- 15 ножка)
; хххх0000 - "ввод" для чтения строк клавиатуры
; 00000ххх - "вывод" для того что бы при чтении клавиатуры получить "0" ??????????????????
ldi Temp,0b00001111 ; настраиваем порт "D" (0-ввод, 1-вывод)
out DDRD,Temp ; 0000хххх - на вывод столбцов клавы
ldi Temp,0b00000000 ; выводим на передатчик лог_0 ????????????????????????????????????????????????
out portB,Temp
ldi Temp,0b00000000 ; установили тактовый сигнал = CK 0
out TCCR1B,Temp ; таймер выключен!!!
sei ; глобальное разрешение прерываний
;*******************************************************************************
; главный цикл
;*******************************************************************************
Main_cicle:
rcall keyboardread ; вызов подпрограммы чтения клавиатуры
rcall certain_buttons_keyboard ; вызов подпрограммы проверки нажатия
rjmp Main_cicle ; циклимся
;*******************************************************************************
; цикл Чтения клавы и запись данных в ОЗУ
;*******************************************************************************
keyboardread: ; метка - опрос клавиатуры
ldi Temp,5 ; количество столбцов клавы = пять
ldi Temp1,0b00000001 ; первый столбец
; загружаем адрес метки массива (key_buff) находящейся в ОЗУ в регистровую пару X
ldi XL, low(key_buff) ; младший байт адреса
ldi XH, high(key_buff) ; старший байт адреса
keyboardread_loop: ; цикл опроса
out PortD,Temp1 ; выводим в порт "Д" значение "Temp1" для выбора столбца клавиатуры
in Temp2,PinB ; прочитали состояние столбца
st X+,Temp2 ; сохраним в ОЗУ состояние столбца клавы,
; адрес в регстровой паре "X" автоматом увеличится на 1
lsl Temp1 ; сдвинули единичку выбора столбца клавиатуры на 1
; позицию влево
dec temp ; уменьшим счетчик
brne keyboardread_loop ; если не все просканировали, то циклимся
ret ; возврат в главный цикл
;******************************************************************************************
; цикл проверки нажатия клавиатуры
;******************************************************************************************
certain_buttons_keyboard:
ldi temp1,5 ; УСТАНОВИМ СЧЕТЧИК столбцов клавы
; загружаем адрес метки (key_buff) находящейся в ОЗУ в регистровую пару "Z"
ldi ZL,low (key_buff) ; младший байт адреса
ldi ZH,high(key_buff) ; старший байт адреса
Certain_button:
ld Temp,Z+ ; загрузим данные в регистр из ОЗУ по адресу из регистровой пары "Z",
; и после этого адресс в регистровой паре автоматически увеличится на еденицу
cpi Temp,0b00000000 ; проверяем, нажата ли какая ни будь кнопка?
brne inform ; если нажата то переходим на метку "inform"
dec temp1 ; уменьшим счетчик
brne Certain_button ; если не все столбцы, то циклимся
metka:
ret ; возврат в главный цикл
;***********************************************************************************************
; вывод информации о состоянии клавиатуры в порт "Б"
;***********************************************************************************************
inform: ; здесь мы включаем таймер
ldi Temp,(1<<COM1A0) ; переключать ножку "OC1A" по совпадению (PB3- 15 ножка)
out TCCR1A,Temp ; *1
LDI R19, 2 ; зададим фиксированную длительность импульса ( 0x200 видимо )
OUT OCR1AH, R19 ; и выведем ее в порт сравнения
LDI R19, 0
OUT OCR1AL ,R19
ldi Temp,0 ; обнуление таймера
out TCNT1H,Temp
out TCNT1L,Temp
ldi Temp,(1<<wgm12)|(1<<cs10) ; подключили режим "CTC" (вместе с *1)
out TCCR1B,Temp ; и установили тактовый сигнал = CK 1:1
; таймер начал считать!!!
ldi Temp,(1<<OCIE1A) ; разрешить прерывание компаратора
out TIMSK,Temp
ldi R22, 0 ; фаза передачи
loop_wait_transmitt: ; цикл ожидания завершения передачи
cpi R22 , 7
brne loop_wait_transmitt
ldi temp1,0 ; обнулим "temp1", что бы точно выйти из цикла проверки нажатия клавиатуры ???????????????????
ret ; возврат в цикл проверки нажатия клавиатуры
;*******************************************************************************
;обработка прерывания
;*******************************************************************************
OCR1A_COMP:
; первоначальное значение R22 - 0
; таким образом сначала будет выполнена инициализации передачи
; проверяем фазу работы прерывания
in temp,SREG ; сохраняем "SREG"/////////////////////////////////////////////////////
push temp
CPI R22, 1
BREQ transmitt_byte ; фаза передачи байта
CPI R22, 2
BREQ transmitt_bite_imp ; фаза передачи импульса бита в байте
CPI R22, 3
BREQ transmitt_bite_pause ; фаза передачи паузы бита в байте
CPI R22, 4
BREQ transmitt_imp_chetn ; фаза передачи импульса бита четности
CPI R22, 5
BREQ transmitt_pausa_chetn ; фаза передачи паузы бита четности
CPI R22, 6
BREQ transmitt_complete ; передача завершена, выключение прерываний
;****************************************************************************************************************
; инициализация передачи, (при R22=0)
ldi R21,0 ; это будет счетчик единичек в передаче (четность)
ldi yl,low(key_buff) ; зададим адрес начала массива прочитанных кнопок в ргистровую пару "Y"
ldi yh,high(key_buff)
ldi R17,5 ; количество байт для передачи
transmitt_byte: ; фаза начала передачи - передача байта
ld temp,y+ ; прочитаем байт для передачи, увеличим на единицу адрес в "Y"
ldi r18,8 ; количество бит в байте для передачи
pop temp ; извлекаем "SREG" ???????????????????????????????????????????????????????????
out SREG, temp
transmitt_bite_imp: ; фаза передачи импульса в передаваемом бите
in temp,SREG ; сохраняем "SREG" ???????????????????????????????????????????????????????????
push temp
LDI R19 ,high(ImpLen) ; зададим фиксированную длительность импульса
OUT OCR1AH, R19 ; и выведем ее в порт сравнения
LDI R19,low(ImpLen)
OUT OCR1AL ,R19
LDI R22, 3 ; в следующий раз передаем паузу
int_reti:
pop temp ; извлекаем "SREG" ////////////////////////////////////////////////////////////
out SREG, temp
RETI ; точка выхода из прерывания
;**********************************************************************************************************************
transmitt_bite_pause: ; фаза передачи паузы в передаваемом бите
; здесь кодируем импульс для бита
in temp,SREG ; сохраняем "SREG" ????????????????????????????????????????????????????????????
push temp
LDI XL,low(Nullen) ; длительность для передачи нуля
LDI XH,high(Nullen)
ROL temp ; двигаем байт влево (циклический сдвиг влево)
BRCC send_nullen ; если "С"=0 то записываем нулевую длительность
LDI XL,low(onelen) ; длительность для передачи единицы
LDI XH,high(onelen)
INC R21 ; передаем единицу - увеличим счетчик единичек (четность)
send_nullen:
OUT OCR1AH,XH ; установим длительность
OUT OCR1AH,XL
LDI R22,2 ; в следующий раз передадим импульс бита
dec R18 ; уменьшим счетчик бит на передачу
brne int_reti ; если это непоследний бит в байте - то выход из прерывания
LDI R22,1 ; в следующий раз передадим новый байт
dec R17 ; уменьшим счетчик Байт для передачи
brne int_reti ; если это не последний байт в массиве - то выход из прерывания
LDI R22,4 ; в следующий раз передадим импульс бита четности
RJMP int_reti ; выход из прерывания
;*********************************************************************************************************************
transmitt_imp_chetn: ; передача импульса бита четности
in temp,SREG ; сохраняем "SREG" ???????????????????????????????????????????????????????????
push temp
LDI R19 ,high(ImpLen) ; зададим фиксированную длительность импульса
OUT OCR1AH, R19 ; и выведем ее в порт сравнения
LDI R19,low(ImpLen)
OUT OCR1AL,R19
LDI R22,5 ; в следующий раз передаем паузу бита четности
rjmp int_reti ; выход из прерывания
;**********************************************************************************************************************
transmitt_pausa_chetn: ; передача паузы бита четности
; здесь кодируем длительность паузы для бита четности
in temp,SREG ; сохраняем "SREG" ???????????????????????????????????????????????????????????
push temp
LDI XL,low(Nullen) ; длительность паузы для передачи нуля
LDI XH,high(Nullen)
COM R21 ; Побитная инверсия
ROR R21 ; Циклический сдвиг вправо
BRCC send_chetn ; если "С"=0 то записываем нулевую длительность
LDI XL,low(onelen) ; длительность паузы для передачи единицы
LDI XH,high(onelen)
send_chetn:
OUT OCR1AH,XH ; установим длительность
OUT OCR1AH,XL
LDI R22,6 ; R22=6 ОТКЛЮЧЕНИЕ ПРЕРЫВАНИЯ
rjmp int_reti ; выход из прерывания
;*************************************************************************************************************************
transmitt_complete: ; КОД ДЛЯ ОТКЛЮЧЕНИЯ ПРЕРЫВАНИЙ
in temp,SREG ; сохраняем "SREG" ???????????????????????????????????????????????????????????
push temp
ldi Temp,0b00000000 ; установили тактовый сигнал = CK 0
out TCCR1B,Temp ; таймер выключен!!!
ldi Temp,0b00000000 ; выводим на передатчик лог_0 ????????????????????????????????????????????????
out portB,Temp
LDI R22, 7 ; Признак окончания передачи
rjmp int_reti ; выход из прерывания
;*************************************************************************************************************************
А можно посмотреть исходник, схему ?Sergi писал(а):Немного не в тему. Вот сейчас запустил цифровой канал передачи. 2 пропорциональных команды и 16 дискретных. Пульт управления ATMega16 + MRF49, приемник ATMega88 + MRF49. Есть исходники на С. Дешифрация - побайтный разбор пакета. TC вроде бы не указал какими RF модулями он пользуется. Мне кажется с цифровой передачей канал надежнее будет. Завтра испытания "в поле".
Спасибо почитаю!Jurkin писал(а):поищите книгу "10 практических устройств на AVR-микроконтроллерах" КНИГА 3 А.В.Кравченко 2011.