Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 190
Зарегистрирован: Чт фев 24, 2011 13:00:49

Сообщение wellcom »

vitalik_1984 писал(а):А что за сложный алгоритм?
Зачем делить на что то?
Это что на дисплей выход?По четыре бита двигать?
Не похоже.Или это через сдвиговый регистр вывод в дисплей?
это вывод N битов из масива последовательно в регистр 74НС595, где каждых три бита соответствуют отдельному 3-х значному двоичному коду, причем разряды этого кода могут ити не попорядку а в разброс
:solder: 32-х ядерный процессор из П213В
Реклама
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Сообщение ut1wpr »

wellcom писал(а):есть такое выражение, как оно будет выполнятся согласно приоритетности С?

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

if((Buffer[Bit/8]>>(Bit%8))&0x01)
0. Вычислить индекс массива Bit/8
1. Вычислить остаток (Bit%8)
2. Прочитанные данные по вычисленному индексу
3. Сдвинуть данные вправо на число-остаток
4. обнулить кроме первого бита

т.е. (([2]>3>(1))&4)
Правильно ли я думаю? :roll:
Неправильно.
Приведен пример тестирования бита № Bit в массиве последовательно расположенных байтов Buffer[].
Положим, нужно узнать состояние бита 133 в массиве байтов Buffer[].
Упрощаем себе жизнь, а компилятору пофиг. Все равно оптимизирует и оттранслирует так же, как и в приведенном примере.

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

#define Mask 0x01
char Buffer[];
char Bit = 133; // Порядковый номер тестируемого бита в массиве байтов
char Idx = Bit / 8;  // Определили в каком байте будет находится тестируемый бит
char Pos = Bit % 8; // Определили позицию бита в байте
Теперь собственно надо сместить тестируемый бит под тест-маску 0b00000001 и определить, истинно выражение или ложно

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

if ( Buffer[Idx] >> Pos &  Mask ) /* do it if true */; else /* do it if false */;
А теперь сравните написанную исходную строку с приведенным фрагментом. И учтите, что результат после компиляции будет один и тот же.
Что проще для понимания? В чем выигрыш первого варианта?
Вот вам и Си!
Напоследок эквивалентная запись:

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

Buffer[Idx] >> Pos &  Mask ? /* do it if true */ : /* do it if false */;
Кому как больше нравится. :)
С уважением,
Виктор.
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

А деление то тут причем?
Вот же вывод

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

void data_shift(unsigned char DATA,unsigned char n_bits,unsigned char start_bit){
unsigned char i,temp;
temp=1<<start_bit;
	for (i=1;i<n_bits;i++){
       if (DATA&temp) set_bit(OUT_PORT,OUT_PIN);
       else clear_bit(OUT_PORT,OUT_PIN);
       DATA=DATA>>1;
	}
} 
[b]Ошибки исправлены[/b]
Правда не совсем правильно понял условие.Данная функция выводит n_bits бит начиная с start_bit из байта.
Последний раз редактировалось vitalik_1984 Ср мар 14, 2012 19:59:46, всего редактировалось 3 раза.
В поисках истины человек развивается.
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город

Сообщение Мастер Ломастер »

ut1wpr писал(а):Напоследок эквивалентная запись:

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

Buffer[Idx] >> Pos &  Mask ? /* do it if true */ : /* do it if false */;
Кому как больше нравится. :)
это смотря чему эквивалентная :) в общем случае эта запись НЕ ЭКВИВАЛЕНТНА оператору if-else. не надо вводить в заблуждение начинающих.
битва с дураками проиграна, победители торжествуют. слава победителям!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Сообщение ut1wpr »

vitalik_1984 писал(а):А деление то тут причем?
Вот же вывод

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

void data_shift(unsigned char DATA,n_bits,start_bit){
temp=temp<<start_bit;
for (i=1;i<n_bits;i++){
       if (DATA&temp) setbit(OUT_PORT,OUT_PIN);
       else clearbit(OUTPORT,OUT_PIN);
       DATA=DATA>>1;
}} 
 
может строчек и больше, зато всем понятно что тут происходит.
Встречный вопрос - а при чем тут вывод?
Я ответил на вопрос по выражению:

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

