Страница 51 из 400

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

Добавлено: Вс ноя 07, 2010 06:10:36
akl
mig-11101 писал(а):...
ATtiny13_power_doun.GIF
Из этого замечания на 30 стр. DS, следует, что выход из POWER-DOWN будет только при низком уровне на INT0.
Попробуйте так
POWER_DOWN.TXT

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

Добавлено: Вс ноя 07, 2010 10:12:44
mig-11101
akl

Спасибо, дейсвтвительно срабатывает, если установить прерывание на низкий уровень.

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

Добавлено: Вс ноя 07, 2010 12:47:44
ZERO..
akl писал(а):
mig-11101 писал(а):...
ATtiny13_power_doun.GIF
Из этого замечания на 30 стр. DS, следует, что выход из POWER-DOWN будет только при низком уровне на INT0.
Попробуйте так
POWER_DOWN.TXT

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

Добавлено: Вс ноя 07, 2010 19:08:11
desolator

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

		.DSEG
Variables:	.byte	3
Variavles2:	.byte	1
 
		.CSEG
 
; Переменная лежит в памяти, сначала надо ее достать.
	LDS	R16, Variables		; Считать первый байт Variables  в R16
	LDS 	R17, Variables+1 	; Считать второй байт Variables  в R17
	LDS	R18, Variables+2	; Ну и третий байт в R18
 
; Теперь прибавим к ней 1, т.к. AVR не умеет складывать с константой, только 
; вычитать, приходиться извращаться. Впрочем, особых проблем не доставляет. 
 
	SUBI	R16,(-1)	; вообще то SUBI это вычитание, но -(- дает +
	SBCI	R17,(-1)	; А тут перенос учитывается. Но об этом потом.
	SBCI	R18,(-1)	; Математика в ассемблере это отдельная история
 
	STS 	Variables,R16		; Сохраняем все как было. 
	STS 	Variables+1,R17
	STS	Variables+2,R18
Вот такой пример. Обьясните, пожалуйста, почему

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

SUBI	R16,(-1)	; вообще то SUBI это вычитание, но -(- дает +
	SBCI	R17,(-1)	; А тут перенос учитывается. Но об этом потом.
	SBCI	R18,(-1)	; Математика в ассемблере это отдельная история
в первой строке используем SUBI, какая разница в вычитании с переносом и в вычитании без переноса?
Спасибо заранее.

У меня в мануале написано:

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

SUBI     (Rd,K8)    вычитание константы Rd=Rd-K8
SBCI     (Rd,K8)    вычитание константы с переносом Rd=Rd-K8-C 
Что такое "С" выше, и откуда берется? как взаимодействует с выражением ?

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

Добавлено: Вс ноя 07, 2010 19:31:43
SII
C -- флаг переноса/заёма. Устанавливается в операциях сложения, вычитания, сравнения и сдвигов. С его помощью осуществляется, например, сложение или вычитание многобайтовых величин (собственно, тут пример именно такой).

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

Добавлено: Вс ноя 07, 2010 19:39:10
Doniak
DX168B писал(а):Видать отправляешь в этот порт целый байт.
Отправив целый байт целиком в порт, ты влияешь на все выводы этого порта.
Если одна часть выводов, например порта D, настроена на выход, а другая на вход, то
лучше управлять выходами порта по отдельности и отслеживать
входы тоже по отдельности(как я писАл выше).
Ещё 2 полезные команды:
sbi - подать на отдельную ногу лог. 1 (подать ток)
cbi - подать на отдельную ногу лог. 0 (убрать ток)
А вот синтаксис:

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

sbi  PortD,  0 ;Запустить ногу PD0
cbi  PortD,  0 ;Отрубить ногу PD0

sbi  PortD,  1 ;Запустить ногу PD1
cbi  PortD,  1 ;Отрубить ногу PD1

sbi  PortD,  2 ;Запустить ногу PD2
cbi  PortD,  2 ;Отрубить ногу PD2

sbi  PortD,  3 ;Запустить ногу PD3
cbi  PortD,  3 ;Отрубить ногу PD3
; И т.д.
Спасибо за помощь. Все заработало как надо буду доделывать прогу. :)

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

Добавлено: Вс ноя 07, 2010 21:25:14
DX168B
Удачи в начинаниях. :) :beer:

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

