Уважаемый Паша, привет!
Да, точно такая же самая задача... Правда скорость чуть больше... ;-)))
И еще я не знал что это зовется "квадратурным энкодером" - ну, умнее стал...
Конкретные данные:
- время между фронтами по линиям A и B одного датчика до 1мкС - т.е. в идеале прерывание должно за это время отрабатываться;
- а датчиков-то два. бу-га-га надо мною ;-)))
Обработчик втиснул в 20 тактов, хотя надо еще учитывать что прерывание вызывается, как я понял, примерно через 5-10 тактов после наступления события, его спровоцировавшего.
План такой:
- поскольку это лабораторная поделка, поставлю кварц 20 МГц или даже 24МГц и посмотрю, будет ли работать - сейчас работает от внутреннего 8МГц генератора;
- ждем массового наступления XMega с частотой 32 (а спасет ли?);
- можно бы сэкономить такты зарезервировав скажем r16 или r23 чтоб не сохранять его на стеке, но не знаю, что мне на это компилятор скажет, пока зарезервировал r2,r3 для младших байтов счетчиков, r4 для sreg, r5 в качестве вспомогательного;
- еще можно экономить байтики поставив двухвходовой и-не на один из входов, чтобы преобразовать обычную последовательность 00, 01, 11, 10, 00... в 00, 01, 10, 11, 00...
Сейчас текст такой (поиграем в Hugi Compo ;-) - что еще улучшить в голову не приходит (впрочем, радикально тут ничего не изменится):
CODE
volatile short coordA1,coordB1;
volatile register byte coordA0 asm("r2");
volatile register byte coordB0 asm("r3");
volatile register byte sregSave asm("r4");
volatile register byte temp2 asm("r5");
//по замыслу coordA=(coordA1<<8)|(coordA0^0x80)
//т.е. седьмой бит младшего (нулевого) байта инвертирован
//а первый и второй байты живут отдельно в SRAM
ISR(INT0_vect,ISR_NAKED){
//ветка для прямого направления движения
asm volatile(
"cli \n\t"
"in r4,0x3F \n\t push r16 \n\t"
"in r16,0x10 \n\t mov r5,r16 \n\t lsl r5 \n\t"
"eor r16,r5 \n\t andi r16,0x08 \n\t breq int0neg \n\t"
"inc r2 \n\t brvs int0ovr \n\t"
"pop r16 \n\t out 0x3F,r4 \n\t"
"sei \n\t reti \n\t"
);//asm
//ветка для overflow младшего байта (в прямом направлении)
asm volatile(
"int0ovr: \n\t"
"lds r16,coordA1 \n\t inc r16 \n\t sts coordA1,r16 \n\t"
"brne int0sk1 \n\t"
"lds r16,coordA1+1 \n\t inc r16 \n\t sts coordA1+1,r16 \n\t"
"int0sk1: \n\t"
"pop r16 \n\t out 0x3F,r4 \n\t"
"sei \n\t reti \n\t"
);//asm
//ветка для обратного направления
asm volatile(
"int0neg: \n\t"
"dec r2 \n\t brvs int0und \n\t"
"pop r16 \n\t out 0x3F,r4 \n\t"
"sei \n\t reti \n\t"
);//asm
//ветка для underflow младшего байта (в обратном направлении)
asm volatile(
"int0und: \n\t"
"lds r16,coordA1 \n\t subi r16,1 \n\t sts coordA1,r16 \n\t"
"brcs int0sk2 \n\t"
"lds r16,coordA1+1 \n\t dec r16 \n\t sts coordA1+1,r16 \n\t"
"int0sk2: \n\t"
"pop r16 \n\t out 0x3F,r4 \n\t"
"sei \n\t reti \n\t"
);//asm
}//ISR(INT0_vect)
ну и так далее... для INT1, INT2 и еще аналоговый компаратор задействовал в качестве INT3 несуществующего...
Сообщение отредактировал rezident - Apr 13 2009, 16:50
Причина редактирования: Оформление цитаты исходника.