if((Buffer[Bit/8]>>(Bit%8))&0x01)
Если вам нужно организовать побитовый вывод массива из N байтов, с применением данного выражения, фрагмент будет выглядеть таким образом:
char i;
for ( i = 0; i != N*8; i++ ){
(Buffer[i/8] >> i%8) & 0x01 ? setbit(OUT_PORT,OUT_PIN); : setbit(OUT_PORT,OUT_PIN);
.......
}
Ничем принципиально от вашего фрагмента эта запись не отличается.
Единственное, она будет правильно работать для любого к-ва байтов в массиве.
Ваш пример содержит ряд ошибок и имеет право не работать вообще.
Похоже, вы привели лишь часть программы. На месте компилятора я бы сразу ругнулся на отсутствие типа данных (определение) переменной temp.
Быть может это глобальная переменная, объявленная за пределами вашей функции?
Ваша DATA имеет тип unsigned char? что наводит на мысль о выводе битов всего лишь из одного байта. В таком случае вам необходимо создать еще один внешний цикл, в котором вам придется перебирать байты внешне объявленного массива и побайтно передавать их в вашу функцию.
Скрывать часть программы, ссылаясь на ее незавершенный фрагмент не совсем корректно.
Все что я хотел сказать - я уже сказал. Считаю дальнейшее пережевывание этого мелкого фрагмента недостойной тратой нашего общего драгоценного времени.
Разрешите откланяться и выйти из пустого обсуждения.
С уважением,
Виктор.
Реклама
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Сообщение ut1wpr »

Мастер Ломастер писал(а):
ut1wpr писал(а):Напоследок эквивалентная запись:

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

Buffer[Idx] >> Pos &  Mask ? /* do it if true */ : /* do it if false */;
Кому как больше нравится. :)
это смотря чему эквивалентная :) в общем случае эта запись НЕ ЭКВИВАЛЕНТНА оператору if-else. не надо вводить в заблуждение начинающих.
Скорее всего, неправ в том, что не применил оператор присваивания. bit = (test) ? 1 : 0; А вот потом уж применять if .. else ..
Надо было получить значение 0 или 1 в зависимости от тестируемого бита, а потом уже поднимать или опускать бит порта. Да, здесь моя ошибка.
С уважением,
Виктор.
Реклама
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 190
Зарегистрирован: Чт фев 24, 2011 13:00:49

Сообщение wellcom »

Да, много чего нового для себя узнал, благодарю за дискуссию! :)
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

ut1wpr писал(а): Если вам нужно организовать побитовый вывод массива из N байтов, с применением данного выражения, фрагмент будет выглядеть таким образом:
char i;
for ( i = 0; i != N*8; i++ ){
(Buffer[i/8] >> i%8) & 0x01 ? setbit(OUT_PORT,OUT_PIN); : setbit(OUT_PORT,OUT_PIN);
.......
}
Ничем принципиально от вашего фрагмента эта запись не отличается.
Единственное, она будет правильно работать для любого к-ва байтов в массиве.
и почему вы решили,что моя функцию не сможет вывести Любое количество байтов?
ut1wpr писал(а): Ваш пример содержит ряд ошибок и имеет право не работать вообще.
а вы уверены что сами то правильно код написали?
for ( i = 0; i != N*8; i++ ){
(Buffer[i/8] >> i%8) & 0x01 ? setbit(OUT_PORT,OUT_PIN); : CLEARBIT(OUT_PORT,OUT_PIN);
ut1wpr писал(а): Похоже, вы привели лишь часть программы.
да это часть программы.но и у вас похоже не вся программа
а как у вас учитывается что отсчет с нуля идет,а вы пишете,что N байтов массив.если от нуля до N досчитать будет N+1 счет.
В поисках истины человек развивается.
Контактная информация:
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Сообщение ut1wpr »

vitalik_1984 писал(а):а как у вас учитывается что отсчет с нуля идет,а вы пишете,что N байтов массив.если от нуля до N досчитать будет N+1 счет.
А каким образом ведущая переменная цикла дойдет до N в этой организации цикла?

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

for ( i = 0; i != N*8; i++ )
Будет выполнен перебор от 0 до (8*N)-1.
Рекомендую не использовать в вычислениях завершения петли цикла операции больше/меньше. При единичных приращениях вы не пропустите лимит, проверяя на неравенство, а вот как поведут себя числа с ошибочно определенными типами (знаковые/беззнаковые) на сравнениях больше/меньше, трудно сказать. Могут возникнуть ошибки. Причем трудно отлавливаемые.
Рекомендую, но не настаиваю. Делайте, как угодно.
С уважением,
Виктор.
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город

Сообщение Мастер Ломастер »

ut1wpr писал(а):Рекомендую не использовать в вычислениях завершения петли цикла операции больше/меньше.
с учетом безумной любви многих делать циклы по глобальным переменным с невразумительными односимвольными именами, я бы наоборот, категорически не советовал пользоваться этой рекомендацией, ибо глобальная переменная может быть "случайно" изменена в прерывании, и тогда цикл может не кончиться никогдавовремя.

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

но это только пояснение, любая точка зрения имеет право на существование :)
битва с дураками проиграна, победители торжествуют. слава победителям!
Контактная информация:
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Сообщение ut1wpr »