Добавлено: Пн ноя 08, 2010 13:16:19
desolator
SII писал(а):C -- флаг переноса/заёма. Устанавливается в операциях сложения, вычитания, сравнения и сдвигов. С его помощью осуществляется, например, сложение или вычитание многобайтовых величин (собственно, тут пример именно такой).
Где про этот флаг можно прочесть более подробно? Т.к. хочется понимать четко почему пишется код именно так, а не иначе.

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

Добавлено: Пн ноя 08, 2010 13:30:00
SII
Это Вам надо хорошо разобраться с двоичной арифметикой вообще -- как складываются и вычитаются двоичные числа "на бумаге" (тогда увидите, как возникают переносы и заёмы), а после этого -- как производится сложение-вычитание чисел, имеющих большую разрядность, чем используемый процессор (в Вашем случае процессор 8-разрядный, а числа -- 16-разрядные, но сама идея не зависит от конкретной разрядности). У всех компьютерных архитектур этот флаг присутствует, поэтому не играет роли, AVR это, PIC, IA-32... В общем, это основа основ :)

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

Добавлено: Пт ноя 12, 2010 02:50:11
desolator
Чтобы люди не бросали, надо просто пофиксить, я думаю админу не пофик, если найдутся жедающие - пофиксят, то админ прилепит.
Было б делом, если б были задачки по мере нарастания сложности.

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

Добавлено: Вс ноя 14, 2010 01:58:16
Roman Venom
у меня такой вопросик.
нужно организовать задержку с изменяемым(прерывание по переполнению таймера) интервалом 8-100мс. Всего 80 значений. В этом прерывании нажимается кнопочка и выставляются значения 0-8000 с шагом 100. Это цифры сразу отображаются на ЖКИ. Этот кусок проги написал.
Думал для управления задержкок сделать похожую конструкцию: табличка с 80-ю значениями. По инкременту они последовательно пишутся в регистр, формирующий задержку.

Хотел сначала сделать обычную консрукцию вроде такой:

ldi work,0
ldi work1,0
ldi work2,0
del3_0:
inc work
cpi work,30
brne del3_1
ret
del3_1:
inc work1
cpi work1,255
brne del3_1
jmp del3_2

del3_2:
inc work2
cpi work2,5
brne del3_2
jmp del3_0

Однако оказалось неудобным то, что приходится менять значения сразу в 2-х регистрах подпроги задержки для формирования точного интервала.
Вопрос как лучше это организовать. Задержку необходимо задавать и в прерывании по переполнению таймера(последовательно) и по прерыванию от юарта(естессно сразу значением).

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

Добавлено: Вт ноя 16, 2010 18:43:38
desolator
SII писал(а):Это Вам надо хорошо разобраться с двоичной арифметикой вообще -- как складываются и вычитаются двоичные числа "на бумаге" (тогда увидите, как возникают переносы и заёмы), а после этого -- как производится сложение-вычитание чисел, имеющих большую разрядность, чем используемый процессор (в Вашем случае процессор 8-разрядный, а числа -- 16-разрядные, но сама идея не зависит от конкретной разрядности). У всех компьютерных архитектур этот флаг присутствует, поэтому не играет роли, AVR это, PIC, IA-32... В общем, это основа основ :)
Да, действительно, я никогда не задумывался об этом. Всегда использовал языки высокого уровня - задал себе тип и имя переменной и делай что хочешь в пределах диапазона допустимых значений. В ассемблере-же всё изнутри :)
Т.е. если мне надо сложить ДВА 16-битных числа, например:

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

0001000110001100
и

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

0001001010001010
то, при сложении если 1 стоит напротив 1, устанавливаются флаги ZCNVHS? и единичка переносится влево, далее до старшего бита?

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

Добавлено: Вт ноя 16, 2010 18:53:55
SII
Они будут складываться побайтно -- сначала младшие байты, затем старшие.

Младшие байты: 10001100 + 10001010 дадут 000010110 и возникнет перенос за пределы разрядной сетки, из-за чего будет установлен C.

