Форум РадиоКот https://radiokot.ru/forum/ |
|
Снова проблема с переменными в прерываниях https://radiokot.ru/forum/viewtopic.php?f=57&t=189529 |
Страница 1 из 1 |
Автор: | kocheryzhka [ Сб авг 12, 2023 14:54:01 ] |
Заголовок сообщения: | Снова проблема с переменными в прерываниях |
Решил снять показания с 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; } } |
Автор: | codenamehawk [ Пн авг 14, 2023 12:07:08 ] |
Заголовок сообщения: | Re: Снова проблема с переменными в прерываниях |
kocheryzhka писал(а): глобальная переменная i не меняется. Может потому что ее у вас нет.Или я просто ее тут не вижу kocheryzhka писал(а): char data[5]={0, 0, 0, 0, 0}; volatile uint8_t lll=7; int n=0; Выложите проект и протеус файлы, проще будет глянуть. Так как то режет глаз изменение переменной pre внутри switch(pre). |
Автор: | metan [ Пн авг 14, 2023 12:52:56 ] |
Заголовок сообщения: | Re: Снова проблема с переменными в прерываниях |
kocheryzhka писал(а): Но чтобы я не делал (врубал volatile, отключал оптимизацию) В первую очередь нужно ВКЛЮЧИТЬ оптимизацию и логику внутри своего кода. И переменные называть нормально, и комментарии писать. А так вообще нефига не ясно, что за дичь тут происходит, и самое главное, зачем? |
Автор: | Martian [ Пн авг 14, 2023 13:05:00 ] |
Заголовок сообщения: | Re: Снова проблема с переменными в прерываниях |
codenamehawk писал(а): Так как то режет глаз изменение переменной pre внутри switch(pre). Это нормальная конструкция. А режет глаз написание "как то" вместо "как-то" - это два разных смысла, для программиста неприемлемо игнорировать дефис.Добавлено after 2 minutes 31 second: Между case 3 и case 4 пропущен break; Не знаю, что означает position(1, 20), но если это что-то типа строка-символ и автоматического сдвига нет, то высвечиваться всегда будет один символ. |
Автор: | kocheryzhka [ Пн авг 14, 2023 15:15:17 ] |
Заголовок сообщения: | Re: Снова проблема с переменными в прерываниях |
Спасибо Мартиану, действительно забыл 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) { } } |
Автор: | veso74 [ Пн авг 14, 2023 15:40:34 ] |
Заголовок сообщения: | Re: Снова проблема с переменными в прерываниях |
Сокращайте действия в перерывах. Например, работать с флагами и следить за флагами в основной программе. Теперь прерывание вероятно прерывается. Оптимизируйте сравнения и действия. Не то чтобы оптимизатор этого не делал, но делайте по возможности вручную. Код: if (i != 0) //уменьшаем занчение i, отсчитывающей номер бита { ... } if (i == 0) { ... } просто введите else{} |
Автор: | kocheryzhka [ Пн авг 14, 2023 15:46:12 ] |
Заголовок сообщения: | Re: Снова проблема с переменными в прерываниях |
я делал else, но надеялся на чудо, когда менял его на if. Типо, может он решил, что else относится к другому if. Не помогло. А как в данной программе контролировать флаги прерываний не внутри прерываний? Ведь в main нельзя угадать момент. |
Автор: | Martian [ Пн авг 14, 2023 16:30:54 ] |
Заголовок сообщения: | Re: Снова проблема с переменными в прерываниях |
как уже сказали коллеги выше, продолжайте оптимизацию. Ловить блох в неоптимизированном коде лень. например: Код: 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++) //а здесь написать комментарий, почему статус инкрементируется.
|
Автор: | kocheryzhka [ Пн авг 14, 2023 16:35:20 ] |
Заголовок сообщения: | Re: Снова проблема с переменными в прерываниях |
не знаю, это не помогает. Оптимизацию подключил |
Автор: | Martian [ Пн авг 14, 2023 16:39:33 ] |
Заголовок сообщения: | Re: Снова проблема с переменными в прерываниях |
это очень помогает, так как убирает ненужные строки, упрощает чтение (понимание кода), а также позволяют сделать логику менее ошибочной. например, veso74 предложил else. В случае с i == 1 с else и без него логика выполнения меняется. Оптимизация в компиляторе - это совершенно не то. А вообще, возьмите и распишите всё блок-схемой. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |