Страница 1 из 3

Вопросы по программированию AVR на ассемблере

Добавлено: Пт май 02, 2014 21:24:40
Родион@22
Я заинтересовался проектом http://cxema.my1.ru/publ/skhemy_ustrojs ... 9-1-0-2397 , но там оказались проблемы с кодом.
У меня возникли вопросы в листинге программы помогите разобраться:
1) Метка есть, а где сам переход по метке?

Код: Выделить всё

DIP:	nop
	in	tmp, PORTA
	nop
	sbis 	PINA, 1		;пропустить если не нажат DIP1.1
	rjmp qq0

Код: Выделить всё

s1:   nop
   sbis   PINB, 6      ;пропустить если не нажат DIP1.2
   rjmp   qq1
   nop
   rjmp qq2
2) В проекте предложен движковый переключатель для выбора подпрограммы[img][img]http://img.radiokot.ru/files/96849/thumbnail/bx1f1ma3k.jpg[/img][/img]
Я хочу его заменить на две кнопки. Не могли бы вы подсказать листинг программы, чтобы, допустим, первая кнопка была для "Подпрограмма загорания светодиодов по очереди", а вторая - для "Подпрограмма загорания светодиодов по возрастанию".
3) Что имел ввиду автор под понятием "среднее арифметическое действие"

Код: Выделить всё

;среднее арифметическое действие

ass:	nop
	clr	r8
	clc
	add	tmp2, r2
	adc	r9, r8
	add	tmp2, r6
	adc	r9, r8
	add	tmp2, r6
	adc	r9, r8
	clc
	lsr	r9
	ror	tmp2
	lsr	r9
	ror	tmp2
	clr	r9
	clc
	add	tmp3, r3
	adc	r9, r8
	add	tmp3, r5
	adc	r9, r8
	add	tmp3, r7
	adc	r9, r8
	clc
	lsr	r9
	ror	tmp3
	lsr	r9
	ror	tmp3
	lsr	r9
	ror	tmp3
	nop
	ret
4) Если есть что-то еще напишите

Код: Выделить всё

.include "tn26def.inc"

.list
.def tmp  = r16
.def tmp2 = r17
.def tmp3 = r18
.def tempo = r19
.def pir = r22
.def pur = r23
.def par = r20
.def Xa = r21
.def adr = r0
.def prg1 = r24
.def prg2 = r25


.cseg
.org 0x00
	rjmp RESET
	rjmp EXT_INT0;прерывание по входному сигналу
	rjmp EXT_PIN ;прерывание не используется
	rjmp TIME_CMPA ;прерывание от таймера
	rjmp TIME_CMPB ;прерывание от таймера
	rjmp TIME_OVF1 ;прерывание от таймера
	rjmp TIME_OVF0 ;прерывание от таймера
	rjmp USI_STRT ;прерывание от USI
	rjmp USI_OVR ;прерывание от USI
	rjmp EE_RDY ;прерывание от таймера
	rjmp ANA_COMP ;прерывание от компаратора
	rjmp ADC_ ;прерывание от АЦП

	;"Заглушки" обработчиков неиспользуемых прерываний
    	EXT_INT0:;прерывание по входному сигналу
	EXT_PIN: ;прерывание не используется
	TIME_CMPA: ;прерывание от таймера
	TIME_CMPB: ;прерывание от таймера
	TIME_OVF1: ;прерывание от таймера
	TIME_OVF0: ;прерывание от таймера
	USI_STRT: ;прерывание от USI
	USI_OVR: ;прерывание от USI
	EE_RDY: ;прерывание от таймера
	ANA_COMP: ;прерывание от компаратора
	ADC_: ; ADC Conversion Handler
	reti


; настройка портов

RESET:  
    	ldi tmp,RAMEND
	out SP,tmp

	clr  tmp
	out DDRA, tmp
	out PORTA, tmp ; обнулить порт А

	clr tmp
	ldi tmp, $FC       ; РА0, РА1, - входы
	out DDRA, tmp

	clr tmp
	out DDRB, tmp
	out PORTB, tmp ; обнулить порт В

	clr tmp
	ldi tmp, $BF ; РВ6-вход
	out DDRB, tmp

;Начало программы

nStart:	nop

;сброс всех значений

	clr	pir
	clr	pur
	clr	prg1
	clr	prg2
	clr	adr

;вход в подпрограмму опроса АЦП1

	nop
	ldi	tmp3, $80	;источник питания, ADC2, ADMUX
	ldi	tmp2, $C6	;одиночное, запуск, 1/64, ADCSR

;опрос уровня заряда конденсатора

	mov	r30, tmp2	;загрузка младшего разряда
	mov	r31, tmp3	;загрузка старшего разряда
	nop
	ldi	tmp2, $B5	;значение младшего разряда порога
	ldi	tmp3, $01	;значение старшего разряда порога

;вычитание значения АЦП и порога

	sub	r30, tmp2

;проверка на ноль старшего байта

	clr	tmp
	rol	tmp
	sub	r31, tmp3	;вычитание старшего байта с заемом
	sub	r31, tmp		;вычитание заема
loki:	nop
	brmi	nStart		;переход, если результат < 0
	nop

;опрос DIP1

DIP:	nop
	in	tmp, PORTA
	nop
	sbis 	PINA, 1		;пропустить если не нажат DIP1.1
	rjmp qq0

s1:	nop
	sbis	PINB, 6		;пропустить если не нажат DIP1.2
	rjmp	qq1
	nop
	rjmp qq2

; DIP1.1
qq0:	nop
	sbis	PINB,6		;пропустить если не нажат DIP1.2		
	rjmp qq3
	nop
	rjmp nStart
qq3:	nop
	clr pir
cvb:	nop
	inc	pir
	rcall	zader
	nop
	rcall	opros
	nop
	cls
	cpi	pir, $0B
	brlt	cvb
	nop
	rjmp	nStart

; DIP1.2

qq1:	nop
	sbis	PINB, 1		;пропустить если не нажат DIP1.1
	rjmp	qq4
	nop
	rjmp	nStart
qq4:	nop
	clr	pir
cvbn:	nop
	inc	pir
	rcall	zader
	nop
	rcall	opron
	nop
	cls
	cpi	pir, $0B
	brlt	cvbn
	nop
	rjmp	nStart

; DIP1

qq2:	nop
	nop
cvbm:	nop
	inc	pir
	rcall	zader
	nop
	rcall	oprom
	nop
	cls
	cpi	pir, $14
	brlt	cvbn
	nop
	rjmp	nStart

;Настройка АЦП

    nop
	nop
	nop
	nop
	nop
	nop
	nop
	clr	tmp
awe:	nop
	cpi	tmp, $04
	brsh	ass
	clr	tmp3
	ldi	tmp3, $83		;внутренний источник, вход ADC3
	out	ADMUX, tmp3		;коммутация входов АЦП
	clr	tmp2
	clr	tmp3
	ldi	tmp2, $C4		;одиночное, запуск, 1/16
	out	ADCSR, tmp2		;запуск АЦП на преобразование
WAIT:
        sbis ADCSR,ADIF    ;Если флаг ADIF установлен, пропустить следующую команду
        rjmp WAIT           ;Иначе флаг ADIF сброшен, преобразование не завершено, вернуться на метку WAIT для опроса флага

;Флаг ADIF установлен, преобразование завершено.

   in R16,ADCSR       ;Считать содержимое ADCSRA в рег.R16
   ori R16,(1<<ADIF)   ;Установить бит ADIF, не трогая остальные биты
   out ADCSR,R16      ;Занести в ADCSRA содержимое R16 c установленным битом ADIF для сброса флага ADIF

;Сохранение данных АЦП

	in	tmp2, ADCL
	in	tmp3, ADCH
	mov	r2, tmp2
	mov	r3, tmp3
	mov	r4, r2
	mov	r5, r3
	mov	r6, r4
	mov	r7, r5
	inc	tmp
	
;среднее арифметическое действие

ass:	nop
	clr	r8
	clc
	add	tmp2, r2
	adc	r9, r8
	add	tmp2, r6
	adc	r9, r8
	add	tmp2, r6
	adc	r9, r8
	clc
	lsr	r9
	ror	tmp2
	lsr	r9
	ror	tmp2
	clr	r9
	clc
	add	tmp3, r3
	adc	r9, r8
	add	tmp3, r5
	adc	r9, r8
	add	tmp3, r7
	adc	r9, r8
	clc
	lsr	r9
	ror	tmp3
	lsr	r9
	ror	tmp3
	lsr	r9
	ror	tmp3
	nop
	ret

