Полная версия этой страницы:
Где с флагами косяк?
Ребята, где то накосячил с флагами. Подскажите кто знает? Программа простая, только выводами дёргать. В ИАРе 4,12 в симуляторе нормально работает, регистр Р-15 меняется на 0 и 1. Прерывание нормально идет, сначала одна половина, потом другая. В Протеусе не идёт и на железе не идёт, точнее идёт с одного вывода, а хотелось бы по-очереди.
Если просто под "переключатель" отдельно переменную выделить, то идёт. Но хотелось бы один бит пользовать для этой цели.
Код
#include<io2313.h>
#include<avr_macros.h>
#include<iomacro.h>
#include<intrinsics.h>
unsigned int pol;
unsigned char sampl, interval;
__regvar __no_init char flags @15;
#define set_polar flags|=(1<<0)
#define clr_polar flags&=~(1<<0)
void pausa (unsigned long int p)
{
while (p>0)
p--;
}
#pragma vector=TIMER1_COMP1_vect
__interrupt void MyInterrupt (void)
{
if(flags & (1 << 0))
{
PORTD_Bit2=0;
pausa(0x10);
PORTD_Bit0=0;pausa(pol);PORTD_Bit0=1;
pausa(0x15);
PORTD_Bit2;
pausa(interval);
PORTD_Bit3=0;pausa(sampl);PORTD_Bit3=1;
clr_polar;
}
else
{
PORTD_Bit2=0;pausa(0x10);
PORTD_Bit1=0;pausa(pol);PORTD_Bit1=1;
pausa(0x15);
PORTD_Bit2=1;
pausa(interval);
PORTD_Bit4=0;pausa(sampl);PORTD_Bit4=1;
set_polar;
}
return;
}
int main( void )
{
PORTD=0xFF;
DDRD=0xFF;
OCR1=0x6420;
TIMSK=0x40;
TCCR1B=0x09;
__enable_interrupt();
while(1)
{
}
}
а че эти переменные pol,sampl, interval; ничем не инициализируются?
Цитата(viael @ Nov 17 2006, 22:30)

а че эти переменные pol,sampl, interval; ничем не инициализируются?
Подбираются при настройке.
Stefan
Nov 18 2006, 07:26
Цитата(Коляй @ Nov 17 2006, 22:51)

Ребята, где то накосячил с флагами. Подскажите кто знает? Программа простая, только выводами дёргать. В ИАРе 4,12 в симуляторе нормально работает, регистр Р-15 меняется на 0 и 1. Прерывание нормально идет, сначала одна половина, потом другая. В Протеусе не идёт и на железе не идёт, точнее идёт с одного вывода, а хотелось бы по-очереди.
Если просто под "переключатель" отдельно переменную выделить, то идёт. Но хотелось бы один бит пользовать для этой цели.
Код
#include<io2313.h>
#include<avr_macros.h> //Зачем? Все равно в программе не используется
#include<iomacro.h>
#include<intrinsics.h>
unsigned int pol; //Почему бы хоть здесь не инициализировать?
unsigned char sampl, interval;
__regvar __no_init char flags @15;
#define set_polar flags|=(1<<0)
#define clr_polar flags&=~(1<<0)
void pausa (unsigned long int p) //А используется с разными типами аргументов. Компилятор молчит?
{
while (p>0)
p--;
}
#pragma vector=TIMER1_COMP1_vect
__interrupt void MyInterrupt (void)
{ //А статус не сохраняете?
if(flags & (1 << 0))
{
PORTD_Bit2=0;
pausa(0x10);
PORTD_Bit0=0;pausa(pol);PORTD_Bit0=1;
pausa(0x15);
PORTD_Bit2; //Я не знал, что так можно. Но для чтения непонятно
pausa(interval);
PORTD_Bit3=0;pausa(sampl);PORTD_Bit3=1;
clr_polar;
}
else
{
PORTD_Bit2=0;pausa(0x10);
PORTD_Bit1=0;pausa(pol);PORTD_Bit1=1;
pausa(0x15);
PORTD_Bit2=1;
pausa(interval);
PORTD_Bit4=0;pausa(sampl);PORTD_Bit4=1;
set_polar;
}
return; //А это зачем?
}
int main( void )
{
PORTD=0xFF;
DDRD=0xFF;
OCR1=0x6420;
TIMSK=0x40;
TCCR1B=0x09;
__enable_interrupt();
while(1)
{
}
}
Период прерывания по таймеру точно больше интервала pausa(pol) и остальных? В обработчики таких прерываний большие задержки ставить нельзя. Объяви в обработчике статический счетчик с интервалом задержки и при каждом вызове прерывания декрементируй, будет ноль - обрабатывай.
defunct
Nov 18 2006, 09:06
2 Коляй,
Ваша программа хоть и мала, но настолько неоптимально написана в целом, что экономия 1-го байта памяти за счет резервирования регистра становится вещью просто абсурдной.
Плюс, как можно говорить о верном либо неверном поведении программы, если у вас все переменные от кототорых это поведение зависит - непроинициализированы?
Цитата(Stefan @ Nov 18 2006, 10:26)

