Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 6347
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

Ну вот, уже баланс скобок появился. Все, оказывается, не так уж безнадежно. Вместо фиксированного delay200ms появился задающий время параметр. Теперь под пытками будет вытянуто: в чем он передается? Сама подпрограмма задержки будет библиотечная, и она сработает на 1200-м? Тогда в чем смысл переписки на асм? И сакральные мантры PORTB=0x1C; тоже имеют магический смысл?
Если бы в Радиокоте провели конкурс на самое замудомудренное описание самой простейшей задачки - вот кандидат на победителя.
Изображение
Реклама
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Jack_A писал(а):...
Многократный вывод в порт - аналог асм команд nop или rjmp PC+1. Только товарищ просит меандр, а по программе ни хрена не меандр.
Контактная информация:
Реклама
Потрогал лапой паяльник
Сообщения: 315
Зарегистрирован: Пт янв 29, 2010 19:42:27

Сообщение 12val12 »

Заработало можно сказать с НУЛЕВОГО раза т е мгновенно
скопировал аsm листинг main с кодевижена .
на всяк случай оставил инит выклченного компаратора. задержка с прошлого проекта
заполнение 55 % включается выключается . можно сказать меандр .
Все
подправил вторую задержку до 0.3 сек лучше срабатывает кнопка

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

    .INCLUDE "1200def.inc"
   .equ   Fo=4000000
 ;NAME DEFINITIONS FOR GLOBAL VARIABLES ALLOCATED TO REGISTERS
    .def   COUNTER=R20   
	.DEF _PowerOn=R3  
   .CSEG
.ORG   $0000
   RJMP   INIT ; Reset Handler
   RJMP EXT_INT0 ; IRQ0 Handler
;.ORG   $0006
.ORG   $0002
  CLI
EXT_INT0:
INIT:
; 0000 0071 // Analog Comparator initialization
; 0000 0072 // Analog Comparator: Off
; 0000 0073 // The Analog Comparator's positive input is
; 0000 0074 // connected to the AIN0 pin
; 0000 0075 // The Analog Comparator's negative input is
; 0000 0076 // connected to the AIN1 pin
; 0000 0077 ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
	LDI  R30,LOW(128)
	OUT  0x8,R30
; 0000 0078 // Digital input buffer on AIN0: On
; 0000 0079 // Digital input buffer on AIN1: On
; 0000 007A DIDR=(0<<AIN0D) | (0<<AIN1D);
	LDI  R30,LOW(0)
	OUT  0x1,R30
; 0000 007B 
; 0000 007C 
; 0000 007D 
; 0000 007E 
; 0000 007F DDRD=0x00;PORTD=0x01;
	OUT  0x11,R30
	LDI  R30,LOW(1)
	OUT  0x12,R30
; 0000 0080 DDRB=0x1C;PORTB=0x00;
	LDI  R30,LOW(28)
	OUT  0x17,R30
	LDI  R30,LOW(0)
	OUT  0x18,R30
; 0000 0081 PowerOn=1;
	LDI  R30,LOW(1)
	MOV  R3,R30
; 0000 0082 while (1)
_0x3:
; 0000 0083 {
; 0000 0084    if (PIND.0 ==0)
	SBIC 0x10,0
	RJMP _0x6
; 0000 0085 
; 0000 0086      {   PORTB=0x1C;
	LDI  R30,LOW(28)
	OUT  0x18,R30
; 0000 0087          delay_ms(100);
 ; ------------------------ 
   LDI   R20,BYTE3(100*Fo/1000/5)
   LDI   R21,BYTE2(100*Fo/1000/5)
   LDI   R22,BYTE1(100*Fo/1000/5)
   RCALL   DELAY
; 0000 0088          PORTB=0x0;
	LDI  R30,LOW(0)
	OUT  0x18,R30
; 0000 0089         if (PIND.0 ==0 )
	SBIC 0x10,0
	RJMP _0x7
; 0000 008A           {  if ( PowerOn==0)  PowerOn=1;
	TST  R3
	BRNE _0x8
	LDI  R30,LOW(1)
	MOV  R3,R30
; 0000 008B                  else  PowerOn=0;
	RJMP _0x9
_0x8:
	CLR  R3
; 0000 008C                 delay_ms(300);
_0x9:
   LDI   R20,BYTE3(300*Fo/1000/5)
   LDI   R21,BYTE2(300*Fo/1000/5)
   LDI   R22,BYTE1(300*Fo/1000/5)
   RCALL   DELAY
; 0000 008D            }
; 0000 008E        }
_0x7:
; 0000 008F if (PowerOn==1)
_0x6:
	LDI  R30,LOW(1)
	CP   R30,R3
	BRNE _0xA
; 0000 0090   {
; 0000 0091     PORTB=0x1C;
	LDI  R30,LOW(28)
	OUT  0x18,R30
; 0000 0092     PORTB=0x1C;
	OUT  0x18,R30
; 0000 0093     PORTB=0x1C;
	OUT  0x18,R30
; 0000 0094     PORTB=0x1C;
	OUT  0x18,R30
; 0000 0095     PORTB=0x1C;
	OUT  0x18,R30
; 0000 0096     PORTB=0x1C;
	OUT  0x18,R30
; 0000 0097     PORTB=0x1C;
	OUT  0x18,R30
; 0000 0098     PORTB=0x1C;
	OUT  0x18,R30
; 0000 0099     PORTB=0x1C;
	OUT  0x18,R30
; 0000 009A     PORTB=0x1C;
	OUT  0x18,R30
; 0000 009B     PORTB=0x0;
	LDI  R30,LOW(0)
	OUT  0x18,R30
; 0000 009C    }
; 0000 009D    }
_0xA:
	RJMP _0x3