; Подпрограмма задержки включения светодиодов

zader:	nop
	wdr
	clr	r26
	clr	r29
	ldi	r29, $AF
	cpi	tmp3, $00
	brne	goo
	ldi	r26, $01
	add	r26, tmp3
	nop
goo:	nop
	mov	r26, tmp3
dm:	nop
	cpi	tmp2, $00
	brne	goq
	ldi	Xa, $01
	add	Xa, tmp2
	nop
goq:	nop
	mov	Xa, tmp2
dv:	nop
	wdr
	nop
dx:	dec	r29
	brpl	dx
	cln
	dec	Xa
	brpl	dv
	cln
	dec	r26
	brne	dm
	ret

;Подпрограмма опроса светодиодов программа1

opros:	nop
	ldi	ZH, high(2*prog1A)
	ldi	ZL, Low(2*prog1A)
	Add	ZL, pir
	LPM
	mov	prg1, adr
	out	PORTB, prg1
	nop
	ldi	ZH, high(2*prog1B)
	ldi	ZL, Low(2*prog1B)
	Add	ZL, pir
	LPM
	mov	prg2, adr
	out	PORTB, prg2
	ret
;Подпрограмма опроса светодиодов программа2

opron:	nop
	ldi	ZH, high(prog2A*2)
	ldi	ZL, Low(prog2A*2)
	Add	ZL, pir
	LPM
	mov	prg1, adr
	out	PORTB, prg1
	nop
	ldi	ZH, high(prog2B*2)
	ldi	ZL, Low(prog2B*2)
	Add	ZL, pir
	LPM
	mov	prg2, adr
	out	PORTB, prg2
	ret

;Подпрограмма опроса светодиодов программа3

oprom:	nop
	ldi	ZH, high(prog3A*2)
	ldi	ZL, Low(prog3A*2)
	Add	ZL, pir
	LPM
	mov	prg1, adr
	out	PORTB, prg1
	nop
	ldi	ZH, high(prog3B*2)
	ldi	ZL, Low(prog3B*2)
	Add	ZL, pir
	LPM
	mov	prg2, adr
	out	PORTB, prg2
	ret

.org $200

prog1A:
.DB $00, $00, $00, $00, $80, $40, $20, $10
.DB $08, $04
prog1B:
.DB $08, $04, $02, $01, $00, $00, $00, $00
.DB $00, $00

prog2A:
.DB $00, $00, $00, $00, $80, $C0, $E0, $F0
.DB $F8, $FC

prog2B:
.DB $08, $0C, $0E, $0F, $0F, $0F, $0F, $0F
.DB $0F, $0F

prog3A:
.DB $0C, $18, $30, $60, $C0, $80, $00, $00
.DB $0C, $08

prog3B:
.DB $00, $00, $00, $00, $00, $01, $03, $06
.DB $0C, $08

.EXIT

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Пт май 02, 2014 22:42:28
Alkul
Родион@22 писал(а):1) Метка есть, а где сам переход по метке?
Ну, начать с того, что объявление метки не накладывает обязанность на неё переходить.

Но вообще, если честно, Вы выбрали не самую лучшую программу для разбора. Давайте посмотрим и начнем с опроса АЦП.
Вы, кстати, скопировали текст с ошибкой (может, есть и еще, но пока заметил эту, очень важную) - перед строчками

Код: Выделить всё

;среднее арифметическое действие
ass:	nop
Вы пропустили команду rjmp awe, должно быть вот так:

Код: Выделить всё

      mov r7,r5
      inc tmp
      rjmp awe
;среднее арифметическое действие
ass:	nop
Посмотрите текст по Вашей ссылке и убедитесь сами. Но вообще - вся программа представляет собой какой-то бред сумасшедшего. Или писалась она на не совсем трезвую голову, или это шутка в стиле "найди 10 ошибок". Давайте посмотрим код опроса АЦП. Опустим даже то, что автор программы опрашивает АЦП не дожидаясь результата, давайте в логику вникнем:

Спойлер

Код: Выделить всё

        clr	tmp              ;обнуляем счетчик опросов
