опрос кнопок MEGA8

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
neox
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Сб мар 10, 2012 21:14:01

опрос кнопок MEGA8

Сообщение neox »

Здравствуйте! помогите плиз с кусочком кода на "С" (пишу в компиляторе CVAVR).
задача такова: восемь кнопок одной стороной сидят на массе а второй подключены к PORTD (PORTD настроен и включена подтяжка), как написать что если любые две из восьми кнопок выключены тогда PORTD.1=0 а если все восемь включены тогда PORTD.1=1 ?
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Re: опрос кнопок MEGA8

Сообщение Mishany »

использовать оператор с условием if
заводим переменную для каждой кнопки удобнее использовать 1 байт для 8 кнопок где 1 нажата 0 отпущена, если сумма всех значений равна 2 то ....., если 8 тогда.....
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: опрос кнопок MEGA8

Сообщение COKPOWEHEU »

А можно сдвигами и сложениями. Вспомнить, что сдвиг сохраняет не поместившийся разряд в бит С, а при сложении этот бит можно добавить к слагаемым за 1 команду. На ассемблере это будет реализовать проще и быстрее чем на Си. А потом также, сравнением с 2 и 8. Подсчет кнопок займет 16 тактов. С учетом нициализации, но без учета if'ов и ввода - 18.
А можно использовать битовую магию, у меня получилось 15 тактов на подсчет кнопок. Не считая if'ов и ввода. Вот это решение даже приведу
СпойлерХотя и не проверял

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

.def temp=r16
.def sum=r17

ANY_PROC:
     push temp //на всякий случай сохраняем временные регистры
     push sum
     in sum,PINB //считывание состояний кнопок. Наверное, и ввод и вывод в PORTD ошибка, пусть кнопки висят на PORTB
     mov temp,sum
     lsr temp //сдвиг на 1 байт
     andi sum,0x55 //первое волшебное число
     andi temp,0x55
     add sum,temp
     mov temp,sum
     lsr temp //сдвиг на 2 байта
     lsr temp
     andi sum,0x33 // второе волшебное число
     andi temp,0x33
     add sum,temp
     mov temp,sum
     swap temp //сдвиг на 4 байта, старший полубайт в данном случае неважен, он будет отрезан andi sum,0x0F
     add sum,temp
     andi sum,0x0F // третье волшебное число
//проверки. Поскольку предыдущая часть считает лог.1, сравнивать надо отпущенные кнопки, а не нажатые.
     cpi sum,0
          breq BTN_8
     cpi sum,6
          breq BTN_2
FUNC_END: //конец процедуры, посстанавливаем сохраненные значения
     pop sum
     pop temp
ret
BTN_8:
     sbi PORTD,1
rjmp FUNC_END
BTN_2:
     cbi PORTD,1
rjmp FUNC_END
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: опрос кнопок MEGA8

Сообщение pyzhman »

Стоять-бояться! Это как? -
neox писал(а):...подключены к PORTD...тогда PORTD.1=0...тогда PORTD.1=1

Включать, выключать подтяжку?
Docendo discimus
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: опрос кнопок MEGA8

Сообщение ARV »

а к чему такая спешка - такты считать?! у меня вот достаточно тупой, без всякой магии, вариант потребляет максимум 55 тактов на вычисление количества единиц во входном байте, причем это максимум, если ни одной единицы в байте нет - и тактов по-моему 3 всего :)

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

uint8_t sum=0;
// переменная data содержит анализируемый байт   
for(;data;data>>=1) sum += !!(data & 1);
// в переменной sum количество единиц, которые были в data
зато кратко и понятно, не то, что всякая ассемблерная магия :)))
P.S. про 55 тактов я соврал, поспешил. Прошу простить
Последний раз редактировалось ARV Ср дек 10, 2014 08:11:51, всего редактировалось 1 раз.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: опрос кнопок MEGA8

Сообщение COKPOWEHEU »

Когда разница в 3.5 раза, уже стоит задуматься. Для данной задачи оптимизация не нужна, можно хоть if'ами каждый бит по отдельности считать. И, кстати, это все равно быстрее, 16 тактов независимо от размера. Что-то мне кажется, что среднее время работы у такого кода лучше, чем у Вашего, хотя минимальное, конечно, хуже.

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

 char x=PINB;
 char sum=0;
 if(x & (1<<0))sum++;
 if(x & (1<<1))sum++;
 if(x & (1<<2))sum++;
 if(x & (1<<3))sum++;
 if(x & (1<<4))sum++;
 if(x & (1<<5))sum++;
 if(x & (1<<6))sum++;
 if(x & (1<<7))sum++;
Но как же можно не поразвлекаться с побитовой магией и ассемблером!
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

