Вы не вошли.
Из принципиальных ошибок:
1. Конструкции типа (0<<BITNAME) смысла не имеют, так как это всегда ноль.
2. StartPoint - это константа. Так почему Вы написали lds temp,StartPoint? Нужно ldi!
3. Бит C портится командой CPI! Нельзя писать sec, cpi, потом rol, которому нужен бит C.
4. Основная программа выводит переменную CommandVar в порт, затем её очищает и снова выводит. Никогда ничего не увидите на светодиодах!
5. Если счетчик бит загружать числом 13, то после приема всех бит в посылке может быть еще один переход (если последний бит посылки = 1), по которому будет срабатывать прерывание, а поскольку дальше посылки нет, возникнет ошибка. Проще всего принимать 14 бит, где последний принятый бит всегда будет единицей.
6. По ошибке приема посылки лучше не делать ничего.
7. При разрешении прерывания таймера в обработчике внешнего прерывания нужно сбрасывать флаг, так как в промежутке между посылками таймер наверняка переполнялся и флаг установлен.
8. Нельзя делать прямую запись констант в регистры оборудования, которыми данный модуль не владеет монопольно. Например, это внешние прерывания. Нужно читать регистр, устанавливать/сбрасывать нужные биты, затем записывать результат обратно.
Остальные изменения чисто косметические, чтобы сделать обработчики прерываний как можно компактней.
- Вместо переменных в памяти взял наименее ценные младшие регистры.
- Флаг объявил как битовую переменную.
- Всю посылку RC-5 вдвигаю в 16-разрядную регистровую переменную, а затем разбираю нужные биты.
- В принципе, внешнее прерывание можно запрещать в нем самом, а разрешать снова в прерывании таймера. Хотя, наверное, это однофигственно.
Что можно улучшить:
- Как рекомендует Philips, после завершения посылки нужно примерно 3 мс контролировать тишину на выходе приемника. Если обнаружены какие-то импульсы - ошибка. А то в условиях интенсивных помех декодер будет выдавать чепуху вместо того, чтобы молчать.
- Хорошо бы проверять валидность Манчестера, т.е. делать не одну выборку на бит, а две: через 1/4 и 3/4 от начала бита. Значения должны быть разными, иначе ошибка. Нужно учитывать, что в нашем примере прерывания происходят в середине бита!
- Для повышения помехоустойчивости можно вместо одной выборки входного сигнала делать серию. Но это будет иметь плохую эффективность в плане фильтрации помех, так как интервал выборок вынуждены выбирать малым, чтобы не сильно увеличивать загрузку процессора. Оптимальным по загрузке/помехоустойчивости было бы по таймеру делать 3 выборки на каждой половине бита (примерно через 130 мкс), а затем по мажоритарному принципу вычислять состояние входа.
Пример реализации двух последних приведенных пунктов есть по ссылке, которую я приводил ранее (на Си).
;----------------------------------------------------------------------------
;Программа декодирования кода RC-5 путем вызова
;прерывания на каждом импульсе.
;МК ATtiny2313 Частота кварца 4 МГц
;----------------------------------------------------------------------------
.include "2313def.inc" ;Liv: 2313 !!!
;----------------------------------------------------------------------------
;Константы:
.equ Ref3_4 = 84 ;3/4 периода RC5 (ТС0 с прескалером СК/64)
.equ Ref2_4 = 55 ;2/4 периода RC5 (ТС0 с прескалером СК/64)
.equ NumberOfBits = 14 ;макс кол-во принимаемых бит: 1 стартовый
;(1-й не сохраняется), 1 управляющий,
;5 адрес системы, 6 код команды, пустой бит
;----------------------------------------------------------------------------
.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
;----------------------------------------------------------------------------
;Глобальные регистровые переменные:
.def RC5_CodeL = r1 ;регистр принимаемого кода RC5 (мл. байт)
.def RC5_CodeH = r2 ;регистр принимаемого кода RC5 (ст. байт)
.def BitCounter = r3 ;счетчик принятых бит
.def temp = r16 ;temporary register temp
.def Flags = r20 ;флаги
.equ NewBit = 0 ;флаг нового бита (устанавливается в INT1)
;----------------------------------------------------------------------------
.DSEG ;сегмент данных
SysVar: .byte 1 ;сюда кладем принятый адрес системы
CommandVar: .byte 1 ;а сюда код команды
;----------------------------------------------------------------------------
.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,NumberOfBits
mov BitCounter,temp ;инициализируем счетчик бит
cbr Flags,(1<<NewBit) ;NewBit = 0
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: push temp ;сохранение темп
in temp,SREG
push temp ;сохранение SREG
;Загружаем таймер 3/4 периода:
ldi temp,256 - Ref3_4 ;грузим начало отсчета
out TCNT0,temp ;таймер начинает считать с этой точки
;Разрешаем прерывания таймера:
ldi temp,(1<<TOIE0) ;ставим бит TOIE0 в 1
out TIMSK,temp ;разрешаем прерывание по переполн ТС0
out TIFR,temp ;очищаем флаг прерывания таймера
;Устанавливаем флаг начала нового бита:
sbr Flags,(1<<NewBit) ;NewBit = 1
pop temp
out SREG,temp ;восст. SREG
pop temp ;восст. temp
reti ;выходим и разрешаем прерывания
;----------------------------------------------------------------------------
;Обработчик по переполнению ТС0:
;----------------------------------------------------------------------------
Timer: push temp ;сохранение темп
in temp,SREG
push temp ;сохранение SREG
;Проверка флага нового бита:
sbrs Flags,NewBit ;проверка NewBit
rjmp RC5_Error ;если NewBit = 0, ошибка таймаута
;Сбрасываем флаг начала нового бита:
cbr Flags,(1<<NewBit) ;NewBit = 0
;Проверка выхода приемника:
sbis PIND,IR_Signal ;проверяем выход приемника
rjmp Store0
;Сохранение 1, разрешаем прерывание по спаду:
Store1: in temp,MCUCR
andi temp,~(1<<ISC10) ;по спаду
out MCUCR,temp
sec ;1
rjmp SaveBit
;Сохранение 0, разрешаем прерывание по фронту:
Store0: in temp,MCUCR
ori temp,(1<<ISC10) ;по фронту
out MCUCR,temp
clc ;0
;Вдвигаем принятый бит:
SaveBit: rol RC5_CodeL
rol RC5_CodeH
;Декремент счетчика бит:
dec BitCounter ;BitCounter - 1
breq EndRec ;0 - завершаем прием посылки
;Загрузка тайм-аута:
ldi temp,256 - Ref2_4 ;грузим начало отсчета для таймаута
out TCNT0,temp ;таймер начинает считать с этой точки
rjmp NextBit ;продолжаем прием посылки
;Прием закончен, раскладываем биты по переменным:
EndRec: mov temp,RC5_CodeL
ror temp
andi temp,0x3F ;чистим ненужные биты
sts CommandVar,temp ;сохраняем код команды в переменную
rol RC5_CodeL
rol RC5_CodeH
mov temp,RC5_CodeH
andi temp,0x3F ;чистим ненужные биты
sts SysVar,temp ;сохраняем адрес системы в переменную
;Перезагрузка счетчика бит:
RC5_Error: ldi temp,NumberOfBits
mov BitCounter,temp ;перезагружаем счетчик бит
;Разрешаем прерывание по спаду:
in temp,MCUCR
andi temp,~(1<<ISC10) ;по спаду
out MCUCR,temp
;Запрещаем прерывание таймера:
ldi temp,0
out TIMSK,temp ;запрещаем прерывание таймера
NextBit: pop temp ;восст SREG
out SREG,temp
pop temp ;восст temp
reti
;----------------------------------------------------------------------------
Отредактировано Liv (07.11.2006 23:31:23)
Вне форума
Из принципиальных ошибок:
1. Конструкции типа (0<<BITNAME) смысла не имеют, так как это всегда ноль.
Будем знать.
2. StartPoint - это константа. Так почему Вы написали lds temp,StartPoint? Нужно ldi!
Ну ошибся, знамо дело... Ничего кстати, уидвительного (самокритично так )
3. Бит C портится командой CPI! Нельзя писать sec, cpi, потом rol, которому нужен бит C.
Вот этого яне знал. Но почему carry портися при сравнении? Причем тут перенос?? Я понимаю если было сложение или еще что-то в этом роде... Ну да ладно, учту на будущее.
Резюме: Как долго еще мне до серьезного понимания многих вещей.... Ну как говорят, на ошибках учаться. Оч хорошо, что есть кому указать эти ошики. Спасибо большое!
......There is someone in my head, but it's not me.......
Вне форума
Вот этого яне знал. Но почему carry портися при сравнении? Причем тут перенос?? Я понимаю если было сложение или еще что-то в этом роде... Ну да ладно, учту на будущее.
Почему? Ну, это вопрос к разработчикам процессора. А вообще то, какая команда модифицирует какой флаг, нужно знать. Тем более хелп всегда под рукой: в AVR Studio ставите курсор на мнемонику команды и жмете F1. Появится хэлп по данной команде, а там будет табличка флагов.
Вот тут написал следующую версию декодера, которая сэмплирует три раза каждую половинку бита, а затем по мажоритарному принципу вычисляет состояние. И еще проверяет валидность Манчестера. Многовато регистров жрет, но при желании можно переменные перенести в память. Посмотрел в отладчика, так в момент декодирования посылки тратится всего 4% процессорного времени, и это на 4 МГц тактовой! Замечательно! Пробовал имитировать помехи, но разницы между первым и вторым вариантом декодера не обнаружил Думаю, в большинстве случаев достаточно простейшего декодера как в первом варианте.
;----------------------------------------------------------------------------
;Программа декодирования кода RC-5 путем вызова
;прерывания на каждом импульсе.
;МК ATtiny2313 Частота кварца 4 МГц
;----------------------------------------------------------------------------
.include "2313def.inc" ;Liv: 2313 !!!
;----------------------------------------------------------------------------
;Константы:
.equ Ref1_8 = 14 ;1/8 периода RC5 (ТС0 с прескалером СК/64)
.equ Ref2_8 = 28 ;2/8 периода RC5 (ТС0 с прескалером СК/64)
.equ NumberOfBits = 14 ;количество принимаемых бит
.equ SAMPLE_COUNT = 3 ;количество выборок, должно быть
;нечетным, чтобы сумма не могла быть нулем
;----------------------------------------------------------------------------
;Полезные макросы:
.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
;----------------------------------------------------------------------------
;Глобальные регистровые переменные:
.def RC5_CodeL = r1 ;регистр принимаемого кода RC5 (мл. байт)
.def RC5_CodeH = r2 ;регистр принимаемого кода RC5 (ст. байт)
.def BitCounter = r3 ;счетчик принятых бит
.def SampCnt = r4
.def SampVal = r5
.def temp = r16 ;temporary register temp
.def Flags = r20 ;флаги
.equ PreVal = 0 ;значение первой половины бита
;----------------------------------------------------------------------------
.DSEG ;сегмент данных
SysVar: .byte 1 ;сюда кладем принятый адрес системы
CommandVar: .byte 1 ;а сюда код команды
;----------------------------------------------------------------------------
.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,NumberOfBits
mov 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 - Ref1_8 ;грузим интервал до первой выборки
out TCNT0,temp
;Разрешаем прерывания таймера:
ldi temp,(1<<TOIE0) ;ставим бит TOIE0 в 1
out TIMSK,temp ;разрешаем прерывание по переполн ТС0
out TIFR,temp ;очищаем флаг прерывания таймера
;Инициализируем переменные:
ldi temp,SAMPLE_COUNT * 2 ;количество выборок на периоде
mov 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
;Проверка признака таймаута:
tst SampCnt
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 SampCnt ;уменьшаем количество сэмплов
breq EvPre ;если ноль, то закончена вторая половина
mov temp,SampCnt
cpi temp,SAMPLE_COUNT
breq EvThis ;закончена первая половина
ldi temp,256 - Ref1_8 ;продолжаем выборки с периодом 1/8
out TCNT0,temp
rjmp NextSam
;Оцениваем текущий бит по результатам сэмплирования первой половины:
EvThis: ldi temp,256 - Ref2_8 ;грузим интервал между сериями сэмплов
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 - Ref2_8 ;грузим интервал таймаута
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: dec BitCounter ;BitCounter - 1
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,NumberOfBits
mov BitCounter,temp ;перезагружаем счетчик бит
;Разрешаем прерывание по спаду:
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
;----------------------------------------------------------------------------
Отредактировано Liv (08.11.2006 03:07:22)
Вне форума
Пробовал имитировать помехи, но разницы между первым и вторым вариантом декодера не обнаружил Думаю, в большинстве случаев достаточно простейшего декодера как в первом варианте.
А мож и правда хватит и простого?? Классно, когда есть всесторонняя проверка но все ж. У меня знакомый как-то делал на PIC'е систему управления для тюнера, так у него там и LCD и пульт, и Sound processor и все шо хош. Он, между прочим, падает в прерывание на первом стартовом бите посылки RC5 и сидит в нем безвылазно до самого конца. И ничего, счастлив....
;----------------------------------------------------------------------------
.include "2313def.inc" ;Liv: 2313 !!!
;----------------------------------------------------------------------------
Эх, не любите вы милый моему сердцу ATtiny2313 ! Я шитов начитался, на мой взгляд это оптимум из мелких. Все что надо есть, нет тока АЦП. Благо, он редко нужен.
;Полезные макросы:
.macro clbr ;clear bit in register
cbr @0,exp2(@1)
Объясните пожалста, что есть макрос и для чего он нужен. А то Вы часто их пользуете, а я не шарю, и программы Ваши понимаю с большим трудом.
.equ DIR_PORTD = ~(1<<PD3) ;порт D нога PD3 - ввод, остальное вывод.
А что дает конструкция типа "~(1<<PD3)" ?? Тоже что-то из Си???
Ага, вот еще непонятно:
.def Flags = r20 ;флаги
.equ PreVal = 0 ;значение первой половины бита
.def Flags - регистр хранящий флаги. А ".equ PreVal = 0 ;значение ......". Что есть ноль?? Нулевой бит в том регистре??
Да, еще по той программе, что Вы правили. На метке SaveBit Вы делаете rol обоим регистрам. Как потом у Вас получается различить адрес ситемы и код команды???
......There is someone in my head, but it's not me.......
Вне форума
2 Liv
Ваша программа почему-то не работает... . После компиляции и прошивки вообще начал греться фотопроемник. Я переписал в программе вместо ~(1<<PD3) написал .equ DIR_PORTD = (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD4) | (1<<PD5) | (1<<PD6) как было. Греться перестал, импульсы с него идут. Светодиоды не загораются....
......There is someone in my head, but it's not me.......
Вне форума
Эх, не любите вы милый моему сердцу ATtiny2313 ! Я шитов начитался, на мой взгляд это оптимум из мелких. Все что надо есть, нет тока АЦП. Благо, он редко нужен.
Это вы батенька зря!:)
Андрей Смирнов
Вне форума
Эх, не любите вы милый моему сердцу ATtiny2313 !
Просто я его еще никогда в руках не держал. А старые 2313 просто так валяются по всем углам
Объясните пожалста, что есть макрос и для чего он нужен. А то Вы часто их пользуете, а я не шарю, и программы Ваши понимаю с большим трудом.
Макрос - это некий кусок текста, который целиком будет вставляться в программу там, где Вы просто укажете его имя. Избавляет от лишней громоздкости. К примеру, я пишу clbr Flags,fOvf, вместо cbr Flags,(1<<fOvf). Или пишу ldy Const вместо ldi YL,byte1(Const), ldi YH,byte2(Const).
А что дает конструкция типа "~(1<<PD3)" ?? Тоже что-то из Си???
В хэлпе по AVR Studio всё это есть. Это побитная инверсия. Т.е. будут все единицы, кроме PD3.
Ага, вот еще непонятно:
.def Flags = r20 ;флаги
.equ PreVal = 0 ;значение первой половины бита
.def Flags - регистр хранящий флаги.
А ".equ PreVal = 0 ;значение ......". Что есть ноль?? Нулевой бит в том регистре??
Да. Имеется в виду именно это. Хотя строчка .equ PreVal = 0 всего лишь определяет константу PreVal, равную нулю, безотносительно к какому-то регистру. Но будучи примененной так: clbr Flags,PreVal сбросит бит 0 регистра Flags. Хотя ести написать clbr r21,PreVal, то будет сброшен бит 0 регистра r21. Это же асм, всё на совести программиста.
Да, еще по той программе, что Вы правили. На метке SaveBit Вы делаете rol обоим регистрам. Как потом у Вас получается различить адрес ситемы и код команды???
После приема всей посылки биты системы и команда будут задвинуты в двухбайтовую регистровую переменную и будут там находится цепочкой друг за другом. Я просто потом беру нужные биты и раскладываю по переменным.
Ваша программа почему-то не работает...
Я же не теоретически писал. Вот рядом лежит макетка, на которой этот декодер реально работает с пультом от телевизора. Правда, у меня AT90S2313. Может у Вас что-то с фузами?
Вне форума
Матроскин пишет:Эх, не любите вы милый моему сердцу ATtiny2313 !
Просто я его еще никогда в руках не держал. А старые 2313 просто так валяются по всем углам
А... ясно. В магазине старый 2313 в 2 раза дороже тини2313
Объясните пожалста, что есть макрос и для чего он нужен. А то Вы часто их пользуете, а я не шарю, и программы Ваши понимаю с большим трудом.
Макрос - это некий кусок текста, который целиком будет вставляться в программу там, где Вы просто укажете его имя. Избавляет от лишней громоздкости. К примеру, я пишу clbr Flags,fOvf, вместо cbr Flags,(1<<fOvf). Или пишу ldy Const вместо ldi YL,byte1(Const), ldi YH,byte2(Const).
Да. Имеется в виду именно это. Хотя строчка .equ PreVal = 0 всего лишь определяет константу PreVal, равную нулю, безотносительно к какому-то регистру. Но будучи примененной так: clbr Flags,PreVal сбросит бит 0 регистра Flags. Хотя ести написать clbr r21,PreVal, то будет сброшен бит 0 регистра r21. Это же асм, всё на совести программиста.
А как так же поиграться с например с битом 1 в данном регистре?
Я же не теоретически писал. Вот рядом лежит макетка, на которой этот декодер реально работает с пультом от телевизора. Правда, у меня AT90S2313. Может у Вас что-то с фузами?
Да хрен его знает... Мож МК глючит или порт PD3 я ему уже угробил. Не спроста же грелся фотприемник. Не запись же ~(1<<PD3) виновата. Насчет фузов.. Я точно знаю, что там включен CKOUT (нога PD2) - забыл выключить когда была возможность. Поэтому я не использую прерывание INT0 (оно на той ноге как раз). А остальное... Я работоспособность проверяю Вашей программкой что светодиодом мигает. Она работает. А там не знаю... Хреново, что AVRProg для тини2313 фузы не шьет. Наверно пойду куплю еще пару МК, попоробую на них. Все равно собирался. Есть у меня еще 2 меги8 но они в TQFP. На макетке с ними не поиграешься. Сочинить бы какой-нибудь переходник, чтоб их без пайки зажимал и можно было "косвенно" подпаяться к выводам. Можно наверно поробовать развести на маленькой платке и изготовить из текстолита накладку с точным вырезом под корпус и накладкой этой мегу сверху прижимать. Есть правда вероятность плохого контакта...
Отредактировано Матроскин (09.11.2006 11:07:17)
......There is someone in my head, but it's not me.......
Вне форума
2 Liv
Я от злости купил Тини26. Программу переделал под него. Светодиоды теперь на порту А, приемник на РВ6 (INT0). AVRProg его полностю поддерживает, с фузами не налажаешь уже, все там прозрачно. Все равно не работает. Не загораются эти светодиоды и все тут. Пробовал 2 пульта. Один "for HORIZONT RC-5/F" другой от телека Samsung CS-15K9MJQ на самом пульте написано AA59-00332D. В том телеке приемник стоит 356VF5 на 38 кГц, но все равно пульт дает импульсы и на 36 кГц - приемнике HL536AA3P, который у меня в макетке (на осциле импульсы вижу).
......There is someone in my head, but it's not me.......
Вне форума
А... ясно. В магазине старый 2313 в 2 раза дороже тини2313
У нас в магазинах нет ни 2313, ни tiny...
А как так же поиграться с например с битом 1 в данном регистре?
Точно так же. Определяете еще одно имя флага как Flag1 = 1. Установить флаг - stbr Flags,Flag1, сбросить - clbr Flags,Flag1.
Есть у меня еще 2 меги8 но они в TQFP. На макетке с ними не поиграешься. Сочинить бы какой-нибудь переходник, чтоб их без пайки зажимал
Зачем такие сложности. Сделайте по лазерно-утюжной технологии маленькую платку, на которой разведите m8, запаяйте её, а выводы разведите в стороны на отверстия с шагом 2.54 мм, к которым будет легко подпаяться. На эксперименты выделить одну m8 не должно быть жалко. У меня такая мега на макетке уже несколько лет служит.
Я от злости купил Тини26. Программу переделал под него. Светодиоды теперь на порту А, приемник на РВ6 (INT0). AVRProg его полностю поддерживает, с фузами не налажаешь уже, все там прозрачно. Все равно не работает. Не загораются эти светодиоды и все тут. Пробовал 2 пульта. Один "for HORIZONT RC-5/F" другой от телека Samsung CS-15K9MJQ на самом пульте написано AA59-00332D. В том телеке приемник стоит 356VF5 на 38 кГц, но все равно пульт дает импульсы и на 36 кГц - приемнике HL536AA3P, который у меня в макетке (на осциле импульсы вижу).
От пульта HORIZONT RC-5 точно должно работать. Возможно, при переделке что-то напутали. Возможно, что-то не так с тактовой частотой. Что я могу посоветовать? Осциллограф - лучший друг программиста Определите отладочные ноги на выход. Одну из них включайте в начале внешнего прерывания, а выключайте в конце. Другую - в прерывании таймера. На внешнюю синхронизацию подайте импульсы с первой ноги, а смотрите по очереди выход фотоприемника и вторую ногу. Сразу будет видно, в какие моменты делаются выборки. Я так и отлаживал.
Вне форума
[ Сгенерировано за 0.061 сек, 8 запросов выполнено - Использовано памяти: 765.41 Кбайт (Пик: 818.3 Кбайт) ]