awe:	nop
	cpi	tmp, $04      ;количество опросов меньше четырех?
	brsh	 ass             ;если нет (сделано 4 опроса), то перейти на метку ass, иначе выполнить следующую команду
	clr	tmp3           ;сделано меньше 4-х опросов, обнулить рег.tmp3
	ldi	tmp3, $83	  ;занести в рег.tmp3 константу для выбора канала АЦП	
	out	ADMUX, tmp3	;выбрать канал АЦП
	clr	tmp2         ;обнулить tmp2
	clr	tmp3         ;обнулить tmp3
	ldi	tmp2, $C4		;занести в tmp2 константу для запуска преобразования АЦП (ЗАЧЕМ было перед этим обнулять tmp2 ?)
	out	ADCSR, tmp2		;запуск преобразования
WAIT:
        sbis ADCSR,ADIF    ;Если флаг ADIF установлен, пропустить следующую команду
        rjmp WAIT           ;Иначе флаг ADIF сброшен, преобразование не завершено, вернуться на метку WAIT для опроса флага

;Флаг ADIF установлен, преобразование завершено.

   in R16,ADCSR       ;Считать содержимое ADCSRA в рег.R16
   ori R16,(1<<ADIF)   ;Установить бит ADIF, не трогая остальные биты
   out ADCSR,R16      ;Занести в ADCSRA содержимое R16 c установленным битом ADIF для сброса флага ADIF

;Сохранение данных АЦП

	in	tmp2, ADCL      ;занести младший байт результата в рег.tmp2
	in	tmp3, ADCH     ;занести старший байт результата в рег.tmp3
	mov	r2, tmp2          ;скопировать младший байт результата в рег.r2
	mov	r3, tmp3          ;скопировать старший байт результата в рег.r3
	mov	r4, r2        ;скопировать младший байт результата из r2 в рег.r4
	mov	r5, r3        ;скопировать старший байт результата из r3 в рег.r5
	mov	r6, r4        ;скопировать младший байт результата из r4 в рег.r6
	mov	r7, r5        ;скопировать старший байт результата из r5 в рег.r7
	inc	tmp          ;инкремент (увеличение на единицу) счетчика опросов АЦП
        rjmp awe      ;возврат на повторный опрос АЦП, при этом младший и старший байты результата, хранящиеся
                           ;в регистрах tmp2 и tmp3 будут уничтожены про повторных инициализациях АЦП, а после получения
                           ;результата он вновь будет записан в регистры tmp2 и tmp3, после чего скопирован в регистры r2...r7
                           ;таким образом, после проведения четырех опросов АЦП результаты первых трех опросов будут
                           ;безвозвратно утеряны, а в регистрах tmp3:tmp2, r3:r2, r5:r4 и r7:r6 будут копии результата ПОСЛЕДНЕГО
                           ;опроса 
	
;среднее арифметическое действие

                              ;тут автор пытается считать какое-то среднее арифметическое по бредовому алгоритму, используя
                              ;в расчетах регистр r9, который ранее не инициализировался. После начала работы программы в ячейках
                              ;ОЗУ (в том числе и в регистрах) могут быть произвольные значения, то бишь "мусор". Любой регистр, прежде
                              ;чем он будет использоваться, должен быть инициализирован, это аксиома программирования. 
ass:	nop 
      clr	r8
	clc
	add	tmp2, r2
	adc	r9, r8     ;как можно выполнять эту команду при обнуленном r8 и неопределенном r9? 
                             ;Значение r9 НИГДЕ ранее не определено
