Теория и практика AVR ассемблера.

Обсуждаем контроллеры компании Atmel.
Ответить
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич

Сообщение Alexeyslav »

Не, че... нормально на безрыбье и рак рыба. Как вспомню веселые времена, когда еще контроллеров небыло а была 537РФ5, 537Ру2 и Z80... при отсутствии программатора и компилятора вполне можно писать программы. Правда любой сбой - набивай программу сначала... А потом принцип матрешки - вручную набиваешь программу которая позволит прошить чистую 537РФ5(для режима прошивки надо только 20 вольт подать) и заносишь туда при помощи 16 кнопок и схемы на логике в 15-ричном виде программу, которая позволит организовать более простой ввод кодов и программирование и пошло поехало... Дошел до подключения ЖК индикатора на 8 строк 20 символов, и уже было пытался подключить винчестер... но там не срослось по электрической части, он даже стартовать не хотел на наколхозенных проводках - слишком высоки пусковые токи. И так все забросилось. Оно даже досихпор работает.

Кстати, можно не подпаиваться к микросхеме чтобы получить доступ к сигналам BitBang - можно взять обычные швейные или канцелярские иголки и наколхозить конструкцию так чтобы они держались с упором на нужные выводы - время жизни такой конструкции = времени на программирование одного контроллера под программатор. Потом конструкцию из иголок и подпорок разбираешь и забываешь как страшный сон.
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 6339
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

АндрейАвербах писал(а):Слева на право?
Да. 3-рядный разъем -- под монитор.
Реклама
Потрогал лапой паяльник
Сообщения: 345
Зарегистрирован: Пт авг 24, 2012 09:45:40
Откуда: Абакан, Хакасия

Сообщение АндрейАвербах »

4 - не знаю
Я ж туда флэшки втыкаю :)
А, и как заставить аврстудию 6 выполнить действие 50176 раз (нужно для прерывания)?
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

4 - не знаю
Jack_A, USB не признали, хоть он и кверху ногами :shock: :))) ?
АндрейАвербах писал(а):А, и как заставить аврстудию 6 выполнить действие 50176 раз (нужно для прерывания)?
Какое такое действие??? Вам цикл что ли нужно 50176 раз выполнить? И причем тут прерывание, поподробнее...
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 6339
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

Engineer_Keen писал(а): Jack_A, USB не признали, хоть он и кверху ногами :shock: :))) ?
Меня смутили 2 пружинки-защелки, думаю : у USB не может быть 2 контакта! А на бочок своего бука лень было взглянуть. Позор на мою седую лысину ! Только нерезкость фото меня может реблитировать.
Итак, это USB.
---------------------
-- Кто сказал вчера, что вода кипит при 100 градусах ?
-- Я.
-- Правильно, Вовочка. А 90 градусов, дети, -- это прямой угол.
Реклама
Потрогал лапой паяльник
Сообщения: 345
Зарегистрирован: Пт авг 24, 2012 09:45:40
Откуда: Абакан, Хакасия

Сообщение АндрейАвербах »

Ночью пришла мне в голову идея, заключается она в следующем: контроллер может делать ШИМ, а я слышал, что с помощью ШИМ можно воспроизводить различные звуки, а если можно воспроизводить звуки, значит можно сделать синтезатор речи аля говорящий компьютер. :) Как-то так.
Кто-то уже пробовал что-либо подобное? И моя идея вообще осуществима?
Какое такое действие??? Вам цикл что ли нужно 50176 раз выполнить? И причем тут прерывание, поподробнее...
Ну, есть программка, которая должна одновременно мигать светодиодом, и следить за состоянием входа, как только на входе 1, зажечь диод на другой ножке. Главный светодиод мигает независимо от обстановки. Для того, чтобы мигать светодиодом я использую прерывание таймера, 50176, время задержки в микросекундах, тут я малян ошибся. \
Вот короче код

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

