Radiohobby Forum

Интернет конференция журнала "Радиохобби"

Вы не вошли.

Объявление

Подписка на новые материалы от Николая Сухова - ролики, схемы, модели, онлайн конференции, консультации, чат.

Внимание! Почта в доменах Яндекс и Mail.ru не будет работать в профилях форумчан, из-за введённых правительством Украины санкций против этих компаний. Всем, кто ранее использовал подобную почту, для сохранения прежней функциональности форума, рекомендуется её поменять.

Огромная просьба, заливать тематические картинки и файлы в личные файловые каталоги на форуме, чтобы они не потерялись, со временем!

Ссылка "Загрузки" находится справа внизу формы набора сообщения.

Подписка на журнал "Радиохобби" прекращена. Подробности. Форум же - продолжает свою работу.

#241 07.11.2006 23:27:55

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Из принципиальных ошибок:

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)

Вне форума

#242 07.11.2006 23:58:29

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

Liv пишет:

Из принципиальных ошибок:

1. Конструкции типа (0<<BITNAME) смысла не имеют, так как это всегда ноль.

Будем знать.

Liv пишет:

2. StartPoint - это константа. Так почему Вы написали lds temp,StartPoint? Нужно ldi!

Ну ошибся, знамо дело... Ничего кстати, уидвительного (самокритично так smile )

Liv пишет:

3. Бит C портится командой CPI! Нельзя писать sec, cpi, потом rol, которому нужен бит C.

Вот этого яне знал. Но почему carry портися при сравнении? Причем тут перенос?? Я понимаю если было сложение или  еще что-то в этом роде... Ну да ладно, учту на будущее.

Резюме: Как долго еще мне до серьезного понимания многих вещей.... Ну как говорят, на ошибках учаться. Оч хорошо, что есть кому указать эти ошики. Спасибо большое!


......There is someone in my head, but it's not me.......

Вне форума

#243 08.11.2006 02:03:42

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Матроскин пишет:

Вот этого яне знал. Но почему carry портися при сравнении? Причем тут перенос?? Я понимаю если было сложение или  еще что-то в этом роде... Ну да ладно, учту на будущее.

Почему? Ну, это вопрос к разработчикам процессора. А вообще то, какая команда модифицирует какой флаг, нужно знать. Тем более хелп всегда под рукой: в AVR Studio ставите курсор на мнемонику команды и жмете F1. Появится хэлп по данной команде, а там будет табличка флагов.

Вот тут написал следующую версию декодера, которая сэмплирует три раза каждую половинку бита, а затем по мажоритарному принципу вычисляет состояние. И еще проверяет валидность Манчестера. Многовато регистров жрет, но при желании можно переменные перенести в память. Посмотрел в отладчика, так в момент декодирования посылки тратится всего 4% процессорного времени, и это на 4 МГц тактовой! Замечательно! Пробовал имитировать помехи, но разницы между первым и вторым вариантом декодера не обнаружил sad Думаю, в большинстве случаев достаточно простейшего декодера как в первом варианте.

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

;Программа декодирования кода 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)

Вне форума

#244 08.11.2006 09:45:43

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

Liv пишет:

Пробовал имитировать помехи, но разницы между первым и вторым вариантом декодера не обнаружил sad Думаю, в большинстве случаев достаточно простейшего декодера как в первом варианте.

А мож и правда хватит и простого?? Классно, когда есть всесторонняя проверка но все ж. У меня знакомый как-то делал на PIC'е систему управления для тюнера, так у него там и LCD и пульт, и Sound processor и все шо хош. Он, между прочим, падает в прерывание на первом стартовом бите посылки RC5 и сидит в нем безвылазно до самого конца. И ничего, счастлив....

Liv пишет:

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

.include "2313def.inc"          ;Liv: 2313 !!!

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

Эх, не любите вы милый моему сердцу ATtiny2313 ! smile Я шитов начитался, на мой взгляд это оптимум из мелких. Все что надо есть, нет тока АЦП. Благо, он редко нужен.

Liv пишет:

;Полезные макросы:

.macro    clbr            ;clear bit in register
    cbr @0,exp2(@1)

Объясните пожалста, что есть макрос и для чего он нужен. А то Вы часто их пользуете, а я не шарю, и программы Ваши понимаю с большим трудом.

Liv пишет:

.equ    DIR_PORTD = ~(1<<PD3)   ;порт D    нога PD3 - ввод, остальное вывод.

А что дает конструкция типа "~(1<<PD3)" ?? Тоже что-то из Си???                                                   

Ага, вот еще непонятно:

Liv пишет:

