Страница 190 из 399
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Пт май 17, 2013 13:19:21
Engineer_Keen
Gudd-Head писал(а):Т.к. адресуются слова, то 2^23-1 = 8М слов, т.е. 16Мбайт.
Адресуются слова, так что 2^22=4Мслов (почему ^23?), а то что это 8Мбайт, не важно, у нас же PC в словах считает

Хорошо еще что речь не о MCS51, а то там есть AJMP, SJMP, LJMP и хитрый JMP с использованием аккумулятора и указателя, но зато путаницы со словами/байтами нет
Мikа писал(а):Пытаюсь вникнуть в написанное вами

Давайте давайте, вникайте скорее, вас еще IJMP\ICALL ждут

Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Пн май 20, 2013 14:28:10
shads
Подскажите, какой самый эффектный способ декремента 16-ти разрядного счетчика (2 регистра в нижней половине) и при достижении 0xffff загрузки в него нового значение....
Сначала думал что есть команда перехода при переполнении, т.е. при переходе 0 -> 255, но наверное она работает только при переполнении в сторону 255 -> 0... т.к. у меня не получилось это с декрементом....
На данный момент лучше ничего не придумал чем это, но думаю можно эффективнее.....
Код: Выделить всё
ldi temp,0xff
dec DivL
cp DivL,temp
brne exit
dec DivH
cp DivH,temp
brne exit
ldi temp,lo8(DIV_CONST)
mov DivL,temp
ldi temp,hi8(DIV_CONST)
mov DivH,temp
exit:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Пн май 20, 2013 15:13:39
ibiza11
ну как минимум можно убрать загрузку в temp числа 0хFF, используя вместо
cp команду
cpi
Добавлено: Вот как вариант
Код: Выделить всё
ldi temp,$1
sub DivL,temp
brcc exit ;Branch if Carry is Cleared
sub DivH,temp
brcc exit
ldi temp,low(DIV_CONST)
mov DivL,temp
ldi temp,high(DIV_CONST)
mov DivH,temp
exit:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Пн май 20, 2013 15:43:22
akl
Может как-то так
Код: Выделить всё
.def DivH =R25
.def DivL =R24
RESET:
SBIW DivL,1
BRCS T1
RJMP RESET
T1:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Пн май 20, 2013 17:19:03
shads
ibiza11 писал(а):ну как минимум можно убрать загрузку в temp числа 0хFF, используя вместо
cp команду
cpi 
Немогу, т.к. регистры в нижней половине.... они же не переваривают
cpi.....
ibiza11 писал(а):Вот как вариант
Код: Выделить всё
ldi temp,$1
sub DivL,temp
brcc exit ;Branch if Carry is Cleared
sub DivH,temp
brcc exit
ldi temp,low(DIV_CONST)
mov DivL,temp
ldi temp,high(DIV_CONST)
mov DivH,temp
exit:
Во..... это уже пинок в нужном направлении.....
а я то думаю почему компилятор
всегда иногда заменяет декремент на вычитание.....
akl писал(а):Может как-то так
Код: Выделить всё
.def DivH =R25
.def DivL =R24
RESET:
SBIW DivL,1
BRCS T1
RJMP RESET
T1:
Не могу занимать старшие регистры... нужно морочится с младшими.....
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Пн май 20, 2013 21:02:18
Alexeyslav
А зачем их занимать? Есть PUSH/POP и не бойся что изменения регистра выйдут за рамки данного алгоритма. Защита забирает по 4 такта на регистр...
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Пн май 20, 2013 22:22:00
shads
Alexeyslav писал(а):А зачем их занимать? Есть PUSH/POP и не бойся что изменения регистра выйдут за рамки данного алгоритма. Защита забирает по 4 такта на регистр...
Все дело в том, что это продолжение эпопеи про совмещение Си и Асма в одном проекте...
http://radiokot.ru/forum/viewtopic.php? ... start=3020
У меня вся прога на Си.... а на асме только маленький кусочек - скоростное прерывание с частотой вызова 250 000 Гц.
У меня на отработку прерывания дано только 38 тактов. Ито это чтобы успеть выйти до начала следующего прерывания. А еще надо чтобы осталось время и на фоновую работу.....
Несколько нижних регистров у меня определены как переменные и в Си и в асме, только с ними я и работаю в прерывании.
Я даже отказался от того чтобы пуш\попить временный регистр и SREG, сохраняю их все в тех же нижних регистрах, так в 2 раза быстрее получается чем пуш\поп. Так что пуш\попить верхние регистры и потом еще перегружать туда\оттуда нижние регистры - несбыточная мечта.....
Вот весь кусок на асме. (кстати я кажется придумал самый короткий способ инкремента и инициализации 16-ти битного счетчика - см. DivL, DivH.)
Спойлер
Код: Выделить всё
//--------------------------------------------------------------------------------------------------------------------------
#include <avr/io.h>
#define T_SLOT 32 /*количество тиков 16 разрядного таймера на один слот RFID сигнала*/
#define DIV_CONST 1250 /*константа для инициализации счетчика деления с 125000Гц до 100 Гц*/
#define DivL r2 /*счетчик делителя частоты с 125000Гц до 100Гц - младший байт*/
#define DivH r3 /*счетчик делителя частоты с 125000Гц до 100Гц - старший байт*/
#define Timer r4 /*программный таймер\счетчик*/
#define Flags r5 /*байт флагов*/
#define INT_100 (1<<0) /*флаг прерывания частоты 100Гц*/
#define Div2 (1<<1) /*флаг деления частоты прерывания с 250000Гц до 125000Гц*/
#define PushSreg r6 /*регистр хранения регистра SREG*/
#define PushTemp r7 /*регистр хранения регистра TEMP*/
#define temp r16 /*временный регистр*/
//--------------------------------------------------------------------------------------------------------------------------
.global TIM0_COMPA_vect
TIM0_COMPA_vect:
//тут частота прохода 250 000 Гц
mov PushTemp,temp //сохраняем регистры
in PushSreg,_SFR_IO_ADDR (SREG)
ldi temp,Div2 //делим частоту прохода с 250000Гц до 125000Гц
eor Flags,temp
and temp,Flags
breq exit
//тут частота прохода 125 000 Гц
inc Timer //обработка счета программного таймера/счетчика (останавливается на 0xff)
brne TmrEnd
dec Timer
TmrEnd:
ldi temp,T_SLOT+(T_SLOT/2) //проверка, необходимо ли включить внешнее прерывание
cp Timer,temp
brne NoEqual
ldi temp,1<<_SFR_IO_ADDR (INT0) //включаем внешнее прерывание
out _SFR_IO_ADDR (GIMSK),temp
NoEqual:
inc DivL //обработка счетчика делителя частоты cо 125000Гц до 100Гц
brne exit
inc DivH
brne exit
//тут частота прохода 100 Гц
ldi temp,lo8(0-DIV_CONST)
mov DivL,temp
ldi temp,hi8(0-DIV_CONST)
mov DivH,temp
ldi temp,INT_100
or Flags,temp //с частотой 100Гц устанавливать флаг медленного прерывания
exit:
//выход из прерывания
out _SFR_IO_ADDR (SREG),PushSreg
mov temp,PushTemp
reti
.end
//--------------------------------------------------------------------------------------------------------------------------
В обчем поясню суть происходящего, ато выглядит как конвульсии сумасшедшего.....
Хочу tiny13 уговорить работать как декодер карт RFID. В схеме должен быть генератор 125 000 Гц для питания катушки связи. Так вот меня заклинило на том, чтобы эту частоту выдавала тинька. А проблема в том, что у тиньки только один железный таймер. Т.е. если им генерить частоту 125 000 Гц, то соответственно остальные прерывания будут плясать от этой частоты.
Т.е. у нас есть частота контроллера 9600000Гц, настраиваем изменение вывода по совпадению. Чтобы получить частоту 125000Гц, надо 9600000 / 125000, получается 76. Но это будет длина периода. Чтобы получить промежуток в полупериод, надо гонять таймер не до 76 а до 38.....
При этом прерывания которые мы можем получить от этого таймера будут с частотой 9600000 / 38 = 250000 (примерно).
Вот вам и циферка.... от которой пляшем.....
В этом сумасшедшем прерывании обрабатываем таймер программный, для измерений сигнала RFID, и генерим флаг для низкоскоростного прерывания 100Гц.
Вот в принципе и вся задачка...
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Пн май 20, 2013 22:42:53
Alexeyslav
Контроллер уже на максимальной частоте в 20Мгц работает? 38 тактов, это с учетом времени на вход в прерывание, выход и +1 такт на очередную инструкцию? На самом деле у тебя времени завались - каждое второе прерывание отрабатывает лишь 10 тактов, у него можно "украсть" еще десяток отложив его обработку, если не уложишься в первом. И еще возникает вопрос, а столь необходимо работать с такой частотой если тебе нужно только каждое второе прерывание? Почему бы не настроить таймер на 125Кгц изначально?
Отсев каждого второго можно сократить если инвертировать бит в глобальном регистре и переходить на выход в зависимости от этого бита, в качестве инверсии взять простой инкремент и проверять 0-й бит SBIC/SBIS. Если уж пляска пошла на такты в прерывании, выделение отдельного регистра под ускорение может быть оправданным.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Пн май 20, 2013 22:59:32
shads
Alexeyslav писал(а):Контроллер уже на максимальной частоте в 20Мгц работает?
Не, на 9600000. Если бы на 20000000 то было бы легче, но неохота пихать кварц.....
Alexeyslav писал(а):38 тактов, это с учетом времени на вход в прерывание, выход и +1 такт на очередную инструкцию? На самом деле у тебя времени завались - каждое второе прерывание отрабатывает лишь 10 тактов, у него можно "украсть" еще десяток отложив его обработку, если не уложишься в первом.
Да, каждое второе прерывание, получается совсем короткое, но это хорошо, т.к. фоновая задача тоже не должна тормозить... пусть для фона резерв будет.
И кстати я тоже думал, что отложенное прерывание должно сработать, если первое не успело закончится к началу второго, ан нет.... если первое не успело до возникновения второго, то почему то оно не срабатывает по окончании первого..... и один такт прерывания пропускается.....
С чем интересно это может быть связано?
Alexeyslav писал(а):И еще возникает вопрос, а столь необходимо работать с такой частотой если тебе нужно только каждое второе прерывание? Почему бы не настроить таймер на 125Кгц изначально?
Мне изначально нужна частота на ножке 125000Гц, а уж потом из того что имеем, получаю остальное, а при генерации такой частоты, у меня получается прерывание 250000Гц..... по другому я чет не дотукал пока, вроде и так и сяк рылся, вроде только так.....
Alexeyslav писал(а):Отсев каждого второго можно сократить если инвертировать бит в глобальном регистре и переходить на выход в зависимости от этого бита, в качестве инверсии взять простой инкремент и проверять 0-й бит SBIC/SBIS. Если уж пляска пошла на такты в прерывании, выделение отдельного регистра под ускорение может быть оправданным.
Я в принципе так и делаю, флаг Div2. Или ты чтото другое имееш ввиду?
А нет уже места где резервировать доп регистр, все уже исчерпал, Си позволяет резервировать вроде только r2-r7. Они как раз уже забиты.....
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт май 21, 2013 08:24:54
ibiza11
можно уменьшить частоту прерываний в 2 раза, если использовать для генерации частоты 125кГц один из аппаратных режимов таймера типа Clear On Compare или PWM. Для этого есть две ноги у контроллера (OC0A и OC0B).
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт май 21, 2013 08:58:28
shads
ibiza11 писал(а):можно уменьшить частоту прерываний в 2 раза, если использовать для генерации частоты 125кГц один из аппаратных режимов таймера типа Clear On Compare или PWM. Для этого есть две ноги у контроллера (OC0A и OC0B).
Ага, я именно аппаратную реализацию и использую, но у меня по другому не получается, частота на OC0A равна 125кГц, но при этом прерывания происходят с частотой 250кГц.....
Вот как у меня настроен таймер:
Код: Выделить всё
//генерация частоты 125000 Hz на выводе OC0A с помощью таймера Т0 (tiny13)
TIMSK0 = (1<<OCIE0A)|(0<<OCIE0B)|(0<<TOIE0); //разрешить соответствующие прерывания
TCNT0 = 0; //СЧЕТНЫЙ РЕГИСТР
OCR0A = 38; //РЕГИСТР СРАВНЕНИЯ
OCR0B = 0; //РЕГИСТР СРАВНЕНИЯ
TCCR0A = //РЕГИСТР УПРАВЛЕНИЯ
(0<<COM0A1)|(1<<COM0A0)| //состояние выводов OC0A при совпадении
(0<<COM0B1)|(0<<COM0B0)| //состояние выводов OC0B при совпадении
(1<<WGM01)|(0<<WGM00); //режим CTC - сброс при совпадении
TCCR0B = //РЕГИСТР УПРАВЛЕНИЯ
(0<<WGM02)|
(0<<FOC0A)|(0<<FOC0B)| //разрешить принудит изменение состоян выв OC0A и OC0B
(0<<CS02)|(0<<CS01)|(1<<CS00); //источник тактового сигнала (0001 - прямое тактирование)
Мож подскажите, как при такой частоте на ножке, уменьшить частоту прерываний.....
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт май 21, 2013 09:03:03
ibiza11
Щас подскажу. Даташит почитаю... если никто не напишет, дополню сообщение.
Добавлено: Вот код инициализации таймера на работу в режиме Fast PWM, таймер считает от 0 до значения TOP. В этом режиме TOP задается регистром OCR0A, а регистром OCR0B задается точка сравнения. Таким образом сигнал 125кГц будет присутствовать на
выводе OC0B. (по-другому здесь нельзя). Прерывание переполнения будет вызываться каждые 76 тактов при достижении счетчиком значения TOP.
Код: Выделить всё
#define F_CPU (9600000UL)
#define f_RFID (125000UL)
#define T0_PWM_TOP (F_CPU/f_RFID)
TCCR0A = 0;
TCCR0A |= (1<<COM0B1)|(1<<COM0B0) /* Set OC0B on Compare Match, clear OC0B at TOP */
|(1<<WGM01)|(1<<WGM00); /* Set Fast PWM mode */
TCCR0B = 0;
TCCR0B |= (1<<WGM02); /* Set TOP = OCR0A */
OCR0A = T0_PWM_TOP; /* Set TOP value */
OCR0B = T0_PWM_TOP/2; /* Set compare value */
TIMSK0 = 0;
TIMSK0 |= (1<<TOIE0); /* overflow interrupt enable (generates on TOP) */
TCCR0B |= (1<<CS00); /* start the timer */
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт май 21, 2013 15:28:29
shads
Ай пасип те мил человек!!!!!
Я когда увидел результат, аж запрыгал как маленький....
Поставлю тебе плюсы везде где только можно
Я прям, ваще слов нет... код в прерывании короче стал (убрал делитель на 2), освободилось 2 нижних регистра (вернулся к стандартным пуш\попам), теперь все спокойно в развалочку помещается, красота.....
А я кстати думал что прерывание на TIM0_OVF_vect возможно только при переходе ч-з 255 на 0..... а оказывается и не только ч-з 255..... наверное поэтому я не нашел решения, потому что крутился тлько вокруг TIM0_COMPA и TIM0_COMPB.....
Вот что теперь имеем:
Желтый - сигнал 125КГц
Голубой - маркер времени выполнения прерывания
Красный - метка прохождения самого длинного пути прерывания
Основное прерывание занимает менее 30% от ширины прерывания,
а самый длинный путь - менее 50% (установка флага медленных прерываний, с частотой 100Гц)

Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт май 21, 2013 15:41:27
ibiza11
"Подумаешь..я еще и вышивать могу.. и на машинке тоже." (c)

