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

Обсуждаем контроллеры компании Atmel.
Ответить
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Сб мар 07, 2015 05:49:57

Сообщение Azizbek »

Всем доброго дня, можно ли эту конструкцию переписать через оператора SWITCH CASE?

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

  if(!(PIND & (1<<PIND0))) {
      digit=0;
      )else{
	 if  if(!(PIND & (1<<PIND1))) {
            digit=1;
      )else{
	 if  if(!(PIND & (1<<PIND2))) {
            digit=2;
      )else{
	 if  if(!(PIND & (1<<PIND3))) {
            digit=3;
      )else{
	 if  if(!(PIND & (1<<PIND4))) {
            digit=4;
      )else{
	 if  if(!(PIND & (1<<PIND5))) {
            digit=5;
      )else{
	 if  if(!(PIND & (1<<PIND6))) {
            digit=6;
      )else{
	 if  if(!(PIND & (1<<PIND7))) {
            digit=7;
      )else{
	 digit=8;
      }
PS:
Будет ли работать эта конструкция?

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

switch(PINB){
	 case (1<<PINB0):digit=0;break;
	    case (1<<PINB1):digit=1;break;
	       case (1<<PINB2):digit=2;break;
		  case (1<<PINB3):digit=3;break;
		     case (1<<PINB4):digit=4;break;
			case (1<<PINB5):digit=5;break;
			   case (1<<PINB6):digit=6;break;
			      case (1<<PINB7):digit=7;break;
			       default: digit=8;break;
Последний раз редактировалось Azizbek Сб апр 18, 2020 08:45:27, всего редактировалось 1 раз.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

1. Нельзя. Хотя бы потому что это не валидная программа ни на одном известном мне языке.
2. Почему switch? Это же не оптимально. Вот, как идея, функция поиска старшего установленного бита. Под меньшую разрядность и инверсию подправить дело 3 сек.

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

uint32_t MostSignificantBitNum(uint32_t x)
{
  uint32_t pos=0;
  if(x >= 1U<<(pos+16)) pos+=16;
  if(x >= 1U<<(pos+8)) pos+=8;
  if(x >= 1U<<(pos+4)) pos+=4;
  if(x >= 1U<<(pos+2)) pos+=2;
  if(x >= 1U<<(pos+1)) pos+=1;
  return pos;
}
Добавлено after 7 minutes 9 seconds:
[uquote="Azizbek",url="/forum/viewtopic.php?p=3829285#p3829285"]PS:
Будет ли работать эта конструкция?[/uquote]Будет, но она не тождественна первоначальному "псевдокоду" ну и не оптимальна.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

да оба кода кривые.. что за конструкция if if в первом?
нет закрывающей скобки во втором...
кстати, эта конструкция не поймёт одновременного нажатия 2х кнопок
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Сб мар 07, 2015 05:49:57

Сообщение Azizbek »

Переделал код. Действительно что то перемудрил с ифами.

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

   if(PINB>=0){
if (!(PINB&0b00000001)) { digit=0; t=0;}    
if (!(PINB&0b00000010)) { digit=1; t=10000;}	    
if (!(PINB&0b00000100)) { digit=2; t=5000;}	    
if (!(PINB&0b00001000)) { digit=3; t=1000;}
if (!(PINB&0b00010000)) { digit=4; t=500;}
if (!(PINB&0b00100000)) { digit=5; t=400;}
if (!(PINB&0b01000000)) { digit=6; t=300;}
if (!(PINB&0b10000000)){  digit=7; t=200;}}
else{
   digit=0;
   t=0;
}


Просто пытаюсь сделать генератор прямоугольных импульсов с переключением частоты.
вот весь код:

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

#include <avr/io.h>
#include <util/delay.h>

int t=1;
char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x80};
int digit=0;

int main(void)
{
   DDRB=0X00;
   DDRC=0XFF;
   DDRD=0xFF;  
   
   PORTB=0XFF;
   PORTC=0Xff;
   PORTD=0x00;
   
    while (1){
       if(PINB>=0){
if (!(PINB&0b00000001)) { digit=0; t=0;}    
if (!(PINB&0b00000010)) { digit=1; t=10000;}	    
if (!(PINB&0b00000100)) { digit=2; t=5000;}	    
if (!(PINB&0b00001000)) { digit=3; t=1000;}
if (!(PINB&0b00010000)) { digit=4; t=500;}
if (!(PINB&0b00100000)) { digit=5; t=400;}
if (!(PINB&0b01000000)) { digit=6; t=300;}
if (!(PINB&0b10000000)){  digit=7; t=200;}}
else{
   digit=0;
   t=0;
}

       PORTC = ~SEGMENTE[digit];
if(digit>0){

      PORTD |= (1<<(PORTD0));
_delay_ms(t/3);
      PORTD |= (1<<(PORTD1));
_delay_ms(t);
      PORTD &= ~(1<<(PORTD0));
_delay_ms(t/3);
      PORTD &= ~ (1<<(PORTD1));
_delay_ms(t);
  
   }else{
   
    PORTD=0x00;}
       }
}

Изображение
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Сообщение BlackKilkennyCat »

digit получается лишней. достаточно t
Меня здесь больше нет
Реклама
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Сб мар 07, 2015 05:49:57

Сообщение Azizbek »

[uquote="BlackKilkennyCat",url="/forum/viewtopic.php?p=3829379#p3829379"]digit получается лишней. достаточно t[/uquote]
Не совсем понял.
через digit я вывожу индикацию на дисплей а через t задаю время задержки.
Реклама
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Сообщение BlackKilkennyCat »

if (!(PINB&0b00000001)) { digit=0; t=0;}

заменить на

if (!(PINB&0b00000001)) {PORTC = 0xC0; t=0;}

и т.д.
Если нигде больше массив SEGMENTE и его индекс использоваться не будут, то они не нужны

Я бы еще и насчёт t/3 подумал бы...
Меня здесь больше нет
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

BlackKilkennyCat, это уже оптимизация в ущерб читаемости кода. Если уж оптимизировать, то в дефайны хотя бы эти "магические числа" сегментника запихнуть. Но вообще если ресурсов хватает, то и пофиг, пусть будут digit и SEGMENTE. 10 байт оперативки тут экономить и пару слов во флэше так себе смысл имеет.
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Сообщение BlackKilkennyCat »

Согласен. хотя тут такой код, что не так уж и страшно. можно и комментариями обойтись. читать, что там из массива где-то от чего-то берется, инвертируется...
в общем, я за дефайны )
Меня здесь больше нет
Мучитель микросхем
Сообщения: 412
Зарегистрирован: Ср янв 04, 2012 11:57:40
Откуда: Алчевск

Сообщение Sergi »

А зачем в первой строке if(PINB>=0) ? Может нужно if(PINB>0) ?
Открыл глаза
Сообщения: 42
Зарегистрирован: Вс сен 03, 2017 19:43:57

Сообщение technik-1017 »

Можно попробовать так (лучше один раз считать значение из порта в переменную и далее с ней работать, а то возможно, что при разборе if/case состояние входов измениться и логика работы программы нарушиться).

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

key = ~PINB;
switch(key)
{
    case 1: digit=0; t=0; break;
    case 2: digit=1; t=10000; break;
    case 4: digit=2; t=5000; break;
    case 8: digit=3; t=1000; break;
    case 16: digit=4; t=500; break;
    case 32: digit=5; t=400; break;
    case 64: digit=6; t=300; break;
    case 128: digit=7; t=200; break;
    default: t=0; break;
}
но программа будет страшно глючить
Надо бы:
1) вывод на индикатор сделать через прерывание
2) формировать выходную частоту также используя прерывания
3) хорошо бы устранить дребезг контактов, хотя при вашей реализации это и не сильно требуется, но любая помеха на входах кнопок приведёт к самопроизвольному нажатию.

Если памяти в контроллере много (а пока ещё очень много), то можно создать массив из 256 элементов unsigned char и переменную key отправлять в этот массив, выходом будет код нажатой клавиши (0-7). Далее это код клавиши использовать в программе (возможно опять как номер элемента других массивов (индикации, частот,...))
Последний раз редактировалось technik-1017 Сб апр 18, 2020 15:41:48, всего редактировалось 1 раз.
Контактная информация:
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Сообщение BlackKilkennyCat »

в этой программе прерывания излишне, более того, можно точно сказать, когда и что выполнится. а раз это можно сказать, то будет удивительно, если что-то будет "страшно глючить"
Меня здесь больше нет
Открыл глаза
Сообщения: 42
Зарегистрирован: Вс сен 03, 2017 19:43:57

Сообщение technik-1017 »

Тогда дальнейшее развитие программы не получиться, придётся писать заново.
И не понятно какие частоты хочет получить ТС. Пока получаются две частоты сдвинутые друг от друга на 1/3.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 15655
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Это удобный метод только в том случае, если сначала выполняется антидребезговый фильтр, а затем обработка с switch/case в которой используются указатели на функции.
Удобно для клавиатуры с изменяемым по ходу работы функционалом.
Хотя в принципе, можно и антидребезг там пристроить - только уж... слишком избыточно будет.
8)
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Сб мар 07, 2015 05:49:57

Сообщение Azizbek »

Спасибо что откликнулись.
я задача в том что б получить строго зафиксированные две, сдвинутые друг от друга на одну треть, частоты при переключении кнопок. В данное время в программе примерные значения. Сколько ни читал про прерывания и таймеры так и не разобрался (наверно уже возраст не тот или мозги совсем затвердели :) ). В интернете полно схем но в основном часы. Схему хочу собрать на AtMega8A-PU.
Друг Кота
Аватара пользователя
Сообщения: 15655
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Дробим программу на две задачт - одна таймерами управляет, вторая кнопками.
Насчет 1/3 это жирновато - проще на величину, кратную двойке...
В принципе от возможностей таймеров и их конфигурации зависит.
На ассемблере это показать можно. И то предпочтительно на известных - тини2313, мега 8515...
Под Си... разве что извратом на адуринке...
8)
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Сообщение BlackKilkennyCat »

да можно и на 1/3 . Если некий фиксированный набор частот (как в этой программе), то можно хоть и на 1/2.95674324 сдвиг делать, поскольку t/3 (или t/2.95674324) можно либо просчитать до генерации, либо выкинуть вообще, просчитав вне и записав готовыми константами
Меня здесь больше нет
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Книга Вольфганг Трамперт AVR-RISC микроконтроллеры. В ней есть пример запуска таймеров. На ассемблере, но по этой книге можно понять как запускать таймеры.
Контактная информация:
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1486
Зарегистрирован: Вс май 13, 2012 00:01:54

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

Скомпилированная конструкция на Switch Case занимает намного больше памяти чем равноценная на If Else. Проверено. Сам озадачивался этим вопросом.
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Ariadna-on-Line, не верю без примера )
Ответить

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