.def    Flags     = r20         ;флаги
.equ    PreVal    = 0           ;значение первой половины бита

.def Flags - регистр хранящий флаги. А ".equ    PreVal    = 0     ;значение ......". Что есть ноль?? Нулевой бит в том регистре??

Да, еще по той программе, что Вы правили. На метке SaveBit Вы делаете rol обоим регистрам. Как потом у Вас получается различить адрес ситемы и код команды???


......There is someone in my head, but it's not me.......

Вне форума

#245 08.11.2006 12:06:54

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

2 Liv

Ваша программа почему-то не работает... sad . После компиляции и прошивки вообще начал греться фотопроемник. Я переписал в программе вместо ~(1<<PD3) написал .equ    DIR_PORTD = (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD4) | (1<<PD5) | (1<<PD6) как было. Греться перестал, импульсы с него идут. Светодиоды не загораются....   sad


......There is someone in my head, but it's not me.......

Вне форума

#246 08.11.2006 17:15:17

Pyku_He_oTTyda
Ветеран
Откуда: г.Великие Луки
Здесь с 23.01.2004
Сообщений: 531

Re: AVR для "чайников"

Эх, не любите вы милый моему сердцу ATtiny2313 ! smile Я шитов начитался, на мой взгляд это оптимум из мелких. Все что надо есть, нет тока АЦП. Благо, он редко нужен.
Это вы батенька зря!:)


Андрей Смирнов

Вне форума

#247 09.11.2006 06:11:03

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Матроскин пишет:

Эх, не любите вы милый моему сердцу ATtiny2313 ! smile

Просто я его еще никогда в руках не держал. А старые 2313 просто так валяются по всем углам smile

Матроскин пишет:

Объясните пожалста, что есть макрос и для чего он нужен. А то Вы часто их пользуете, а я не шарю, и программы Ваши понимаю с большим трудом.

Макрос - это некий кусок текста, который целиком будет вставляться в программу там, где Вы просто укажете его имя. Избавляет от лишней громоздкости. К примеру, я пишу 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. Может у Вас что-то с фузами?

rc-5_board.jpg

Вне форума

#248 09.11.2006 11:05:20

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

Liv пишет:
Матроскин пишет:

Эх, не любите вы милый моему сердцу ATtiny2313 ! smile

Просто я его еще никогда в руках не держал. А старые 2313 просто так валяются по всем углам smile

А... ясно. В магазине старый 2313 в 2 раза дороже тини2313

Матроскин пишет:

Объясните пожалста, что есть макрос и для чего он нужен. А то Вы часто их пользуете, а я не шарю, и программы Ваши понимаю с большим трудом.

Макрос - это некий кусок текста, который целиком будет вставляться в программу там, где Вы просто укажете его имя. Избавляет от лишней громоздкости. К примеру, я пишу clbr Flags,fOvf, вместо cbr Flags,(1<<fOvf). Или пишу ldy Const вместо ldi YL,byte1(Const), ldi YH,byte2(Const).


Liv пишет:

Да. Имеется в виду именно это. Хотя строчка .equ PreVal = 0 всего лишь определяет константу PreVal, равную нулю, безотносительно к какому-то регистру. Но будучи примененной так: clbr Flags,PreVal сбросит бит 0 регистра Flags. Хотя ести написать clbr r21,PreVal, то будет сброшен бит 0 регистра r21. Это же асм, всё на совести программиста.

А как так же поиграться с например с битом 1 в данном регистре?


Liv пишет:

Я же не теоретически писал. Вот рядом лежит макетка, на которой этот декодер реально работает с пультом от телевизора. Правда, у меня 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.......

Вне форума

#249 09.11.2006 15:08:04

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

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.......

Вне форума

#250 09.11.2006 17:19:35

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Матроскин пишет:

А... ясно. В магазине старый 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 точно должно работать. Возможно, при переделке что-то напутали. Возможно, что-то не так с тактовой частотой. Что я могу посоветовать? Осциллограф - лучший друг программиста smile Определите отладочные ноги на выход. Одну из них включайте в начале внешнего прерывания, а выключайте в конце. Другую - в прерывании таймера. На внешнюю синхронизацию подайте импульсы с первой ноги, а смотрите по очереди выход фотоприемника и вторую ногу. Сразу будет видно, в какие моменты делаются выборки. Я так и отлаживал.

Вне форума

Сейчас в этой теме пользователей: 0, гостей: 1
[Bot] ClaudeBot

Подвал форума

Под управлением FluxBB
Модифицировал Visman

[ Сгенерировано за 0.061 сек, 8 запросов выполнено - Использовано памяти: 765.41 Кбайт (Пик: 818.3 Кбайт) ]