.org 0x0000 ;вектора прерываний
	rjmp Reset
	.org 0x0001
	rjmp EXT_INT0
	.org 0x0002
	rjmp PCINT
	.org 0x0003
	rjmp TIM0_OVF
	.org 0x0004
	rjmp EE_RDY
	.org 0x0005
	rjmp ANA_COMP
	.org 0x0006
	rjmp TIM0_COMPA
	.org 0x0007
	rjmp TIM0_COMPB
	.org 0x0008
	rjmp WATCHDOG
	.org 0x0009
	rjmp ADC_

;Reset:
EXT_INT0:
PCINT:
TIM0_OVF:
EE_RDY:
ANA_COMP:
;TIM0_COMPA:
TIM0_COMPB:
WATCHDOG:
ADC_:
RETI

TIM0_COMPA:
	com R19
	breq l
	ldi R20, 0b000000
	mov R21, R20
	add R21, R18
	out PORTB, R21
	rjmp e
l:  ldi R20, 0b000001
    mov R21, R20
	add R21, R18
	out PORTB, R21
e:  ldi R16, 0            ;обнуление таймера
	out TCNT0, R16
	reti
Reset:	ldi R16, low(ramend)
	out SPL, R16
	ldi R16, 0b101111
	out DDRB, R16
	ldi R16, 0x04         ;разрешение прерываний компаратора 
	out TIMSK0, R16
	ldi R16, 0b00000100   ;выбор частоты счетчика
	out TCCR0B, R16
	ldi R16, 0b11000100   ;число для сравнения
	out OCR0A, R16
	ldi R16, 0            ;обнуление таймера
	out TCNT0, R16
	ldi R19, 0b11111111
	sei
st1: 
	in R17, PINB
	lsr R17
	lsr R17
	lsr R17
	lsr R17
	cpi R17, 0b000001
	
	breq n1
	
	cpi R18, 0b001000
	brne n
	CLR R18
	mov R22, R18
	add R22, R20
	out PORTB, R22
	rjmp n
n1: rcall led
n:
	rjmp st1

led: ldi R18, 0b001000
	mov R22, R18
	add R22, R20
	out PORTB, R22
	ret
Реклама
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Оййй, ёёёёёё... :o :kill:
АндрейАвербах писал(а):Вот короче код
Код действительно короче. :)
А главная программа не глючит?

Ладно, не буду томить.
При входе в обработчик прерывания надо сохранять состояние регистров, а при выходе восстанавливать.
У AVR-ок при входе в прерывание сохраняется только адрес возврата. Остальное надо в коде делать.
Даже если у вас регистры строго распределены между основной программой и прерыванием, то остаётся регистр состояния SREG, который, как правило, надо сохранять и восстанавливать.
Вот пример.
Спойлер

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

TIM0_COMPA:
push r0 ; сохраняем в стэк r0
in    r0,SREG ; загружаем sreg
push r0 ; сохраняем в стэк sreg
push r1 ; сохраняем другие регистры если необходимо
push r2

; основной код обработчика

pop r2 ;восстанавливаем из стэка (в обратном порядке !!!)
pop r1
pop r0
out SREG, r0
pop r0
reti
Есть, конечно, случаи, когда можно и sreg не сохранять. Но это отдельная тема.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Потрогал лапой паяльник
Сообщения: 345
Зарегистрирован: Пт авг 24, 2012 09:45:40
Откуда: Абакан, Хакасия

Сообщение АндрейАвербах »

Да вроде не глючит, в симуляторе работает как надо, программатор недельки через две придет, проверю в железе.
Есть еще такой вариант.

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

ldi R16, 0b101111
	out DDRB, R16
	ldi R16, low (ramend)
	out SPL, R16
	clr R23
	clr R25
	ldi R24, 0b11111111
st1:	in R17, PINB
	lsr R17
	lsr R17
	lsr R17
	lsr R17
	cpi R17, 0b000001
	brne m
	rcall led
	rjmp e
m:	clr R18 
	mov R22, R20
	add R22, R18
	out PORTB, R22
