Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Где с флагами косяк?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Коляй
Ребята, где то накосячил с флагами. Подскажите кто знает? Программа простая, только выводами дёргать. В ИАРе 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)
  {
    
  }

}
viael
а че эти переменные pol,sampl, interval; ничем не инициализируются?
Коляй
Цитата(viael @ Nov 17 2006, 22:30) *
а че эти переменные pol,sampl, interval; ничем не инициализируются?

Подбираются при настройке.
Stefan
Цитата(Коляй @ 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)
  {
    
  }

}
Abell
Период прерывания по таймеру точно больше интервала pausa(pol) и остальных? В обработчики таких прерываний большие задержки ставить нельзя. Объяви в обработчике статический счетчик с интервалом задержки и при каждом вызове прерывания декрементируй, будет ноль - обрабатывай.
defunct
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, 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;

Всё заработало нормально.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.