В общем, Родион@22, не тратьте зря свое время. Нельзя по этой, с позволения сказать, "программе" ничему научиться.
Её нужно удалить к едрене фене и писать код заново, если уж вы так хотите сделать это устройство. А заодно схему переделать.
За каким, спрашивается... этим самым оцифровывать ADC3 , если к этому выводу подключен затвор транзистора Q9? Что автор разработки ожидает оттуда получить?

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Пт май 02, 2014 22:50:20
AIpp
1. А его может и не быть, это значит что туда программа приходит банально с предыдущей команды по порядку, а метка стоит для понятности или на будущее.
2. Разбираться в коде честно неохота, но для использования кнопок как минимум нужно реализовать антидребезг и вообще цикл их опроса. DIP наверняка опрашивают однократно на запуске и до выключения программе на его изменение плевать.
3. Вычисление среднего арифметического, очевидно (точнее двух). При беглом взгляде - идут суммирования и деления сдвигами.

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Пт май 02, 2014 22:55:19
Родион@22
ну я так подумал принцип довольно-таки прост:
нужно, чтобы конденсаторы дошли до порога срабатывания ADC=(3,8*1024)/1,1=3537=DD1h, потом активизация подпрограмм засветки светодиодов и выбираешь одну из них.
Почти как "Бегущие огни". Но проблема, в том что я не знаю как записать, что порог сработал, да и с кнопками есть проблемы :cry:

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Пт май 02, 2014 23:01:34
Alkul
Родион@22 писал(а):нужно, чтобы конденсаторы дошли до порога срабатывания ADC=(3,8*1024)/1,1=3537=DD1h, потом активизация подпрограмм засветки светодиодов и выбираешь одну из них.
Вы внимательно прочитали то, что я написал?
Схему смотрели? Куда подключен вывод ADC3 (PA3)? Что он "измеряет"? Будучи сконфигурирован как "выход" и подключенный к затвору полевого транзистора?
В моем предыдущем сообщении под спойлером я в комментариях разобрал часть кода, относящуюся к опросу АЦП. Вы сами видите, что в программе написан бред? Или не видите?

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Пт май 02, 2014 23:17:25
Родион@22
Вы сами видите, что в программе написан бред? Или не видите?
...Да.... вижу бессмыслица... :cry:
Значит надо использовать ADC0(PA0) - он то точно от кондеров отходит.
мне бы для начала организовать, то что понятнее более или менее:
Подпрограмма по возрастанию:
00000001
00000011
00000111
00001111
00011111
00111111
01111111
11111111
Подпрограмма по очереди:
00000001
00000010
00000100
00001000
00010000
00100000
01000000
10000000
подскажете? :?
По очереди вроде бы также как и "Обучалке":

Код: Выделить всё

Init:    ldi Temp,0b00000001  ;загрузка начального значения

Shift:   rcall Delay          ;вызов п/п Delay(вывод+задержка)
         cpi Temp,0b10000000  ;сравнить Temp с крайним значением
         breq Init            ;если равно - перейти на загрузку нач. значения

         lsl Temp             ;иначе - сдвиг влево
         rjmp Shift           ;перейти в начало цикла Shift

;Задержка

Delay:    out PortB,Temp

          ldi Temp1,0
          ldi Temp2,0
          ldi Temp3,10

Loop:     dec Temp1
          brne Loop

          dec Temp2
          brne Loop

          dec Temp3
          brne Loop

          ret

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Пт май 02, 2014 23:34:03
Alkul
Родион@22 писал(а): Значит надо использовать ADC0(PA0) - он то точно от кондеров отходит.
Да толку-то. Вы видите, что вывод PA0, кроме конденсаторов, заряжаемых фотоэлементом, еще подключен к анодам светодиодов?
Используются сверхяркие светодиоды.
Обычные светодиоды потребляют порядка 10-20 мА. Уж сверхяркие-то точно не меньше 20 мА для нормального свечения. У вас максимальный ток фотоэлемента 84 мА. 10 светодиодов по 20 мА - это сколько будет? Никакого свечения Вы не получите
Судя же по схеме, ток через светодиоды составит порядка 6-7 мА. Фотоэлемент это потянет на ярком свете, но только будет ли видно свечение сверхяркого светодиода, если пропускать через него 7 мА...
Родион, схему устройства нужно полностью перерабатывать. Бред что схема, что программа.
Родион@22 писал(а): Значит надо использовать ADC0(PA0) - он то точно от кондеров отходит.
То, что АЦП опрашивается четырежды, а учитываются только результат четвертого замера - это Вы увидели? Хоть какой канал АЦП используй при таком опросе, какая разница... То, что нужно переписывать весь опрос АЦП, Вам понятно? Хотя при такой схеме это не имеет никакого смысла.
Родион@22 писал(а): Подпрограмма по возрастанию:
00000001
00000011
00000111
00001111
00011111
00111111
01111111
11111111
Подпрограмма по очереди:
00000001
00000010
00000100
00001000
00010000
00100000
01000000
10000000
Я не понял, что Вы имеете в виду. Вы светодиоды хотите зажигать в такой последовательности?
"лог.1" означает зажженный светодиод? Используя линейку из 8 светодиодов?

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Пт май 02, 2014 23:41:41
Родион@22
Я не понял, что Вы имеете в виду. Вы светодиоды хотите зажигать в такой последовательности?
"лог.1" означает зажженный светодиод? Используя линейку из 8 светодиодов?
Вы все правильно подумали))

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Пт май 02, 2014 23:44:13
Родион@22
ну наверное автор имел ввиду, что светодиоды хоть и не яркие, зато под солнечной батареей будет видно(тень создает) :)) хотя батарея короче... тогда не понятно зачем нужны транзисторы, если ток 3 и 5 мА

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Пт май 02, 2014 23:48:50
Родион@22
Да толку-то. Вы видите, что вывод PA0, кроме конденсаторов, заряжаемых фотоэлементом, еще подключен к анодам светодиодов?
а ко входу AVCC тоже не вариант?

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Сб май 03, 2014 00:14:59
Alkul
Родион@22 писал(а):Вы все правильно подумали))
А чего тут сложного. Допустим,светодиоды подключены к порту A по схеме с общим катодом.
Если нужно зажигать светодиоды именно так - вначале по возрастанию, потом (после состояния 11111111) переходить к состоянию 00000001 и дальше делать сдвиг, то писать так:
Спойлер

