контроль нажатой кнопки с помошью case

Обсуждаем контроллеры компании Atmel.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: контроль нажатой кнопки с помошью case

Сообщение Demiurg »

Он частично прав. Я делал опыты, уточню работаю в IAR, зависит от количества. Для меня if менее читабельны, и так как разница несущестенна, я плюнул на if, использую switch-case.
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: контроль нажатой кнопки с помошью case

Сообщение NStorm »

Вы же понимаете, что это от многого зависит - от компилятора и его флагов сборки, от построения кода. Чтобы проверить разные варианты, нужно понимать в какой ситуации у сказавшего это возникает разница. Поэтому и прошу пример, а не домыслы и рассуждения.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: контроль нажатой кнопки с помошью case

Сообщение Demiurg »

Я и сказал, что он частично прав. Опыты сами ставьте. Потому что я зависимость не помню.
Аватара пользователя
Ariadna-on-Line
Это не хвост, это антенна
Сообщения: 1479
Зарегистрирован: Вс май 13, 2012 00:01:54

Re: контроль нажатой кнопки с помошью case

Сообщение Ariadna-on-Line »

Сохранять коды, тем более "полу-фабрикаты", сроду не приходило в голову. Мне интересно "железо", а не тонкости кода и компиляторов. Что видел по ходу "впиханий невпихуемого" в процы - то и запомнил. Switch Case, реально более синтаксически-изящная структура. Но - размеры кода диктуют... Не претендую на истину в последней инстанции.
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: контроль нажатой кнопки с помошью case

Сообщение NStorm »

Ну банальный пример, простой:
Спойлер

Код: Выделить всё

#include <avr/io.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

volatile uint8_t a, b;

int main() {
  while (1) {
    switch (a) {
      case 0:
        PORTB = 0;
        break;
      case 1:
        PORTB = 1;
        break;
      case 2:
        PORTB = 1 << 1;
        break;
      case 3:
        PORTB = 1 << 2;
        break;
    }

    if (b == 0)
      PORTB = 0;
    else if (b == 1)
      PORTB = 1;
    else if (b == 2)
      PORTB = 1 << 1;
    else if (b == 3)
      PORTB = 1 << 2;
  }
}
switch-case занимает 30 байт в итоге что при -Og, что при -Os. if занимает 50 или 44 байт при данных уровнях оптимизации:
Спойлер

Код: Выделить всё

00000032 <main>:
        break;
      case 2:
        PORTB = 1 << 1;
        break;
      case 3:
        PORTB = 1 << 2;
  32:   94 e0           ldi     r25, 0x04       ; 4

volatile uint8_t a, b;

