Alexeyslav писал(а):А зачем их занимать? Есть PUSH/POP и не бойся что изменения регистра выйдут за рамки данного алгоритма. Защита забирает по 4 такта на регистр...
Все дело в том, что это продолжение эпопеи про совмещение Си и Асма в одном проекте...
viewtopic.php?f=20&t=37190&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Гц.
Вот в принципе и вся задачка...