e:	dec R23
	brne st1
	dec R25
	brne st1
	rcall stroboskop
	rjmp st1

	led:
		ldi R18, 0b001000
		mov R22, R20
		add R22, R18
		out PORTB, R22
		ret

	stroboskop:
		com R24
		cpi R24, 0b00000000
		brne s2
		ldi R20, 0b000001
		mov R22, R18
		add R22, R20
		out PORTB, R22
		rjmp en
	s2: ldi R20, 0b000000
	mov R22, R18
		add R22, R20
		out PORTB, R22
	en: ret
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Если вы не сохраняете состояние регистров используемых в коде, который может быть прерван работой прерывания, то, независимо от "варианта", это потенциальный источник глюков.
Это понятно или пример нужен?
Последний раз редактировалось Kavka Пт май 31, 2013 07:41:13, всего редактировалось 1 раз.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

АндрейАвербах писал(а):...а я слышал, что с помощью ШИМ можно воспроизводить различные звуки, а если можно воспроизводить звуки
гляньте здесь
Потрогал лапой паяльник
Сообщения: 345
Зарегистрирован: Пт авг 24, 2012 09:45:40
Откуда: Абакан, Хакасия

Сообщение АндрейАвербах »

Лучше пример.
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

АндрейАвербах писал(а):Лучше пример.
Синус с частотой F/256/128
F - частота контроллера, 256 - разрешение таймера (8 бит), частота квантования получается 8МГц/256=31250 Гц
128 - число семплов, частота синуса получается 31250/128=244Гц
Спойлер

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

.include "tn2313def.inc"
	.macro	OUTI ;просто для сокращения размера кода
	LDI	R16,@1
	OUT	@0,R16
	.endm
.cseg
.org 0
	RJMP 	START	 	;RESET
.org	OVF0addr	
	RJMP	SND_OUT		;T0 OVERFLOW
//-------------------Program start----------------//
START:
	LDI	R16,low(ramend);стек
	OUT	SPL,R16
	SBI	DDRB,PB2 ;PB2 - выход
	OUTI	TCCR0A,(1<<COM0A1)|(1<<WGM01)|(1<<WGM00) ;режим FastPWM, PB2 вкл при TCNT=0, выкл в TCNT=OCR0A
	OUTI	TCCR0B,(1<<CS00) ;делитель=1
	OUTI	TIMSK,(1<<TOIE0) ;вкл прерывание по переполнению таймера0
	LDI	ZL,low(sine*2) ;загружаем в ZH:ZL адрес начала таблицы
	LDI	ZH,high(sine*2)
	SEI ;включаем прерывания
LOOP:	RJMP	LOOP ;ничего не делаем
SND_OUT:LPM	R16,Z+ ;в прерывании читаем семпл из флеша
	OUT	OCR0A,R16 ;выводим в PWM
	CBR	ZL,0x80; делаем так чтобы адрес был в пределах таблицы: (SINE) ~ (SINE+128)
	LDI	ZH,high(sine*2)
	RETI
.org	0x0100
SINE: ;таблица семплов синуса, 128 штук
.DB	0x80,0x86,0x8c,0x92,0x98,0x9f,0xa5,0xab,0xb0,0xb6,0xbc,0xc1,0xc7,0xcc,0xd1,0xd5
.DB	0xda,0xde,0xe2,0xe6,0xea,0xed,0xf0,0xf3,0xf5,0xf7,0xf9,0xfb,0xfc,0xfd,0xfe,0xfe
.DB	0xfe,0xfe,0xfe,0xfd,0xfc,0xfa,0xf8,0xf6,0xf4,0xf1,0xef,0xeb,0xe8,0xe4,0xe0,0xdc
.DB	0xd8,0xd3,0xce,0xc9,0xc4,0xbf,0xb9,0xb3,0xae,0xa8,0xa2,0x9c,0x95,0x8f,0x89,0x83
.DB	0x7c,0x76,0x70,0x6a,0x63,0x5d,0x57,0x51,0x4c,0x46,0x40,0x3b,0x36,0x31,0x2c,0x27
.DB	0x23,0x1f,0x1b,0x17,0x14,0x10,0x0e,0x0b,0x09,0x07,0x05,0x03,0x02,0x01,0x01,0x01
.DB	0x01,0x01,0x02,0x03,0x04,0x06,0x08,0x0a,0x0c,0x0f,0x12,0x15,0x19,0x1d,0x21,0x25
.DB	0x2a,0x2e,0x33,0x38,0x3e,0x43,0x49,0x4f,0x54,0x5a,0x60,0x67,0x6d,0x73,0x79,0x80
А вообще звук генерируется 2мя способами:
1) воспроизведение сигнала по таблице или какой-либо формуле - тогда много памяти не нужно, так работают простые синтезаторы, генераторы, музыкальные шкатулки, звонки и прочее.
2) воспроизведение ранее записанного сигнала из файла - тут нужна память размером с длину файла, так работают WAV-плееры, диктофоны, в т.ч. и для синтезатора речи придется скорее всего использовать этот способ
Друг Кота
Аватара пользователя
Сообщения: 6339
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