Re: опрос кнопок MEGA8

Сообщение BCluster »

ARV писал(а):

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

!!(data & 1);

а зачем данная конструкция туть? я имею ввиду двойное отрицание.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: опрос кнопок MEGA8

Сообщение WiseLord »

Хотел было сначала ответить: чтобы любое ненулевое число превращалось в 1. Но потом понял, что в скобках вообще-то не любое число, а либо 0, либо 1. Так что да, двойное отрицание не нужно. И вполне хватит

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

for(sum = 0; data; data >>= 1) sum += (data & 1);
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Re: опрос кнопок MEGA8

Сообщение Mishany »

в виде функции, которую можно вызывать по мере надобности и не влияющую на все остальное, как то так:
Спойлер

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

void button(void)
{
unsigned char a,i;
for(i=0;i<8;i++)
   {
    if((PIND&(1<<i))==0)   //проверяем в цикле все порты D
       {a++;}   //считаем сколько кнопок вкл/выкл
   }
if(a==6)   // если 2 из 8 выключены
   {
   //что то делаем....
   }
if(a==8)   // если все включены
   {
   //что то делаем....
   }
a=0;
}
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: опрос кнопок MEGA8

Сообщение ARV »

COKPOWEHEU писал(а):уже стоит задуматься
да, стоит.
как раз хотел спросить: а вы этот алгоритм сами придумали или просто содрали из книжки Кнута (если не ошибаюсь)? если сами - честь вам и хвала. однако сумеете ли преобразовать свой код для 16, 32 или 64-битных чисел? согласны, что мой код сработает для любой (в разумных пределах) разрядности переменной data без какой бы то ни был модификации?
WiseLord писал(а):чтобы любое ненулевое число превращалось в 1. Но потом понял
перемудрил, признаю :)

среднее быстродействие моего варианта можно еще повысить, если цикл записать в соответствии с условиями задачи

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

for(;(sum < 2) && data; data >>=1)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Miw
Первый раз сказал Мяу!
Сообщения: 33
Зарегистрирован: Пн ноя 24, 2014 16:58:41

Re: опрос кнопок MEGA8

Сообщение Miw »

COKPOWEHEU писал(а):А можно использовать битовую магию, у меня получилось 15 тактов на подсчет кнопок. Не считая if'ов и ввода. Вот это решение даже приведу


Вау! Это какой-то известный алгоритм или сам придумал ?
придумал новые детальки : оптимистор и пессимистор ...
осталось придумать для чего они нужны ))))
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

Re: опрос кнопок MEGA8

Сообщение BCluster »

А еще можно предподсчет сделать, если не жалко 256 байт. Оч быстро будет )
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: опрос кнопок MEGA8

Сообщение COKPOWEHEU »

if((PIND&(1<<i))==0)
Если процессор будет считать честно - медленно будет, лучше завести для (1<<i) отдельныю переменную.
да, стоит.
как раз хотел спросить: а вы этот алгоритм сами придумали или просто содрали из книжки Кнута (если не ошибаюсь)?
Содрал, но не с Кнута, а с говнокода, там же понял принцип работы. Продолжить ряд магических чисел? 0x5555, 0x3333, 0x0F0F, 0x00FF, вроде так для двухбайтных чисел.
Ваш код сработает для любой разрядности, но время иногда бывает критичным, а примерно для половны чисел (у которых старший бит равен 1) оно будет максимальным.
ARV писал(а):среднее быстродействие моего варианта можно еще повысить, если цикл записать в соответствии с условиями задачи

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

for(;(sum < 2) && data; data >>=1)
И при sum=2 оно повиснет.
А еще можно предподсчет сделать, если не жалко 256 байт. Оч быстро будет )

Упрощенный вариант с массивом из 16 элементов.

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

unsigned char len[16]={0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
unsigned char calc(unsigned char x){
 return len[x&0x0F]+len[x>>4];
}
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: опрос кнопок MEGA8

Сообщение ARV »

COKPOWEHEU писал(а):И при sum=2 оно повиснет.
почему?!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: опрос кнопок MEGA8

Сообщение COKPOWEHEU »

Условие (sum<2) будет всегда возвращать false, а false && x = false независимо от х.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: опрос кнопок MEGA8

Сообщение ARV »

COKPOWEHEU писал(а):Условие (sum<2) будет всегда возвращать false, а false && x = false независимо от х.

ну дык верно, условие false и цикл завершается. с чего ему виснуть?
за пределами цикла смотрим на sum - если оно 0 - значит нет ни одной 1, если не ноль - как минимум что-то есть...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: опрос кнопок MEGA8

Сообщение COKPOWEHEU »

Верно, прошу прощения.
Ответить

Вернуться в «Разные вопросы по МК»