Например TDA7294

Форум РадиоКот • Просмотр темы - Снова проблема с переменными в прерываниях
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Вт июн 24, 2025 11:00:27

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 10 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: Снова проблема с переменными в прерываниях
СообщениеДобавлено: Сб авг 12, 2023 14:54:01 
Родился

Зарегистрирован: Сб авг 12, 2023 14:39:28
Сообщений: 4
Рейтинг сообщения: 0
Решил снять показания с dht-22 и вывести их на дисплей. При этом считываю показания датчика прерываниями int1. Но чтобы я не делал (врубал volatile, отключал оптимизацию) глобальная переменная i не меняется. Тестирую в протеусе 8. В качестве проверки вывожу на дисплей "5", но так как переменная не меняется, то остаётся "B". Прошу, помогите, я новичок. UPD: снял надпись "B", потому что она несколько раз должна была гасить "5", но по итогу на экране всё равно "1", то есть i вообще не меняется.
Код:
char data[5]={0, 0, 0, 0, 0};
volatile uint8_t lll=7;
int n=0;
ISR(INT1_vect)
{
   switch(pre)
   {
      case 2:
      pre=3;
      TCNT0=0;
      break;
      
      case 3:
      if (TCNT0>=80)
      {
         pre=4;
         position (1,20);
         str_send("1");
      }
      else
      {
         pre=99;
         position (1,20);
         str_send("2");
      }
      
      case 4:
      pre=5;
      TCNT0=0;
      //TIMSK|=(1<<TOIE0);
      break;
      
      case 5:
      if (TCNT0>=50)
      {
         pre=6;
         position (1,20);
         str_send("B");
         TCNT0=0;
      }
      else
      {
         pre=100;
         position (1,20);
         str_send("C");
      }
      break;
      
      case 6:
      if (TCNT0>=70)
      {
         data[2]|=(1<<lll);
      }
      if (lll!=0)
      {
         lll--;
         TCNT2=0;
          pre=5;
         TCNT0=0;
      }
      else
      {
         position(1, 20);
         str_send ("5");
         //n++;
         //i=7;
         if(n==5)
         {
            pre=7;
            TCNT0=0;
         }
         else
         {
            pre=5;
            TCNT0=0;
         }
      }
      break;
      
      case 7:
      if (TCNT0>=80)
      {
         pre=0;
         position(1, 20);
         str_send ("5");
         //TIMSK|=(1<<TOIE0);
         //TCNT0=250;
      }
      else
      {
         position(1, 20);
         str_send ("A");
      }
      break;
      
   }
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Снова проблема с переменными в прерываниях
СообщениеДобавлено: Пн авг 14, 2023 12:07:08 
Мучитель микросхем

Карма: 4
Рейтинг сообщений: 37
Зарегистрирован: Вт фев 09, 2010 17:52:26
Сообщений: 453
Рейтинг сообщения: 0
kocheryzhka писал(а):
глобальная переменная i не меняется.
Может потому что ее у вас нет.
Или я просто ее тут не вижу
kocheryzhka писал(а):
char data[5]={0, 0, 0, 0, 0};
volatile uint8_t lll=7;
int n=0;

Выложите проект и протеус файлы, проще будет глянуть.
Так как то режет глаз изменение переменной pre внутри switch(pre).


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Снова проблема с переменными в прерываниях
СообщениеДобавлено: Пн авг 14, 2023 12:52:56 
Вымогатель припоя

Карма: 6
Рейтинг сообщений: 183
Зарегистрирован: Ср янв 06, 2010 10:01:46
Сообщений: 585
Рейтинг сообщения: 0
kocheryzhka писал(а):
Но чтобы я не делал (врубал volatile, отключал оптимизацию)

В первую очередь нужно ВКЛЮЧИТЬ оптимизацию и логику внутри своего кода.
И переменные называть нормально, и комментарии писать.
А так вообще нефига не ясно, что за дичь тут происходит, и самое главное, зачем?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Снова проблема с переменными в прерываниях
СообщениеДобавлено: Пн авг 14, 2023 13:05:00 
Друг Кота

Карма: 68
Рейтинг сообщений: 1958
Зарегистрирован: Сб дек 18, 2021 19:25:32
Сообщений: 12867
Рейтинг сообщения: 0
codenamehawk писал(а):
Так как то режет глаз изменение переменной pre внутри switch(pre).
Это нормальная конструкция. А режет глаз написание "как то" вместо "как-то" - это два разных смысла, для программиста неприемлемо игнорировать дефис.

Добавлено after 2 minutes 31 second:
Между case 3 и case 4 пропущен break;
Не знаю, что означает position(1, 20), но если это что-то типа строка-символ и автоматического сдвига нет, то высвечиваться всегда будет один символ.


Вернуться наверх
 
В продаже новые LED-драйверы XLC компании MEAN WELL с диммингом нового поколения

Компания MEAN WELL пополнила ассортимент своей широкой линейки светодиодных драйверов новым семейством XLC для внутреннего освещения. Главное отличие – поддержка широкого спектра проводных и беспроводных технологий диммирования. Новинки представлены в MEANWELL.market моделями с мощностями 25 Вт, 40 Вт и 60 Вт. В линейке есть модели, работающие как в режиме стабилизации тока (СС), так и в режиме стабилизации напряжения (CV) значением 12, 24 и 48 В.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Снова проблема с переменными в прерываниях
СообщениеДобавлено: Пн авг 14, 2023 15:15:17 
Родился

Зарегистрирован: Сб авг 12, 2023 14:39:28
Сообщений: 4
Рейтинг сообщения: 0
Спасибо Мартиану, действительно забыл break. Ещё день назад победил i, и она теперь меняется, но с p не выходит. Сейчас вроде всё закомментировал подробно. Помогите, прошу. Вот весь код.
Код:
 
#define F_CPU 1000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
#define E PD6
#define DHT PC0
uint8_t data[5]={0, 0, 0, 0, 0};
volatile uint8_t i=7;
volatile uint8_t p=0;
void E1 ()
{
   PORTD|=(1<<E);
}
void E0()
{
   PORTD&=~(1<<E);
}
void DHT1()
{
   PORTB|=(1<<DHT);
}
void DHT0()
{
   PORTB&=~(1<<DHT);
}
void writeD(unsigned int n)
{
   n<<=4;
   E1();
   PORTD&=~((1<<4)|(1<<5)|(1<<6)|(1<<7));
   PORTD|=n;
   E0();
}
void byte(unsigned int n, unsigned int b)
{
   if (b)
   {
      PORTD|=(1<<0);
   }
   else
   {
      PORTD&=~(1<<0);
   }
   
   writeD(n>>4);
   writeD(n);
}
void writeB(unsigned int n)
{
   n<<=4;
   E1();
   PORTB&=~((1<<4)|(1<<5)|(1<<6)|(1<<7));
   PORTB|=n;
   asm("nop");
   E0();
}
void byteb(unsigned int n, unsigned int b)
{
   if (b)
   {
      PORTD|=(1<<5);
   }
   else
   {
      PORTD&=~(1<<5);
   }
   
   writeB(n>>4);
   writeB(n);
}
void init_timer()
{
   TCCR0|=(1<<CS00);
   TCCR0|=(1<<CS02);
   TCCR0&=~(1<<CS01);
   TIMSK|=(1<<TOIE0);
}
void init_timer2()
{
   TCCR2|=(1<<CS20);
   TCCR2|=(1<<CS21);
   TCCR2|=(1<<CS22);
   TIMSK&=~(1<<TOIE2);
}
int status=0;
void str_send(char s[])
{
   for (int b=0; b<strlen(s); b++)
   {
      byteb(s[b],1);
   }
}
void position (unsigned int line, unsigned int column)
{
   unsigned int pos=(line*0x40+column)|0x80;
   byteb(pos, 0);
   //_delay_us(50);
}
int pre=20;
ISR(TIMER0_OVF_vect)
{
   switch(status)
   {
      case 0:
      writeB(3);
      status=1;
      TCNT0=250;
      break;
      
      case 1:
      //TCNT0=240;
      writeB(3);
      status=2;
      TCCR0=1;
      TCNT0=105;
      break;
      
      case 2:
      //TCCR0=1;
      //TCNT0=125;
      writeB(3);
      status=3;
      TCNT0=195;
      break;
      
      case 3:
      //TCNT0=195;
      writeB(2);
      status=4;
      TCNT0=195;
      break;
      
      case 4:
      //TCNT0=195;
      byteb(40, 0);
      status=5;
      TCNT0=195;
      break;
      
      case 5:
      //TCNT0=195;
       byteb(12, 0);
      status=6;
      TCNT0=195;
      break;
      
      case 6:
      //TCNT0=195;
      init_timer();
      byteb(1, 0);
      status=7;
      TCNT0=245;
      break;
      
      case 7:
      //TCNT0=195;
      byteb(6,0);
      status=8;
      TCCR0=1;
      TCNT0=205;
      break;
      
      case 8:
      status=9;
      pre=0;
      TCNT0=250;
      init_timer();
      //TIMSK&=~(1<<TOIE0);
   }
   switch (pre)
   {
      case 0: //прижимаем линию на 30 мс
      DDRD|=(1<<3);
      TCNT0=225;
      pre=1;
      break;
      
      case 1:
      DDRD&=~(1<<3); //отпускаем линию, включаем прерывания
      MCUCR|=(1<<ISC10);
      MCUCR&=~(1<<ISC11);
      GICR|=(1<<INT1);
      GIFR=(1<<INTF1);
      TCCR0=1;
      TIMSK&=~(1<<TOIE0);
      pre=2;
      break;
   }
}
ISR(INT1_vect)
{
   switch(pre)
   {
      case 2: //первое прерывание, отсчитываем 80 мкс
      pre=3;
      TCNT0=0;
      break;
      
      case 3:
      if (TCNT0>=80) //если датчик в ответ отпустил линию на 80 мкс, то всё хорошо
      {
         pre=4;
      }
      else
      {
         pre=99;
         position (1,20);
         str_send(" Error");
      }
      break;
      
      case 4:
      pre=5;
      TCNT0=0; //ожидаем первый бит 80 мкс
      break;
      
      case 5:
      if (TCNT0>=80) //если всё хорошо, то прерывание будет через 80 мкс, начало отсчёта сигнала "старт"
      {
         pre=6;
         TCNT0=0;
      }
      else
      {
         pre=100;
         position (1,20);
         str_send("Error");
      }
      break;
      
      case 6:
      if (TCNT0>=50) //если датчик прижал линию на >50 мкс, то начинаем фиксировать биты
      {
         pre=7;
         TCNT0=0;
      }
      else
      {
         pre=100;
         position (1,20);
         str_send("Error");
      }
      break;
      
      case 7:
      if (TCNT0>=70) //если больше 70 мкс, то "1"
      {
         data[p]|=(1<<i);
      }
      if (i!=0) //уменьшаем занчение i, отсчитывающей номер бита
      {
         i--;
         pre=6;
         TCNT0=0;
      }
      if (i==0)
      {
         p++; //если байт закончился, то начинаем следующий
         i=7;
         if (p==5)
         {
             pre=8; //если байты закончились, заканчиваем передачу
             TCNT0=0;
         }
         else
         {
            pre=6; //если нет, то заново переходим в 6
            TCNT0=0;
         }
      }
      break;
      
      case 8:
      if (TCNT0>=80) //если пауза 80 мкс, то заканчиваем передачу
      {
         pre=0;
         TIMSK|=(1<<TOIE0);
         TCNT0=250;
      }
      else
      {
         position(1, 20);
         str_send ("Error");
      }
      break;
   }
}
void lcd()
{
   while(status!=9);
   position (0, 0);
   str_send("Temperature:");
   position (1,0);
   str_send("Humidity:");
   position (0,20);
   str_send("Pressure:");
   //position (1,20);
   //str_send("Radiation:");
}
int main(void)
{
   sei();
   init_timer();
   DDRD|=(1<<5)|(1<<6);
   DDRB|=(1<<4)|(1<<5)|(1<<6)|(1<<7);
   DDRD&=~(1<<3);
   
   TCNT0=235;
   lcd();
   //init_timer2();
   //TCNT2=240;
   while (1)
   {
   }
}



Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Снова проблема с переменными в прерываниях
СообщениеДобавлено: Пн авг 14, 2023 15:40:34 
Говорящий с текстолитом

Карма: 25
Рейтинг сообщений: 450
Зарегистрирован: Сб май 05, 2012 20:24:52
Сообщений: 1622
Откуда: KN34PC, Болгария
Рейтинг сообщения: 0
Сокращайте действия в перерывах. Например, работать с флагами и следить за флагами в основной программе. Теперь прерывание вероятно прерывается.

Оптимизируйте сравнения и действия. Не то чтобы оптимизатор этого не делал, но делайте по возможности вручную.
Код:
  if (i != 0) //уменьшаем занчение i, отсчитывающей номер бита
  {
    ...
  }
  if (i == 0)
  {
    ...
  }

просто введите else{}


Вернуться наверх
 
Распродажа паяльного оборудования ATTEN!
Паяльные станции, паяльники и аксессуары по самой выгодной цене.

По промокоду radiokot скидка 10%
Не в сети
 Заголовок сообщения: Re: Снова проблема с переменными в прерываниях
СообщениеДобавлено: Пн авг 14, 2023 15:46:12 
Родился

Зарегистрирован: Сб авг 12, 2023 14:39:28
Сообщений: 4
Рейтинг сообщения: 0
я делал else, но надеялся на чудо, когда менял его на if. Типо, может он решил, что else относится к другому if. Не помогло. А как в данной программе контролировать флаги прерываний не внутри прерываний? Ведь в main нельзя угадать момент.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Снова проблема с переменными в прерываниях
СообщениеДобавлено: Пн авг 14, 2023 16:30:54 
Друг Кота

Карма: 68
Рейтинг сообщений: 1958
Зарегистрирован: Сб дек 18, 2021 19:25:32
Сообщений: 12867
Рейтинг сообщения: 0
как уже сказали коллеги выше, продолжайте оптимизацию. Ловить блох в неоптимизированном коде лень. например:

Код:
if (i!=0) //уменьшаем занчение i, отсчитывающей номер бита
      {
         i--;
         pre=6;
         TCNT0=0;
      }
      if (i==0)
      {
         p++; //если байт закончился, то начинаем следующий
         i=7;
         if (p==5)
         {
             pre=8; //если байты закончились, заканчиваем передачу
             TCNT0=0;
         }
         else
         {
            pre=6; //если нет, то заново переходим в 6
            TCNT0=0;
         }
      }

очевидно же, что просится
Код:
if (i!=0) //уменьшаем занчение i, отсчитывающей номер бита
      {
         i--;
         pre=6;
      }
      if (i==0)
      {
         i=7;
         if (++p==5)
         {
             pre=8; //если байты закончились, заканчиваем передачу
         }
         else
         {
            pre=6; //если нет, то заново переходим в 6   
         }
      }
TCNT0=0;

Здесь, кстати, могут отработать оба условия, если i = 1

Далее:
Код:
switch(status)
   {
      case 0:
      writeB(3);
      status=1;
      TCNT0=250;
      break;
     
      case 1:
      //TCNT0=240;
      writeB(3);
      status=2;
      TCCR0=1;
      TCNT0=105;
      break;
     
      case 2:
      //TCCR0=1;
      //TCNT0=125;
      writeB(3);
      status=3;
      TCNT0=195;
      break;
...

Если везде status становится больше на 1, то почему его не инкрементировать после switch один раз, а не в каждом case?
Полагаю, даже такое сработает:
Код:
switch(status++) //а здесь написать комментарий, почему статус инкрементируется.


Последний раз редактировалось Martian Пн авг 14, 2023 16:40:31, всего редактировалось 2 раз(а).

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Снова проблема с переменными в прерываниях
СообщениеДобавлено: Пн авг 14, 2023 16:35:20 
Родился

Зарегистрирован: Сб авг 12, 2023 14:39:28
Сообщений: 4
Рейтинг сообщения: 0
не знаю, это не помогает. Оптимизацию подключил


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Снова проблема с переменными в прерываниях
СообщениеДобавлено: Пн авг 14, 2023 16:39:33 
Друг Кота

Карма: 68
Рейтинг сообщений: 1958
Зарегистрирован: Сб дек 18, 2021 19:25:32
Сообщений: 12867
Рейтинг сообщения: 0
это очень помогает, так как убирает ненужные строки, упрощает чтение (понимание кода), а также позволяют сделать логику менее ошибочной.
например, veso74 предложил else. В случае с i == 1 с else и без него логика выполнения меняется.

Оптимизация в компиляторе - это совершенно не то.

А вообще, возьмите и распишите всё блок-схемой.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 10 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: Google Adsense [Bot] и гости: 14


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y