Старшие байты: 00010001 + 00010010 дадут 00100011, однако к ним будет добавлено значение флага C, а там у нас 1, и в результате будет получено 00100100. При этом C будет сброшен, поскольку переноса из старшего разряда в этом сложении уже не возникло.

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

Добавлено: Сб ноя 20, 2010 02:18:54
Roman Venom
появился один интересный прикол. в прерывании по переполнению 16-битного таймера вызывается 2 подпрограммы:
next_time_H:;
; *
ldi work,0x00; *
out TIMSK,work;запретить прерывания таймерoв
ldi ZH,High(speed_value_delays_H1*2); *
ldi ZL,Low(speed_value_delays_H1*2); *
; *
; *
;
; *
add ZL,BLDC_cnt;указать адрес ячейки таблицы
adc ZH,work
;*
lpm; извлечь из флеш-памяти *
mov t_count1_H,r0;вывести значение
; *
out TCNT1H,t_count1_H;отправить в таймер *
ldi work,0b00000100;разрешить прерывание по переполнению *
out TIMSK,work ; *


; *
ret ;*
;*************************************
и сразу за ней вызывается вторая(такая же. только она перемещает из другой таблички число в младший рег. 16-битного таймера)
next_time_L:;

; *
ldi work,0x00; *
out TIMSK,work;запретить прерывания таймерoв
ldi ZH,High(speed_value_delays_L*2); *
ldi ZL,Low(speed_value_delays_L*2); *
; *
; *
;
; *
add ZL,BLDC_cnt;
adc ZH,work
;
; *
lpm; *
mov t_count1_L,r0; *
out TCNT1L,t_count1_L; *
ldi work,0b00000100; *
out TIMSK,work ; *
; *
ret ;*
Таблички:
speed_value_delays_L:
.db 0b11111111, 0b00000100, 0b00000100, 0b11111100, 0b00000100, 0b10010010, 0b00000100, 0b11111010, 0b00000000, 0b01001000
.db 0b11111010, 0b01010010, 0b01000110, 0b11111110, 0b10000100, 0b11001110, 0b00000100, 0b00001000, 0b00000010, 0b11011110
.db 0b10100110, 0b01011010, 0b00000100, 0b10011010, 0b00100110, 0b10101000, 0b00100000, 0b10011000, 0b11111100, 0b01100000
.db 0b11000100, 0b00010100, 0b01100100, 0b10110100, 0b00000100, 0b01000000, 0b10000110, 0b11000010, 0b11111110, 0b00111010
.db 0b01101100, 0b10011110, 0b11010000, 0b00000010, 0b00101010, 0b01010010, 0b10000100, 0b10100010, 0b11001010, 0b11110010
.db 0b00010000, 0b00111000, 0b01010110, 0b01110100, 0b10010010, 0b10110000, 0b11001110, 0b11100010, 0b00000000, 0b00010100
.db 0b00110010, 0b01000110, 0b01100100, 0b01111000, 0b10001100, 0b10100000, 0b10110100, 0b11001000, 0b11011100, 0b11110000
.db 0b00000100, 0b00011000
И другая типа такой же.
Короче всё стандартно. НО. Первая подпрограмма извлекает число из таблички корректно, а другая извлекает непонятно какое число и непонятно откуда. Промаялся с этим 2 часа, потом переместил вторую табличку "повыше" в программу и всё заработало. Если скопировать эту табличку и поместить в конец проги то опять начинается такая хрень. МОжет, надо задавать адрес флеша, может из-за этого такие лаги? Подскажите плз, ибо планируются ещё таблицы и интересно почему так.

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

Добавлено: Сб ноя 20, 2010 08:37:12
akl
Здравствуйте. Не указан тип контроллера, но, судя по назначению бита разрешения прерывания переполнения Т1 это что-то типа mega8. Проверил в студии 3.21 для 90S8515; принудительно сделал различные таблицы, вроде никаких противовопоказаний нет.
За одним попробовал свое представление занесения значений из таблицы в формате старший-младший. Находится в закомментированном T1_OVER1.

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