Т.е. МР3 не существует в природе ? Можно хранить в формате МР3, но для раскодировки МР3 нужен быстрый процессор. Зато памяти нужно меньше.
Потрогал лапой паяльник
Сообщения: 345
Зарегистрирован: Пт авг 24, 2012 09:45:40
Откуда: Абакан, Хакасия

Сообщение АндрейАвербах »

Kavka писал(а):Если вы не сохраняете состояние регистров используемых в коде, который может быть прерван работой прерывания, то, независимо от "варианта", это потенциальный источник глюков.
Это понятно или пример нужен?
Лучше показать на примере.

Вроде исправил.

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

ldi R16, 0b101111
	out DDRB, R16
	ldi R16, low (ramend)
	out SPL, R16
	clr R23
	clr R25
	ldi R24, 0b11111111
st1:	in R17, PINB
	lsr R17
	lsr R17
	lsr R17
	lsr R17
	cpi R17, 0b000001
	brne m
	rcall led
	rjmp e
m:	clr R18 
	mov R22, R20
	add R22, R18
	out PORTB, R22
e:	dec R23
	brne st1
	dec R25
	brne st1
	rcall stroboskop
	rjmp st1

	led:
		ldi R18, 0b001000
		mov R22, R20
		add R22, R18
		out PORTB, R22
		ret

	stroboskop:
		in R26, SREG
		push R26
		com R24
		cpi R24, 0b00000000
		brne s2
		ldi R20, 0b000001
		mov R22, R18
		add R22, R20
		out PORTB, R22
		rjmp en
	s2: ldi R20, 0b000000
	mov R22, R18
		add R22, R20
		out PORTB, R22
		pop R26
		out SREG, R26
	en: ret
Последний раз редактировалось АндрейАвербах Пт май 31, 2013 11:02:46, всего редактировалось 1 раз.
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

MP3 тоже относится к 2му типу, только помимо памяти нужно еще и кодек подключать, речь-то про AVR, а его для раскодировки не хватит. То же самое касается и OGG и остальных форматов, не перечислять же их все...
АндрейАвербах писал(а): Лучше показать на примере.
Представим простейший бегущий огонь на 16 ног (код дан отрывками):

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

SEI
LDI R16,0x80 ;горит крайний левый диод
LDI R17,0x00
OUT PORTA,R16 ;выводим в порты
OUT PORTB,R17
LOOP:
ROR R16 ;сдвигаем бит вправо через флаг C
ROR R17
OUT PORTA,R16 ;выводим в порты
OUT PORTB,R17
RCALL DELAY ;ждем допустим 1 сек
RJMP LOOP
Допустим внезапно между строками ROR R16-ROR R17 случилось прерывание, когда ROR R16 дало 0 в R16 и 1 в C:

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

INT0_IRQ:
CP R1,R2 ;сравниваем какие-то регистры
BRNE LESS ;все, теперь флаг С зависит от результата операции CP
NOP
LESS:
NOP
RETI
Если в результате прерывания С сбросится, то все огни потухнут, так как ROR R17 даст 0
Обратная ситуация, прерывание между ROR-ROR возникло при С=0 и в результате С стало 1 - будут бегать лишние огни.
Последний раз редактировалось Engineer_Keen Пт май 31, 2013 11:13:38, всего редактировалось 1 раз.
Потрогал лапой паяльник
Сообщения: 345
Зарегистрирован: Пт авг 24, 2012 09:45:40
Откуда: Абакан, Хакасия