Код: Выделить всё

;Главный цикл
MAIN:
rcall INCREM    ;Сделать цикл по возрастанию
rcall SHIFT    ;Сделать цикл по сдвигу
rjmp MAIN    ;Вернуться и повторить цикл по возрастанию

;Цикл зажигания по возрастанию
INCREM:
ldi R17,0x08       ;Инициализировать счетчик на 8
ldi R16,0x01       ;Начальное состояние порта
INCREM1:  out PORTA,R16  ;вывести в порт содержимое рег. R16
rcall DELAY       ;Выполнить задержку
sec         ;установить флаг Carry (флаг переноса)
rol R16   ;выполнить ротацию рег.R16, при этом бит Carry вдвигается в бит 0 рег.R16,
             ;а старший бит после ротации выдвигается в бит Carry
dec R17 ;Декремент (уменьшение на 1) счетчика сдвигов
brne INCREM1 ;Если выполнены не все сдвиги, вернуться на метку INCREM1
ret     ;Иначе выполнены все сдвиги, выйти из подпрограммы

;Цикл зажигания со сдвигом
SHIFT:
ldi R17,0x08       ;Инициализировать счетчик на 8
ldi R16,0x01       ;Начальное состояние порта
SHIFT1: out PORTA,R16    ;вывести в порт содержимое рег. R16
rcall DELAY         ;Выполнить задержку
lsl R16        ;выполнить сдвиг рег.R16 влево, при этом в младший бит заносится 0
dec R17      ;Декремент (уменьшение на 1) счетчика сдвигов
brne SHIFT1  ;Если выполнены не все сдвиги, вернуться на метку SHIFT1
ret     ;Иначе выполнены все сдвиги, выйти из подпрограммы

;Подпрограмма задержки
DELAY:
;Задержка нулевая, для написания задержки нужно знать, под какой МК её писать и как реализовывать -
;по прерыванию или прокруткой в "пустом цикле", а также нужно знать время задержки
ret
Родион@22 писал(а):а ко входу AVCC тоже не вариант?
При чем тут вход AVCC. Он на схеме вообще неверно сделан. Если используется АЦП, то AVCC нужно подключать через LC-цепь, как показано в даташите. Я Вам уже писал об этом, если не ошибаюсь. Откройте даташит на ATtiny26 и посмотрите.

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Сб май 03, 2014 00:21:04
Родион@22
вы не ошибаетесь - ошибаюсь я :cry:

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Сб май 03, 2014 00:23:35
Родион@22
А чего тут сложного.
А так ведь еще две кнопки: одна отвечает за подпрограмму по возрастанию, другая - по очереди

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Сб май 03, 2014 00:28:11
Alkul
Родион@22 писал(а):А так ведь еще две кнопки: одна отвечает за подпрограмму по возрастанию, другая - по очереди
Вы хоть алгоритм опишите. Один цикл сдвига после однократного нажатия на кнопку, следующий цикл только после отпускания и следующего нажатия, или же пока кнопку держать нажатой, цикл будет крутиться...
Опишите.
Только сделаю я это завтра вечером, сейчас уже поздно. Полтретьего ночи.

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Сб май 03, 2014 00:38:00
Родион@22
для написания задержки нужно знать, под какой МК её писать и как реализовывать - по прерыванию или прокруткой в "пустом цикле", а также нужно знать время задержки
А пример из "Обучалки" никак не подойдет?