; 0000 009E 
; 0000 009F   }
_0xB:
	RJMP _0xB
; .FEND



 
;
;
;-----------------------------
DELAY:
   SUBI   R22,BYTE1(1)
   SBCI   R21,BYTE2(1)
   SBCI   R20,BYTE3(1)
   BRNE   DELAY
   RET

спасибо тов akl за процедуру задержки .
ух ты.... показывает
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Алгоритм работы:
1 - Ждем нажатия кнопки.
Если не нажато, то п. 1.
Если нажато, то п.2.
2 - Задержка 30-40 мс, по окончании задержки, если еще нажато, то п.3, если нет, то п. 1.
3 - Если флаг 0, то включаем генератор и флаг =1, если флаг=1, то выключаем генератор и флаг=0. Генератор-таймер в режиме ШИМ.
4 - Ждем отжатия кнопки.
Если не отжато, то п. 4.
Если отжато, то задержка 30-40 мс, по окончании задержки, если еще не отжато, то п. 4, если отжато, то п. 1.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Открыл глаза
Сообщения: 53
Зарегистрирован: Пн ноя 09, 2009 20:14:52

Сообщение SatinS »

Не нашёл, где задать свой вопрос, потому спрошу здесь.
Объясните, пожалуйста как работает статусный регистр, пользоваться я им умею и назначение всех его битов мне понятно. Не могу понять как он "привязывается" к регистру, как МК понимает, что именно в этом регистре отрицательное число или вот в том регистре флаг заёма?
И попутно 2й вопрос, какие служебные регистры можно использовать для своих целей? Например, USIBR при неиспользуемом USI?
Спасибо.
Реклама
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

SatinS писал(а):Не нашёл, где задать свой вопрос, потому спрошу здесь.
Объясните, пожалуйста как работает статусный регистр, пользоваться я им умею и назначение всех его битов мне понятно. Не могу понять как он "привязывается" к регистру, как МК понимает, что именно в этом регистре отрицательное число или вот в том регистре флаг заёма?
Спасибо.
После каждого выполнения каждой команды в регистре SREG в зависимости от команды устанавливаются или сбрасываются те или иные флаги. Есть команды, которые не влияют на регистр SREG.
Если выполняются операции на регистрах, то после выполнение команды те или иные флаги относятся к тому регистру, на котором совершаются операции.
Установка или сброс флагов происходят внутри АЛУ (арифметико-логическое устройство). Это уже относится к схемотехнике цифровых устройств.
Контактная информация:
Реклама
Открыл глаза
Сообщения: 53
Зарегистрирован: Пн ноя 09, 2009 20:14:52

Сообщение SatinS »

Demiurg писал(а):...
Вот мне и интересно - как происходит механизм запоминания, к какому именно регистру относится флаг, и сколько регистров с флагами можно обрабатывать, в даташите на авр я ничего об этом не нашёл.
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Прежде чем задавать "странные", мягко говоря, вопросы, изучите архитектуру МК. Книга Вольфганг Трамперт AVR-RISC микроконтроллеры фирмы ATMEL. Во-первых сами разберетесь, и не будете доставать на форумах людей своими глупыми вопросами. Повторяю еще раз. Флаги SREG выставляются после каждой команды-операции над регистрами.