Мастер Ломастер писал(а):делать циклы по глобальным переменным
А где у мну сказано про глобальность ведущей переменной цикла?
контролировать диапазон допустимости значения, а не равенство или неравенство "краю" диапазона
На мой взгляд - игра слов. В любом случае "диапазон" определяется его граничными значениями. И от сравнения с ними не уйти. А там уж поступайте, как вам будет угодно. Либо определяйте превышение, либо точное совпадение с... Я ведь сделал оговорку про единичное приращение :) Вот только на надежности программы это не скажется, у неё другие составляющие.
но это только пояснение, любая точка зрения имеет право на существование :)
Дык и я об том же. :) С удовольствием жму лапу!
С уважением,
Виктор.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

Хочу сделать пояснение к своей функции- я подумал нужно найти n бит из байта.А тут получается весь массив рассматривается.Теперь вкурил зачем это деление :) хитрО.
В поисках истины человек развивается.
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город

Сообщение Мастер Ломастер »

ut1wpr писал(а):А где у мну сказано про глобальность ведущей переменной цикла?
да у вас-то, слава богу, нигде не сказано, но вот сплошь и рядом я встречаю у других глобальные перменные для цикла - вот и "спрогнозировал" :) :beer:
ut1wpr писал(а):На мой взгляд - игра слов. В любом случае "диапазон" определяется его граничными значениями. И от сравнения с ними не уйти.
я поясню. если вы написали for(i=0; i != 5; i++) и в результате, скажем, сбоя ячейки памяти перемення i после значения 4 станет равна равна 6 (1 бит поменяется), то цикл отработает еще 256 раз! а если было бы написано for(i=0; i < 5; i++) этого не случилось бы. я не утверждаю, что мой вариант на 100% спасет от неприятностей, но во многих случаях он предпочтительнее скачка в числе итераций цикла. наиболее надежным было бы for(i=0; (i < 5) && (i >= 0); i++) - но это уже менее удачно по быстродействию.
битва с дураками проиграна, победители торжествуют. слава победителям!
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула

Сообщение IfoR »

Вы уже на пару страниц такую тут ахинею порасписали, блин. А уже пятый раз захожу сюда и столько же раз офигиваю.

Великие носители истин vitalik_1984, Мастер Ломастер и ut1wpr сошлись в одном месте. Такое не часто увидишь.
Последний раз редактировалось IfoR Ср мар 14, 2012 20:29:29, всего редактировалось 1 раз.
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город

Сообщение Мастер Ломастер »

IfoR писал(а):Вы уже на пару страниц такую тут ахинею порасписали, блин. А уже пятый раз захожу сюда и столько же раз офигиваю.
не заходите :)))
битва с дураками проиграна, победители торжествуют. слава победителям!
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула

Сообщение IfoR »

Это как три разговорных бота в конференции. Каждый найдёт какую фигню ответить на предыдущую :)
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Контактная информация:
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Сообщение ut1wpr »

IfoR писал(а):Это как три разговорных бота в конференции. Каждый найдёт какую фигню ответить на предыдущую :)
Ошибка! Ботов уже четыре. Кто четвертый - догадываетесь...
/dev/urandom - гигабайты информации.
/dev/null - место ее надежного хранения... :)
С уважением,
Виктор.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула

Сообщение IfoR »

Да ну. Я здесь не предлагаю if () заменять на ()? ;: ; или for(; < ;) на for (; != ;) и наоборот. Я просто тупо офигиваю и только сейчас решился запостить пост.
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 302
Зарегистрирован: Пн янв 07, 2008 16:56:28
Откуда: Минск

Сообщение levaclaus »

Вопрос 1
Все порты заняты, но позарез надо заюзать прерывание INT0. Можно ли одновремено настроить порт на выход (к порту подключен сегмент матрицы) и использовать прерывания?

Вопрос 2
Собственно, на портD подключено всего 4 разряда, ещё 4 пина остаются непригодны для использования, т.к. в коде ниже мы отключаем весь портD. Как сделать отключение только 4 пинов? Т.е. PORTD.0 = 0; PORTD.1 = 0; PORTD.2 = 0; PORTD.3 = 0; Так? Или есть вариант покомпактнее?

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

//Timer 0 interrupt
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
    unsigned char m;
    bit c;
    
    TCNT0  = 0; 

   if (isprint(str[SignPlace]) == 0) {
        m = 10; 
        c   = 1;
    };
    
    if (c == 0) {
        m   = toint(str[SignPlace]);
    }
                            
    PORTD   = 0;
    PORTB   = 0;
    PORTB   =   digit_ar[m];
    PORTD   =   SPlace_ar[SignPlace];
    
    c = 0;
    SignPlace = SignPlace + 1;
    if (SignPlace == 4) SignPlace = 0;

}  
Встал на лапы
Сообщения: 128
Зарегистрирован: Пт сен 23, 2011 23:49:20
Откуда: Симферополь, Украина

Сообщение juzik »

Настройка порта

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

DDRD = 0b11110000;
Подтяжка 1 и 3 битов

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

PORTD |= 0b1010;
Запись в порт

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

PORTD |= 0xF0 & (value)
Чтение из порта

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

value = PIND & 0x0F
Ответить

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