Код: Выделить всё

;Задержка

Delay:    out PortB,Temp

          ldi Temp1,0
          ldi Temp2,0
          ldi Temp3,10

Loop:     dec Temp1
          brne Loop

          dec Temp2
          brne Loop

          dec Temp3
          brne Loop

          ret
или все же с помощью таймера?

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Сб май 03, 2014 01:12:10
Родион@22
Простите, что уж так надоедаю :oops: (просто вторую неделю все изучаю и редактирую)
Вы хоть алгоритм опишите.
Кнопка - без фиксации.
1-ая кнопка:
Нажал пошла подпрограмма "по возрастанию"
2-ая кнопка:
Нажал пошла подпрограмма "по очереди"

[img][img]http://img.radiokot.ru/files/96849/thumbnail/bx7xsenyc.jpg[/img][/img]

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Сб май 03, 2014 10:59:21
Jack_A
Родион@22, к слову, выкладывая такие "простыни", надо их спойлерами прикрывать, а то модер ата-та по попе устроит.

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Сб май 03, 2014 21:53:34
Alkul
Родион@22 писал(а):А пример из "Обучалки" никак не подойдет?
Подойдет, если Вы пишете простую программу, которая ничем больше, кроме моргания светодиодами не занимается.
Вот в таком виде при работе МК на частоте 8 МГц подпрограмма задержки будет выполняться 320 мс.
Спойлер

Код: Выделить всё

Delay:    
          ldi R16,0
          ldi R17,0
          ldi R18,13

Loop:     dec R16
          brne Loop

          dec R17
          brne Loop

          dec R18
          brne Loop

          ret
Родион@22 писал(а): Кнопка - без фиксации.
1-ая кнопка:
Нажал пошла подпрограмма "по возрастанию"
2-ая кнопка:
Нажал пошла подпрограмма "по очереди"
Да проще простого, под спойлером текст программы. Конечно, я подразумеваю, что инициализацию таблицы векторов прерываний, инициализацию указателя вершины стека и настройку портов Вы сделаете самостоятельно. В моем листинге ничего этого нет. Только суть.
Спойлер

Код: Выделить всё

;Определение имен кнопок. Кнопки подключены к "земле", выводы, к которым подключены кнопки, должны быть
;сконфигурированы как входы с активированными pull-up резисторами (резисторами подтяжки к "плюсу" питания).
;При этом когда кнопка нажата, с вывода, к которому она подключены, читается лог.0, когда отпущена - лог.1
.equ  BUT1=0x00       ;Кнопка 1 подключена к нулевому биту(выводу) порта
.equ  BUT2=0x01       ;Кнопка 2 подключена к первому биту(выводу) порта
.equ  BUTTON=0x16	;Определение имени порта, к которому подключены кнопки, как PINB
.equ	LED= 0x1b       ;Определение имени порта, к которому подключены светодиоды, как PORTA

;Начальный цикл опроса кнопок
MAIN:
sbis BUTTON,BUT1        ;Кнопка 1 нажата? Если нет, то пропустить следующую команду
rjmp M_BUT1       ;Иначе кнопка 1 нажата, перейти на "антидребезговый" опрос кнопки 1
sbis BUTTON,BUT2       ;Кнопка 2 нажата? Если нет, то то пропустить следующую команду
rjmp M_BUT2       ;Иначе кнопка 2 нажата, перейти на "антидребезговый" опрос кнопки 2
rjmp MAIN        ;Иначе вернуться на начало опроса кнопок

;"Антидребезговый" опрос кнопки 1
M_BUT1:
sbis BUTTON,BUT1  ;Если кнопка 1 отпущена, пропустить следующую команду
rjmp M_BUT1      ;Иначе кнопка 1 все еще нажата, вернуться на опрос кнопки 1
rcall DELAY      ;Кнопка 1 отпущена, выполнить антидребезговую задержку
rjmp INCREM      ;Переход на выполнение подпрограммы "по возрастанию"