int main() {
  while (1) {
    switch (a) {
  34:   80 91 61 00     lds     r24, 0x0061     ; 0x800061 <a>
  38:   81 30           cpi     r24, 0x01       ; 1
  3a:   49 f0           breq    .+18            ; 0x4e <__SREG__+0xf>
  3c:   30 f0           brcs    .+12            ; 0x4a <__SREG__+0xb>
  3e:   82 30           cpi     r24, 0x02       ; 2
  40:   31 f0           breq    .+12            ; 0x4e <__SREG__+0xf>
  42:   83 30           cpi     r24, 0x03       ; 3
  44:   29 f4           brne    .+10            ; 0x50 <__SREG__+0x11>
        break;
      case 2:
        PORTB = 1 << 1;
        break;
      case 3:
        PORTB = 1 << 2;
  46:   98 bb           out     0x18, r25       ; 24
        break;
  48:   03 c0           rjmp    .+6             ; 0x50 <__SREG__+0x11>

int main() {
  while (1) {
    switch (a) {
      case 0:
        PORTB = 0;
  4a:   18 ba           out     0x18, r1        ; 24
        break;
  4c:   01 c0           rjmp    .+2             ; 0x50 <__SREG__+0x11>
      case 1:
        PORTB = 1;
        break;
      case 2:
        PORTB = 1 << 1;
  4e:   88 bb           out     0x18, r24       ; 24
      case 3:
        PORTB = 1 << 2;
        break;
    }

    if (b == 0)
  50:   80 91 60 00     lds     r24, 0x0060     ; 0x800060 <_edata>
  54:   81 11           cpse    r24, r1
  56:   02 c0           rjmp    .+4             ; 0x5c <__SREG__+0x1d>
      PORTB = 0;
  58:   18 ba           out     0x18, r1        ; 24
  5a:   ec cf           rjmp    .-40            ; 0x34 <main+0x2>
    else if (b == 1)
  5c:   80 91 60 00     lds     r24, 0x0060     ; 0x800060 <_edata>
  60:   81 30           cpi     r24, 0x01       ; 1
  62:   21 f0           breq    .+8             ; 0x6c <__SREG__+0x2d>
      PORTB = 1;
    else if (b == 2)
  64:   80 91 60 00     lds     r24, 0x0060     ; 0x800060 <_edata>
  68:   82 30           cpi     r24, 0x02       ; 2
  6a:   11 f4           brne    .+4             ; 0x70 <__SREG__+0x31>
      PORTB = 1 << 1;
  6c:   88 bb           out     0x18, r24       ; 24
  6e:   e2 cf           rjmp    .-60            ; 0x34 <main+0x2>
    else if (b == 3)
  70:   80 91 60 00     lds     r24, 0x0060     ; 0x800060 <_edata>
  74:   83 30           cpi     r24, 0x03       ; 3
  76:   f1 f6           brne    .-68            ; 0x34 <main+0x2>
      PORTB = 1 << 2;
  78:   98 bb           out     0x18, r25       ; 24
  7a:   dc cf           rjmp    .-72            ; 0x34 <main+0x2>
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: контроль нажатой кнопки с помошью case

Сообщение Demiurg »

Пример не корректный.
Swithc-case:
Спойлер

Код: Выделить всё

      static u08 a;

      switch (a)
      {
         case 0: PORTB = (1<<0);
                 a = 1;
                 break;

         case 1: PORTB = (1<<1);
                 a = 2;
                 break;

         case 2: PORTB = (1<<2);
                 a = 3;
                 break;

         case 3: PORTB = (1<<3);
                 a = 4;
                 break;

         case 4: PORTB = (1<<4);
                 a = 5;
                 break;

         case 5: PORTB = (1<<5);
                 a = 6;
                 break;

         case 6: PORTB = (1<<6);
                 a = 7;
                 break;

         case 7: PORTB = (1<<7);
                 a = 0;
                 break;

      }
If:
Спойлер

Код: Выделить всё

      if (a == 0) {PORTB = (1<<0); a = 1;}
      if (a == 1) {PORTB = (1<<2); a = 2;}
      if (a == 2) {PORTB = (1<<3); a = 3;}
      if (a == 3) {PORTB = (1<<3); a = 4;}
      if (a == 4) {PORTB = (1<<4); a = 5;}
      if (a == 5) {PORTB = (1<<5); a = 6;}
      if (a == 6) {PORTB = (1<<6); a = 7;}
      if (a == 7) {PORTB = (1<<7); a = 0;}
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: контроль нажатой кнопки с помошью case

Сообщение NStorm »

И всё равно на gcc с -Os у меня switch занимает меньше. 84 байта против 114.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: контроль нажатой кнопки с помошью case

Сообщение Demiurg »

Я уже подробностей не помню. Подобный диалог и подобные примеры были несколько лет назад на форуме easyelectronics. Для меня switch-case более читабелен и структурирован.
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: контроль нажатой кнопки с помошью case

Сообщение NStorm »

Может это было в какой-нибудь старой версии компилятора? Или уровень оптимизации низкий для упрощения отладки стоял. Или еще какой нюанс.

Demiurg, кстати вот ваш пример как раз таки странный, в отсутствии else if и сменой a внутри блоков :)
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: контроль нажатой кнопки с помошью case

Сообщение Demiurg »

Ну, да ретурны забыл. Писал на смарте, потому и так.
А вообще эта ошибка иногда может стоить часов а то и дней разборок в коде. И это касается как switch-case, break return. Так и в данном случае. Я на одном проекте так нарвался. Длинный свитч кейс.
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: контроль нажатой кнопки с помошью case

Сообщение NStorm »

Некоторые IDE, кстати, предупреждают об отсутствии break'ов в конце case'ов, емнип. А вот про if уже вряд ли будут понимать.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: контроль нажатой кнопки с помошью case

Сообщение Demiurg »

Break не всегда нужно ставить. Я иногда намеренно так делаю. Когда установлено новое состояние, тут же идёт новый кейс и код. Иногда делаю так, несколько кейсов списком и код.
Типа такого:
Спойлер

Код: Выделить всё

//=============
   switch (state)
   {
      case STATE_INIT:
         io_init ();
         state = STATE_WORK;
      case STATE_WORK:
         bla-bla ();
         state = STATE_X;
         break;
   }
//=============

//=============
//------------------------------------------------------------------------
      case TUI_SERVICE_CHANGE_T_HEAT:
         blink_heat ();
         break;
//------------------------------------------------------------------------
      case TUI_SERVICE_CHANGE_T_FORMOVKA:
         blink_form ();
         break;
//------------------------------------------------------------------------
      case TUI_SERVICE_CHANGE_T_PNEV:
         blink_pnev ();
         break;
//------------------------------------------------------------------------
      case TUI_SERVICE_ENTER_SETT_QUANT:
      case TUI_SERVICE_CHANGE_SETT_QUANT:
         blink_tirag ();
         break;
//------------------------------------------------------------------------
      case TUI_SERVICE_ENTER_ADD_CURR_QUANT:
      case TUI_SERVICE_ENTER_SUB_CURR_QUANT:
      case TUI_SERVICE_CHANGE_CURR_QUANT:
         blink_curr_quant ();
         break;

      case TUI_SERVICE_CHANGE_PART:
      case TUI_SERVICE_ENTER_PART:
         blink_part ();
         break;
//=============
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: контроль нажатой кнопки с помошью case

Сообщение NStorm »

Конечно не всегда, я в курсе. Но очень часто. И поэтому IDE предупреждает очень тактично. :)
Ответить

Вернуться в «AVR»