//Я не знал, что так можно. Но для чтения непонятно
Конечно не можно. Вот так надо PORTD_Bit2=1; (На скорую руку порты просто вписал, а так они по другому в pindef.h определены.)
Экономия одного байта конечно не оправдана в такой программе, но кто знает, может надо будет дальше писать. Это пока только управление и никакой обработки.
Теперь уже воще ничего не понимаю. В АВР-студио всё нормально работает, а в протеусе опять один только канал работает.
ПРограмма работает на железе, но только с байтовой переменной в качестве флага.
Если вот так битовую структуру создать, то всё нормально работает. Вопрос только как сделать что бы он в регистре (R15 например) эту структуру держал? А он её в ОЗУ кладёт. (в свойствах проекта отведён один регистр 15.) ....
Всё, разобрался, вот так нормально стало. Спасибо всем ответившим.
__regvar __no_init
volatile struct {
unsigned char Key :1;
unsigned char Menu :1;
unsigned char Enter :1;
unsigned char LCD :1;
unsigned char Auto :1;
unsigned char ZapretLCD :1;
unsigned char polar :1;
unsigned char Save :1;
} flag @15;
prottoss
Nov 18 2006, 17:00
Цитата(Коляй @ Nov 18 2006, 23:56)

Если вот так битовую структуру создать, то всё нормально работает. Вопрос только как сделать что бы он в регистре (R15 например) эту структуру держал? А он её в ОЗУ кладёт. По-моему верхняя строчка никак к этой структуре не относится... (в свойствах проекта отведён один регистр 15.)
volatile struct {
unsigned char Key :1;
unsigned char Menu :1;
unsigned char Enter :1;
unsigned char LCD :1;
unsigned char Auto :1;
unsigned char ZapretLCD :1;
unsigned char polar :1;
unsigned char Save :1;
}flag_type;
__regvar __no_init flag_type flags @15;
__no_init
volatile struct {
unsigned char Key :1;
unsigned char Menu :1;
unsigned char Enter :1;
unsigned char LCD :1;
unsigned char Auto :1;
unsigned char ZapretLCD :1;
unsigned char polar :1;
unsigned char Save :1;
} flag @15;
Вот так заработало (__reg_var убрал), но теперь и в ОЗУ обращается и R15 изменяется! Если только в ОЗУ, то всё нормально работает, а если только в R15, то работает один цикл и опять по старому, как будто R15 сбивается. (в Протеусе в самом начале наблюдается только один правильный импульс, а дальше неправильно). Специально АСМ посмотрел к R15 всего только три обращения. Да и программа то в "три" строчки. Чему там сбивать?
Упростил всё. Устанавливал бит так flag|=(1<<0);
Сбрасывал flag&=~(1<<0);
Регистр объявлял так.
__regvar __no_init unsigned char flag @ 15;
Но компилятор генерит вот такой код ...
clt
bld r15,b0 // очистка.
set
bld r15,b0// установка.
Он что, еб...я? С этим кодом не работает!
Заменил вот таким
ori r16,0x01;
mov r15,r16;
Всё заработало нормально.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.