Рад, что помог!)))
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт май 21, 2013 19:29:10
Alexeyslav
Ну вот, уже все ответили. Как и предполагал...
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт май 21, 2013 19:39:58
shads
Да.... с таймерами мне еще надо подтянутся.....
Я смотрю там куча всяких режимов, так что с ходу голыми руками не взять...
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Пн май 27, 2013 23:25:33
Kavka
Если есть желающие размять мозги, то вот задачка.
Дано:
МК ATtiny13.
Регистры var1 и var2 (любые).
Начальные значения var1=0, var2=0x80
Можно использовать дополнительные регистры и ОЗУ. В том числе заранее инициализированные.
Задача: минимизировать время выполнения следующих действий.
сдвинуть вправо var2
если var2 == 0 то {
var1 = var1 + 1
если var1 > 3 то var1 = 0
var2 = 0x80
}
Попытка на ночь глядя чего-то придумать дала 5 тактов (5 команд).
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт май 28, 2013 10:58:08
Engineer_Keen
По-моему меньше 5 команд не получится, хотя вариантов несколько, самый логичный естественно:
Код: Выделить всё
LSR VAR2
BRCC END
INC VAR1
ANDI VAR1,0x03
LDI VAR2,0x80
END:
3 цикла при VAR2<>0 и 5 при VAR2=0
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт май 28, 2013 14:11:16
Kavka
Есть такой вариант.
У меня ещё вот такое получилось.
Код: Выделить всё
; zero - регистр с нулевым значением
bst var2, 0
lsr var2
bld var2, 7
adc var1, zero
andi var1, 0x03
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт май 28, 2013 14:24:55
Engineer_Keen
Такой вариант тоже думал, но задача была минимизировать время, а этот вариант всегда выполняется по максимуму - 5 тактов. Или важна как раз стабильность по времени?