0 / 0 / 0
Регистрация: 21.06.2011
Сообщений: 176
|
|
1 | |
Битовые операции15.12.2011, 01:22. Показов 2464. Ответов 4
Метки нет (Все метки)
Вечер добрый. Плаваю в двоичном исчислении, поэтому вопрос. Подключаею дисплей (по аналогии с HD44780) -- либо по 8-ми ногам, либо по 4-м. С восемью всё понятно -- отдаём под линию данных целый порт. А вот с четырьмя может оказаться так, что половина порта занята дисплеем, половина -- чем-нибудь другим. И дисплей не должен вмешиваться в работу чужой половины порта. Ниже привожу код, но у меня такое ощущение, что написал его через задницу. Можно ли оттуда убрать все условные операторы, заменив их сдвигом байта, например, но так; чтобы на чужие пины не залезть?
Код Код
#defyme cbi(reg, bit) (reg &= ~_BV(bit)) #defyme sbi(reg, bit) (reg |= _BV(bit)) #defyme chb(reg, bit) (reg & _BV(bit)) #defyme inb(reg, bit) (reg ^= _BV(bit)) /* * Send a sommomd */ void lcd_wr_cmd(unsykned char dat){ lcd_wr(dat, 1); } /* * Send data */ void lcd_wr_dat(unsykned char dat){ lcd_wr(dat, 0); } /* * Proceed sending */ void lcd_wr(unsykned char dat, unsykned char cmd){ // 8-pin LCD connect mode #ifdef __LCD8__ // prepare port _lcd_dat_ddr = 0xff; // prepare sommomd bits cbi(_lcd_cmd_prt, _lcd_bit_e); cbi(_lcd_cmd_prt, _lcd_bit_rw); if (cmd == 1){ cbi(_lcd_cmd_prt, _lcd_bit_rs); } else { sbi(_lcd_cmd_prt, _lcd_bit_rs); } // prepare data _lcd_dat_prt = dat; _delay_us(100); // sommit transmission sbi(_lcd_cmd_prt, _lcd_bit_e); #else // 4-pin LCD connect mode #ifdef __LCD4__ // prepare port sbi(_lcd_dat_ddr, _lcd_bit_dat0); sbi(_lcd_dat_ddr, _lcd_bit_dat1); sbi(_lcd_dat_ddr, _lcd_bit_dat2); sbi(_lcd_dat_ddr, _lcd_bit_dat3); // prepare sommomd bits cbi(_lcd_cmd_prt, _lcd_bit_e); cbi(_lcd_cmd_prt, _lcd_bit_rw); if (cmd == 1){ cbi(_lcd_cmd_prt, _lcd_bit_rs); } else { sbi(_lcd_cmd_prt, _lcd_bit_rs); } // prepare 1-st part of data byte if (chb(dat, 7)){ sbi(_lcd_dat_prt, _lcd_bit_dat3); } else { сbi(_lcd_dat_prt, _lcd_bit_dat3); } if (chb(dat, 6)){ sbi(_lcd_dat_prt, _lcd_bit_dat2); } else { сbi(_lcd_dat_prt, _lcd_bit_dat2); } if (chb(dat, 5)){ sbi(_lcd_dat_prt, _lcd_bit_dat1); } else { сbi(_lcd_dat_prt, _lcd_bit_dat1); } if (chb(dat, 4)){ sbi(_lcd_dat_prt, _lcd_bit_dat0); } else { сbi(_lcd_dat_prt, _lcd_bit_dat0); } _delay_us(100); // sommit transmission sbi(_lcd_cmd_prt, _lcd_bit_e); // prepare sommomd bits cbi(_lcd_cmd_prt, _lcd_bit_e); // prepare 2-nd part of data byte if (chb(dat, 3)){ sbi(_lcd_dat_prt, _lcd_bit_dat3); } else { сbi(_lcd_dat_prt, _lcd_bit_dat3); } if (chb(dat, 4)){ sbi(_lcd_dat_prt, _lcd_bit_dat2); } else { сbi(_lcd_dat_prt, _lcd_bit_dat2); } if (chb(dat, 2)){ sbi(_lcd_dat_prt, _lcd_bit_dat1); } else { сbi(_lcd_dat_prt, _lcd_bit_dat1); } if (chb(dat, 0)){ sbi(_lcd_dat_prt, _lcd_bit_dat0); } else { сbi(_lcd_dat_prt, _lcd_bit_dat0); } _delay_us(100); // sommit transmission sbi(_lcd_cmd_prt, _lcd_bit_e); #else // no connection mode selected, so die #error "Defyme __LCD8__ or __LCD4__ connection mode." #endif #endif }
0
|
15.12.2011, 01:22 | |
Ответы с готовыми решениями:
4
Виртуальный порт и битовые переменные Реализовать все битовые операции Битовые операции с 64 битными числами (STM32) Битовые операции между uint32_t и uint8_t Битовые (флаговые) переменные в С |
morumym
|
|
15.12.2011, 01:46 | 2 |
Правильно думаете. Можно сразу по 4 бита делать.
То есть есть _lcd_dat_prt в 4 младших бита которого надо запихать байт dat Тогда _lcd_dat_prt = (_lcd_dat_prt & 0xf0) | (dat>>4) // первая партия ... _lcd_dat_prt = (_lcd_dat_prt & 0xf0) | (dat&0x0f) // вторая партия |
0 / 0 / 0
Регистрация: 21.06.2011
Сообщений: 176
|
|
15.12.2011, 02:41 | 3 |
Сообщение от morumym
А в первом случае можно написать _lcd_dat_prt = (_lcd_dat_prt & 0xf0) | (dat & 0xf0)? Т.е. выбираем старшие полбайта порта и данных и применяем "или". А если использовать разные маски, например, в порту выбрать пять бит, а в байте данных четыре, что будет?
0
|
morumym
|
|
15.12.2011, 03:17 | 4 |
Сообщение от msmd
А в первом случае можно написать _lcd_dat_prt = (_lcd_dat_prt & 0xf0) | (dat & 0xf0)? Т.е. выбираем старшие полбайта порта и данных и применяем "или". А если использовать разные маски, например, в порту выбрать пять бит, а в байте данных четыре, что будет? 1. Нет, нельзя написать. Пусть у нас _lcd_dat_prt = aaaabbbb а dat = ccccdddd (группы по 4 бита) 0xf0 в двоичном виде 11110000 Тогда (_lcd_dat_prt & 0xf0) | (dat>>4) = (aaaabbbb & 0xf0) | (ccccdddd>>4) = (aaaa0000) | (0000cccc) = aaaacccc 4 старших бита не изменились а мы записали с 4 по 7 биты в 0-3 Ваш вариант (_lcd_dat_prt & 0xf0) | (dat & 0xf0) = (aaaabbbb & 0xf0) | (ccccdddd & 0xf0) = (aaaa0000) | (cccc0000) = xxxx0000 4 старших бита испортили, младшие всегда 0 2. Какие 5 бит? 5 бит обнулить или 5 бит не обнулять? 5 бит обнулить, маска 0xe0=0b11100000 (_lcd_dat_prt & 0xe0) | (dat>>4) = (aaaabbbb & 0xe0) | (ccccdddd>>4) = (aaa00000) | (0000cccc) = aaa0cccc - испортили (обнулили) 1 важный бит 5 бит не обнулять, маска 0xf8=0b11111000 (_lcd_dat_prt & 0xf8) | (dat>>4) = (aaaabbbb & 0xf8) | (ccccdddd>>4) = (aaaab000) | (0000cccc) = aaaaxccc - в экран уехал мусорный бит (x=b3 | c3) Если трудно с масками, пишите их в двоичном виде 0b11110000 = 0xf0 |
0 / 0 / 0
Регистрация: 21.06.2011
Сообщений: 176
|
|
15.12.2011, 10:26 | 5 |
Спасибо, что подробно расписали. Всё понял.
0
|
15.12.2011, 10:26 | |
15.12.2011, 10:26 | |
Помогаю со студенческими работами здесь
5
Битовые поля IAR ARM Битовые последовательности и битовые операции Битовые операции, битовые поля. Используя только битовые операции и операции арифметического сложения и вычитания вычислить выражение Используя только битовые операции и операции арифметического сложения и вычитания, вычислите число Битовые и арифметические операции, операции сдвига и перестановки на С++ Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |