Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс. e-mail:jobsmp@pochta.ru |
;----------------------------------------------------------------------------;Программа декодирования кода RC-5:
; - высокая помехозащищенность
; - низкая загрузка процессора;Использует внешние прерывание от фотоприемника и прерывание таймера 0.
;Производится несколько выборок для каждой половинки бита
;(количество выборок задается константой SAMPLE_COUNT),
;логический уровень вычисляется по мажоритарному принципу.
;Кроме того, проверяется валидность кода Манчестер.;----------------------------------------------------------------------------
.include "2313def.inc"
;----------------------------------------------------------------------------
;Константы:
.equ FCLK = 4000000 ;Hz
.equ PRE = 64
.equ RC5_SLOT = 1778 ;uS
.equ RC5_LENGTH = 14 ;количество принимаемых бит
.equ SAMPLE_COUNT = 3 ;количество выборок, должно быть
;нечетным, чтобы сумма не могла быть нулем.equ T_SAMPLE_US = RC5_SLOT / ((SAMPLE_COUNT + 1) * 2)
.equ F_TIMER = FCLK / PRE
.equ T_SAMPLE = (T_SAMPLE_US * F_TIMER /100000 + 5) / 10;----------------------------------------------------------------------------
;Полезные макросы:
.macro clbr ;clear bit in register
cbr @0,exp2(@1)
.endm.macro stbr ;set bit in register
sbr @0,exp2(@1)
.endm.macro bbrc ;branch if bit in register clear
sbrs @0,@1
rjmp @2
.endm.macro bbrs ;branch if bit in register set
sbrc @0,@1
rjmp @2
.endm;----------------------------------------------------------------------------
.equ IR_Signal = PD3 ;выход ик-приемника на ноге РD3 (INT1)
;Байты направления портов:
.equ DIR_PORTB = 0xFF ;направление для порта В.
.equ DIR_PORTD = ~(1 << PD3) ;порт D нога PD3 - ввод, остальное вывод.
;Байты первоначального состояния портов:.equ PUP_PORTB = 0x00 ;после сброса весь порт B ставим в 0
.equ PUP_PORTD = (1 << PD3) ;после сброса Pull-Up на PD3
;----------------------------------------------------------------------------.DSEG ;сегмент данных
SysVar: .byte 1 ;сюда кладем принятый адрес системы
CommandVar: .byte 1 ;а сюда код команды
BitCounter: .byte 1 ;счетчик принятых бит
SampCnt: .byte 1;----------------------------------------------------------------------------
;Глобальные регистровые переменные:
.def RC5_CodeL = r2 ;регистр принимаемого кода RC5 (мл. байт)
.def RC5_CodeH = r3 ;регистр принимаемого кода RC5 (ст. байт)
.def SampVal = r4.def temp = r16 ;temporary register temp
.def Flags = r20 ;флаги
.equ PreVal = 0 ;значение первой половины бита;----------------------------------------------------------------------------
.CSEG ;сегмент кода
;Векторы прерываний:.org 0 ;по адресу 0 вектор сброса
rjmp Init ;переход на основную программу.org INT1addr ;прерывание по внешнему сигналу INT1
rjmp EdgeRC5.org OVF0addr ;по адресу OVF0addr вектор прерывания по
rjmp Timer ;переполнению таймера 0;----------------------------------------------------------------------------
;Программа начинает выполняться отсюда
;----------------------------------------------------------------------------
;Здесь пишем всякую инициализацию, которая должна
;выполняться один раз при старте программы.Init: ldi temp,low(RAMEND) ;константа RAMEND определена в tn2313def.inc
out SPL,temp ;инициализируем SatckPoiter
;ldi temp,high(RAMEND)
;out SPH,temp;Инициализация переменных:
ldi temp,RC5_LENGTH
sts BitCounter,temp ;инициализируем счетчик бит
stbr Flags,PreVal ;первая половина старт-бита = 1
clr temp
sts SysVar,temp ;очистка системы
sts CommandVar,temp ;очистка команды;Настройка портов:
ldi temp,PUP_PORTB
out PORTB,temp ;включаем Pull-Up в PORTB
ldi temp,DIR_PORTB
out DDRB,temp ;настраиваем направление для PORTB
ldi temp,PUP_PORTD
out PORTD,temp ;включаем Pull-Up в PORTD
ldi temp,DIR_PORTD
out DDRD,temp ;настраиваем направление для PORTD;Настройка оборудования:
ldi temp,(1 << CS00) | (1 << CS01) ;предделитель таймера ставим на СК/64
out TCCR0,temp ;записываем в регистр TCCR0in temp,MCUCR
ori temp,(1 << ISC11) ;по спаду
out MCUCR,temp
in temp,GIMSK
ori temp,(1 << INT1) ;бит INT1 в GIMSK равен 1
out GIMSK,temp ;разрешаем внешнее прерывание INT1
sei ;global interrupts enable;----------------------------------------------------------------------------
;Основной цикл программы.
;----------------------------------------------------------------------------
Main: lds temp,CommandVar ;грузим код команды из переменной
out PORTB,temp ;выводим на порт
rjmp Main ;цикл;----------------------------------------------------------------------------
;Обработчик внешнего прерывания:
;----------------------------------------------------------------------------
EdgeRC5: sbi PORTD,PD4 ;контроль на PD4 внешнего прерывания
push temp ;сохранение темп
in temp,SREG
push temp ;сохранение SREG
;Загружаем таймер:ldi temp,256 - T_SAMPLE ;грузим интервал до первой выборки
out TCNT0,temp
;Разрешаем прерывания таймера:ldi temp,(1 << TOIE0) ;ставим бит TOIE0 в 1
out TIMSK,temp ;разрешаем прерывание по переполн ТС0
out TIFR,temp ;очищаем флаг прерывания таймера;Инициализируем переменные:
ldi temp,SAMPLE_COUNT * 2 ;количество выборок на периоде
sts SampCnt,temp
clr SampVal ;очищаем суммарное значение выборокpop temp
out SREG,temp ;восст. SREG
pop temp ;восст. temp
cbi PORTD,PD4
reti ;выходим и разрешаем прерывания;----------------------------------------------------------------------------
;Обработчик по переполнению ТС0:
;----------------------------------------------------------------------------
Timer: sbi PORTD,PD5 ;контроль на PD5 прерывания таймера
push temp ;сохранение темп
in temp,SREG
push temp ;сохранение SREG;Проверка признака таймаута:
lds temp,SampCnt
tst temp
brne DoSamp
rjmp RC5_Error ;если SampCnt = 0, ошибка таймаута;Делаем выборки:
DoSamp: sbis PIND,IR_Signal ;проверяем выход приемника
rjmp Bit0
Bit1: inc SampVal ;если единица, то SampVal + 1
rjmp CheckSmp
Bit0: dec SampVal ;если ноль, то SampVal - 1;Проверка числа сэмплов:
CheckSmp: dec temp ;уменьшаем количество сэмплов
sts SampCnt,temp
breq EvPre ;если ноль, то закончена вторая половинаcpi temp,SAMPLE_COUNT
breq EvThis ;закончена первая половинаldi temp,256 - T_SAMPLE ;продолжаем выборки с периодом T_SAMPLE
out TCNT0,temp
rjmp NextSam;Оцениваем текущий бит по результатам сэмплирования первой половины:
EvThis: ldi temp,256 - T_SAMPLE * 2 ;грузим интервал между сериями сэмплов
out TCNT0,temp;Определяем состояние:
tst SampVal ;если SampVal > 0, то единица
brmi Store0 ;если SampVal < 0, то ноль;Первая половина равна единице, бит равен нулю:
Store1: bbrs Flags,PreVal,RC5_Error ;проверяем на ошибку Манчестера
clc
rjmp SaveBit;Первая половина равна нулю, бит равен единице:
Store0: bbrc Flags,PreVal,RC5_Error ;проверяем на ошибку Манчестера
sec;Вдвигаем принятый бит:
SaveBit: rol RC5_CodeL
rol RC5_CodeH
clr SampVal ;очищаем сумму выборок
rjmp NextSam ;приступаем ко второй половине;Закончено сэмплирование второй половины бита:
EvPre: ldi temp,256 - T_SAMPLE * 2 ;грузим интервал таймаута
out TCNT0,temp;Определяем состояние:
tst SampVal
brmi Pre0;Вторая половина равна единице, сохраняем в PreVal:
Pre1: stbr Flags,PreVal
in temp,MCUCR
andi temp,~(1 << ISC10) ;настраиваем прерывание по спаду
out MCUCR,temp
rjmp DecCnt;Вторая половина равна нулю, сохраняем в PreVal:
Pre0: clbr Flags,PreVal
in temp,MCUCR
ori temp,(1 << ISC10) ;настраиваем прерывание по фронту
out MCUCR,temp;Декремент счетчика бит:
DecCnt: lds temp,BitCounter
dec temp ;BitCounter - 1
sts BitCounter,temp
breq EndRec ;0 - завершаем прием посылки
rjmp NextSam ;прием следующего бита посылки;Прием закончен, раскладываем биты по переменным:
EndRec: mov temp,RC5_CodeL
andi temp,0x3F ;чистим ненужные биты
sts CommandVar,temp ;сохраняем код команды в переменную
rol RC5_CodeL
rol RC5_CodeH
rol RC5_CodeL
rol RC5_CodeH
mov temp,RC5_CodeH
andi temp,0x3F ;чистим ненужные биты
sts SysVar,temp ;сохраняем адрес системы в переменную
;Перезагрузка счетчика бит:RC5_Error: ldi temp,RC5_LENGTH
sts BitCounter,temp ;перезагружаем счетчик бит
stbr Flags,PreVal ;первая половина старт-бита = 1;Разрешаем прерывание по спаду:
in temp,MCUCR
andi temp,~(1 << ISC10) ;по спаду
out MCUCR,temp;Запрещаем прерывание таймера:
ldi temp,0
out TIMSK,temp ;запрещаем прерывание таймераNextSam: pop temp ;восст SREG
out SREG,temp
pop temp ;восст temp
cbi PORTD,PD5
reti;----------------------------------------------------------------------------