subi r16, 15 // В SREG будет результат операции над регистром r16. Что здесь непонятного?!

А как эти флаги выставляются аппаратно, нужно изучать схемотехнику цифровых устройств. Гуглите АЛУ. Там будут схемы и вы примерно будете представлять, как выставляются флаги SREG.

Все, отстаньте с глупыми вопросами, пока не прочитаете книгу, которую я вам назвал.
Контактная информация:
Открыл глаза
Сообщения: 53
Зарегистрирован: Пн ноя 09, 2009 20:14:52

Сообщение SatinS »

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

Сообщение Kavka »

SatinS писал(а):как происходит механизм запоминания, к какому именно регистру относится флаг, и сколько регистров с флагами можно обрабатывать
Статусный регистр один. Механизма "привязки" в АЛУ никакого нет .

Флаги в статусном регистре относятся к последней выполненной команде, которая их (флаги) меняла. Всё.

Дальше можно логически получать разные следствия из предыдущего утверждения. Например, что флаги относятся к тем регистрам общего назначения, над которыми выполнялась та последняя команда, которая меняла соответствующие флаги.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32

Сообщение alex38779 »

Есть вот команды sbrc и cbrc которые проверяют n бит байта, sbrc r16, n. То есть работают с константой, а как мне сделать чтобы n задавать в программе, допустим инкрементировать ее ? Например я хочу проверить каждый бит байта.
Контактная информация:
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

alex38779 писал(а):Есть вот команды sbrc и cbrc
1 - sbrc sbrs.
2 - Варианты.

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

//==================
.nolist
.include	"m8535def.inc"
.list
//==================

rjmp Reset

Reset:
ldi r16, HIGH (RAMEND)
out SPH, r16
ldi r16, LOW (RAMEND)
out SPL, r16

Main:
wdr

//------------------------------------------------------------------------
Method_1:
ldi r16, 5 // Нужно проверить 5 бит.
ldi r17, 1<<5 // Устанавливаем 5 бит.

Method_1_Cycle:
tst r16
breq Method_1_Equal
lsr r17
dec r16
rjmp Method_1_Cycle

Method_1_Equal:
sbrs r17, 0
rjmp Method_1_Zero
rjmp Method_1_One

Method_1_Zero:
rjmp PC+1

Method_1_One:
rjmp PC+1
//------------------------------------------------------------------------
Method_2:
ldi r16, 5 // Нужно проверить 5 бит.
ldi r17, 1<<5 // Устанавливаем 5 бит.
ldi r18, 1

Method_2_Cycle:
tst r16
breq Method_2_Equal
lsl r18
dec r16
rjmp Method_2_Cycle

Method_2_Equal:
and r17, r18
breq Method_2_Zero
brne Method_2_One

Method_2_Zero:
rjmp PC+1

Method_2_One:
rjmp PC+1
//------------------------------------------------------------------------
Method_3:
ldi r16, 5 // Нужно проверить 5 бит.
ldi r17, 1<<5 // Устанавливаем 5 бит.

clr ZH
mov ZL, r16
subi ZL, LOW (-(Table_Bits*2))
sbci ZH, HIGH (-(Table_Bits*2))
lpm

and r17, r0

breq Zero
brne One

Zero:
rjmp PC+1

One:
rjmp PC+1

rjmp  Main

;-------------------------------------------------------------------------
Table_Bits:
.db		0b00000001, 0b00000010
.db		0b00000100, 0b00001000
.db		0b00010000, 0b00100000
.db		0b01000000, 0b10000000
;-------------------------------------------------------------------------
Учтите, вы должны проверять значение номера бита на выход за предел 7 (0-7 биты). И учитывайте, что машинный счет начинается с нуля. То есть, декрементируйте номер бита. То есть, если нам нужно проверить 1 бит, то индекс должен быть 0.
Последний раз редактировалось Demiurg Вс апр 24, 2016 10:07:02, всего редактировалось 2 раза.
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32

Сообщение alex38779 »

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

Сообщение Kavka »

alex38779 писал(а):Например я хочу проверить каждый бит байта.
Какой контроллер? Не важно.
Табличный метод хорош. Стабилен по времени выполнения и компактен.
Можно маску получать с помощью цикла со сдвигом. Может быть будет чуть меньше занимать в памяти, но время выполнения будет разное для разных битов.
Последний раз редактировалось Kavka Вс апр 24, 2016 06:20:28, всего редактировалось 1 раз.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