Сообщение АндрейАвербах »

см. два поста вверх.
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Пример.

Самый простой. Допустим в основной программе задействованы абсолютно все регистры. Что будете делать в прерывании?

Ещё один.
Обработчик прерывания регистры не сохраняет и не восстанавливает.
И пусть в конце работы он оставляет установленным флаг С.

Главная программа.
Например вы складываете два 4х байтных числа:
Оба равны 1.
add r0,r4 ; 1+1=2, С=0
adc r1,r5 ; 0+0+C=0, С=0
adc r2,r6 ; 0+0+C=0, С=0
adc r3,r7 ; 0+0+C=0, С=0
Результат 0x00000002 - правильно.

А теперь всё тоже самое, но происходит прерывание между любыми из этих инструкций на выходе которого установлен флаг С.
add r0,r4 ; 1+1=2, С=0
adc r1,r5 ; 0+0+C=0, С=0
; прерывание после которого C=1
adc r2,r6 ; 0+0+C=1, С=0
adc r3,r7 ; 0+0+C=0, С=0
Результат 0x00010002 = 6553810
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Потрогал лапой паяльник
Сообщения: 345
Зарегистрирован: Пт авг 24, 2012 09:45:40
Откуда: Абакан, Хакасия

Сообщение АндрейАвербах »

В моем случае такого вроде нет, хотя могу ошибиться.
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Для проверки в начале каждой подпрограммы, в т.ч. прерывании нужно камент написать, какие ресурсы используются, и какие при этом "портятся", а потом пройтись по всей программе и проверить, чтобы ресурсы не пересекались (если конечно это не предусмотрено целью программы).
пример:

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

   led: ;используется: R20, ломается: R18,R22,SREG
      ldi R18, 0b001000
      mov R22, R20
      add R22, R18
      out PORTB, R22
      ret
   stroboskop: Используется:R18, SREG, ломается:R20,R22,R24,R26
      in R26, SREG
      push R26
      com R24
      cpi R24, 0b00000000
      brne s2
      ldi R20, 0b000001
      mov R22, R18
      add R22, R20
      out PORTB, R22
      rjmp en
   s2: ldi R20, 0b000000
   mov R22, R18
      add R22, R20
      out PORTB, R22
      pop R26
      out SREG, R26
   en: ret
Совет: беречь регистры начиная с R26, так как они используются для 16-битной адресации (X, Y, Z), например в коде выше можно R26 заменить на R22, а R22 на один из младших регистров R0-R15 :idea:

Совет2: после com сравнивать с 0 не обязательно, com сам ставит флаг Z если надо (команда BRNE проверяет именно флаг Z), таким образом с R24 снимается ограничение на использование только старшей половины регистров (команда cpi работает только с ними) и вместо него можно взять более дешевые R0-R15 :idea:

совет3: если есть лишний регистр, который вообще нигде в программе не используется, можно использовать для сохранения SREG его во всех подпрограммах, тогда не нужно его каждый раз PUSH-POP-ить (каждый PUSH или POP - это 2 такта и отъединение одного байта от ОЗУ)
Потрогал лапой паяльник
Сообщения: 345
Зарегистрирован: Пт авг 24, 2012 09:45:40
Откуда: Абакан, Хакасия

Сообщение АндрейАвербах »

Ну упрощенно мою прогу можно представить так:



загрузка

\/
Прочесть состояние входа.
Равно X? Нет ->-
Да |
\/ |
Зажечь светодиод |
Прыгнуть в конец |
Основного цикла |
Погасить светодиод <---
Конец основного цикла: Уменьшить значение регистра-
счетчика
Счетчик равен нулю? Нет--------------
\/ |
Да |
Зажечь(погасить) стробоскоп |
В начало цикла <--------------------
Ответить

Вернуться в «AVR»