;"Антидребезговый" опрос кнопки 1
M_BUT2:
sbis BUTTON,BUT2  ;Если кнопка 2 отпущена, пропустить следующую команду
rjmp M_BUT2      ;Иначе кнопка 2 все еще нажата, вернуться на опрос кнопки 2
rcall DELAY      ;Кнопка 2 отпущена, выполнить антидребезговую задержку
rjmp SHIFT      ;Переход на выполнение подпрограммы "по очереди" 

;Цикл зажигания по возрастанию
INCREM:
ldi R17,0x08       ;Инициализировать счетчик на 8
ldi R16,0x01       ;Начальное состояние порта
INCREM1:  out LED,R16    ;вывести в порт содержимое рег. R16
rcall DELAY       ;Выполнить задержку
sec         ;установить флаг Carry (флаг переноса)
rol R16        ;выполнить ротацию рег.R16, при этом бит Carry вдвигается в бит 0 рег.R16,
             ;а старший бит после ротации выдвигается в бит Carry
dec R17         ;Декремент (уменьшение на 1) счетчика сдвигов
sbis BUTTON,BUT2   ;Кнопка 2 нажата? Если нет, то продолжаем "возрастание", пропустить следующую команду
rjmp MAIN        ;Иначе нажата кнопка 2, прервать возрастание, вернуться на опрос кнопок
brne INCREM1    ;Если выполнены не все сдвиги, вернуться на метку INCREM1
rjmp INCREM     ;Иначе выполнены все сдвиги, вернуться на метку INCREM для повторения сдвигов

;Цикл зажигания по очереди
SHIFT:
ldi R17,0x08       ;Инициализировать счетчик на 8
ldi R16,0x01       ;Начальное состояние порта
SHIFT1: out LED,R16     ;вывести в порт содержимое рег. R16
rcall DELAY         ;Выполнить задержку
lsl R16         ;выполнить сдвиг рег.R16 влево, при этом в младший бит заносится 0
dec R17           ;Декремент (уменьшение на 1) счетчика сдвигов
sbis BUTTON,BUT1   ;Кнопка 1 нажата? Если нет, то продолжаем "возрастание", пропустить следующую команду
rjmp MAIN        ;Иначе нажата кнопка 1, прервать возрастание, вернуться на опрос кнопок
brne SHIFT1     ;Если выполнены не все сдвиги, вернуться на метку SHIFT1
rjmp SHIFT     ;Иначе выполнены все сдвиги, вернуться на метку SHIFT для повторения сдвигов

;Подпрограмма задержки 320 мс (на частоте 8 МГц)
DELAY:
          push R16     ;Сохранить на стеке
          push R17     ;используемые
          push R18     ;подпрограммой регистры
          ldi R16,0      ;Инициализация
          ldi R17,0      ;трех циклов
          ldi R18,13    ;ожидания

Loop:     dec R16
          brne Loop

          dec R17
          brne Loop

          dec R18
          brne Loop
          pop R18      ;Восстановить
          pop R17      ;из стека
          pop R16      ;используемые регистры
          ret              ;Выход из подпрограммы задержки

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Сб май 03, 2014 22:44:36
Родион@22
Спасибо, Вам, что хоть это написали, не каждый ведь возмется. :))
Подойдет, если Вы пишете простую программу, которая ничем больше, кроме моргания светодиодами не занимается.
А если добавить программу, которая определяет, что конденсаторы дошли до порога срабатывания ADC=(3,8*1024)/1,1=3537=DD1h, потом активизация подпрограмм засветки светодиодов, то уже никак не подойдет?

Re: Вопросы по программированию AVR на ассемблере

Добавлено: Сб май 03, 2014 22:56:34
Alkul
Родион@22 писал(а):А если добавить программу, которая определяет, что конденсаторы дошли до порога срабатывания ADC=(3,8*1024)/1,1=3537=DD1h, потом активизация подпрограмм засветки светодиодов, то уже никак не подойдет?
Не знаю, прикидывать надо. Работу с АЦП однозначно делать через прерывания.
Но я так понимаю, Вы все же хотите попытаться оживить мертворожденный проект (я про ту схему)?. Если да, то мне жаль тратить на это время.
С программой, реализующей конкретный алгоритм (управление светодиодами) я Вам помог.
Та схема, что так упорно хотите сделать Вы, работать не будет. А значит, бессмысленно рассуждать о реализации программы. Стыковать написанный мной код со сферическим конем в вакууме нет никакого желания.