Телесистемы
 Разработка, производство и продажа радиоэлектронной аппаратуры
На главную   | Карта сайта | Пишите нам | В избранное
Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс.
e-mail:jobsmp@pochta.ru

Телесистемы | Электроника | Конференция «Микроконтроллеры и их применение»

Опять забыл про-HTML-ить << , попытка 2:

Отправлено Леонид Иванович 27 декабря 2006 г. 23:51
В ответ на: Вот декодер RC-5 с хорошей помехоустойчивостью на ASM для AVR, можно легко переписать на Си. отправлено Леонид Иванович 27 декабря 2006 г. 23:48


;----------------------------------------------------------------------------

;Программа декодирования кода 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 ;записываем в регистр TCCR0

in 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

;----------------------------------------------------------------------------



Составить ответ | Вернуться на конференцию

Ответы


Отправка ответа
Имя*: 
Пароль: 
E-mail: 
Тема*:

Сообщение:

Ссылка на URL: 
URL изображения: 

если вы незарегистрированный на форуме пользователь, то
для успешного добавления сообщения заполните поле, как указано ниже:
введите число 567:

Перейти к списку ответов | Конференция | Раздел "Электроника" | Главная страница | Карта сайта

Rambler's Top100 Рейтинг@Mail.ru
 
Web telesys.ru