alex38779 писал(а):... а как мне сделать чтобы n задавать в программе...
Иногда в подобных случаях помогает вспомогательная маска "бегущий нуль(единица)", смещаемая при каждом контрольном цикле программы.
8)
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

alex38779 писал(а):Например я хочу проверить каждый бит байта

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

   ldi R16,0x55 //тестируемый регистр
	ldi R17,8 //количество циклов

	push r16 //сохранить значение регистра (если надо)

povtor:
	lsl R16 //сдвиг влево регистра, старший бит во флаг С
	brcs Propusk //пропустить сколкьо надо команд если установлен флаг С

	nop    //что то когда флаг С сброшен
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop

Propusk:
dec R17			//уменьшаем счечтик циклов и если не ноль то повторяем
brne  povtor

  pop r16		//восстановить R16
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Z_h_e писал(а):...
Ну тады как-то так: тут.
Контактная информация:
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

alex38779 писал(а):Есть вот команды sbrc и cbrc которые проверяют n бит байта, sbrc r16, n. То есть работают с константой...
Замечу. Команды SBRS и SBRC работают с 1 битом!
SBRC This instruction tests a single bit in a register and skips the next instruction if the bit is cleared.
SBRS This instruction tests a single bit in a register and skips the next instruction if the bit is set.
Для проверки n-бит есть прекрасная команда
CPSE This instruction performs a compare between two registers Rd and Rr, and skips the next instruction if Rd = Rr.
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

akl писал(а):
alex38779 писал(а):Есть вот команды sbrc и cbrc которые проверяют n бит байта, sbrc r16, n. То есть работают с константой...
SBRS и SBRC работают с 1 битом!
Об этом все знают. Перечитайте еще раз цитату, которую сами привели: ТС сетует, что эти команды работают с константой, и ему хочется проверять произвольный бит, который задан в переменной.
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32

Сообщение alex38779 »

Почему команда ret кидает в самое начало программы -
.ORG $00? Ни как не могу понять..
Спойлер

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

 .def temp2    = r18 
 .def numDigit = r19
 .def temp     = r20
 .def temp1    = r21
 .def tempL    = r23
 .def tempH    = r24
 .def tempX    = r25

 .equ DS = PB3
 .equ ST_CP = PB4
 .equ SH_CP = PB2 

 ;================
 .DSEG
	number: .byte 1
	digit:  .byte 1
	n1:		.byte 1 ;1000
	n2:		.byte 1 ;100
	n3:		.byte 1 ;10
	n4:		.byte 1 ;1
 ;================
 .CSEG

 .ORG $00
	rjmp reset    ; Reset
 .ORG $03
	rjmp OVF0 ; Timer/Counter0 Overflow
 
 OVF0: 	
	;rjmp send595			
	reti

 reset: 	 
	;stek
	ldi r16, RAMEND 
	out SPL, r16
	cli
	;595
	in temp, DDRB
	ori temp, 1<<DS | 1<<ST_CP | 1<<SH_CP
	out DDRB, temp
	in temp, PORTB
	andi temp, ~(1<<DS | 1<<ST_CP | 1<<SH_CP)
	out PORTB, temp
	;timer
	in r16, TCCR0B
	ori r16, 1<<CS01
	out TCCR0B, r16
	ldi r16, $00
	out TCNT0, r16
	;прерывания
	in r16, TIMSK0
	ori r16, 1<<TOIE0
	out TIMSK0, r16
	sei
	ldi numDigit, 0b11110000;0b76543210	
 main:
	rjmp staskSave
	;число в оперативку
	ldi YL, low(1234)
	ldi YH, high(1234)	
	ld r16, Y+
	ld r17, Y+
	ldi XL, byte1(596)
	ldi XH, byte2(596)
	st Y+, XH
	st Y+, XL
	;разложение на разряды
	;rjmp todigit	
	rjmp staskLoad
	rjmp main
 
 staskSave:
	push r16
	push r17
	push r18
	push r19
	push r20
	push r21
	push r22
	push r23
	push r24
	push r25
	push r26
	push r27
	push r28
	push r29
	push r30
	push r31
	ret

 staskLoad:
	pop r31
	pop r30
	pop r29
	pop r28
	pop r27
	pop r26
	pop r25
	pop r24
	pop r23
	pop r22
	pop r21
	pop r20
	pop r19
	pop r18
	pop r17
	pop r17


	ret

даже когда вызываю через rcall, все ровно кидает в начало.
Последний раз редактировалось alex38779 Вс апр 24, 2016 21:25:08, всего редактировалось 1 раз.
Контактная информация:
Ответить

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