Добавлено: Сб ноя 20, 2010 14:44:07
Roman Venom
akl
Благодарю. У меня атмега16 на 5В.
Возникло несколько вопросов по вашей программе.
T1_OVER1:
OUT TCCR1B,ZERO ;остановить таймер
OUT TCNT1H,ZERO
OUT TCNT1L,ZERO
RCALL NEXT
OUT TIFR,_FF ; сброс флагов Т1
OUT TCCR1B,A ; запусить таймер
Первые 3 бита регистра TCCR1B отвечают(по крайней мере в меге16) за предделитель тактовой частоты. Зачем его сбрасывать а потом устанавливать в прерывании, если можно запретить прерывание по переполнению(а по выходу из прерывания разрешить) и обнулить счётчики(собсно это у вас есть). Не подумайте, что придираюсь: просто интересно.

и ещё маленький вопросик
NEXT:
ldi ZH,High(T_speed1*2); *
ldi ZL,Low(T_speed1*2); *
add ZL,BLDC_cnt ;указать адрес ячейки таблицы
adc ZH,ZERO
LPM; извлечь из флеш-памяти *
OUT TCNT1H,R0;отправить в таймер *
ADIW ZL,1
LPM
OUT TCNT1L,R0;отправить в таймер *
INC BLDC_cnt ; только для теста!!!!!!!
INC BLDC_cnt ; только для теста!!!!!!!
ret ;*
Интересует зачем здесь применена строчка АDIW ZL,1.
В регистровую пару прибавляется по единице для извлечения из таблицы следующей по счёту ячейки и всё?
П.С. Ну и смещать таблички заданием адреса попробую. Может, в этом дело.

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

Добавлено: Сб ноя 20, 2010 15:21:17
Liv
Если это мега16, то проще использовать команду LPM Rxx,Z+

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

Добавлено: Сб ноя 20, 2010 16:07:18
Roman Venom
Liv
Если это мега16, то проще использовать команду LPM Rxx,Z+
Проще, если требуется последовательно извлекать из таблички. А если изменение счётчика должно происходить, допустим, по нажатию кнопки, то не очень.

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

Добавлено: Сб ноя 20, 2010 17:13:49
akl
Мне было лениво создавать проект в 4-й студии, поэтому использовал "классику", в которой нет еще таких продвинутых команд.
По поводу сброса-запуска таймера в прерывании
-запрет прерывания в самом прерывании нелогичен, т.к. I-флаг сбрасывается в прерывании аппаратно. Другое дело очищать флаги или исключать из таблиц состояния вызывающие такие требования (например первый элемент Вашей таблицы, в котором сразу в таймер загружается максимальное число, а таймер не остановлен. Т.е. следующее прерывание будет несанкционированным)
-манипуляции с предустановками в TCNT1 можут привести к появлению флага TOV1, да и другие флаги могут взвестись. Причем на аппаратном уровне. Я так привык делать
-остановил
-очистил, чтобы начинать с одной точки
-загрузил требуемое значение
-сбросил флаги
-запустил

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

Добавлено: Сб ноя 20, 2010 19:03:41
avreal
Roman Venom писал(а):Проще, если требуется последовательно извлекать из таблички. А если изменение счётчика должно происходить, допустим, по нажатию кнопки, то не очень.
Liv абсолютно прав и для данного случая, ведь из таблички извлекается больше одного байта. Если уж на асме писать, то зачем делать хуже, чем сделает С-компилятор?

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

...
	adc	ZH,ZERO
	LPM	R0, Z+
	OUT	TCNT1H,R0
	; и эта команда оказалась не нужна ;  ADIW	ZL,1
	LPM
	OUT	TCNT1L,R0
	...
Кстати, а почему в табличке константы хранятся старшим байтом по младшему адресу, неудобно же табличку задавать. Что двумя полутаблицами, что с переставленными байтами... Иногда есть за что побороться, но лучше хранить в естественном порядке. Тут, похоже, ZL/ZH уже не нужны после вычитывания из таблички, так что (чтобы лишний регистр не занимать)

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

...
	adc	ZH, ZERO
	LPM	R0, Z+ ; младший
	LPM	ZL, Z   ; старший
	OUT	TCNT1H, ZL ; старший
	OUT	TCNT1L, R0 ; младший
	...