Jump to content

    
Sign in to follow this  
Dx!

Последовательность действий - побитовая инверсия и сдвиг

Recommended Posts

Компилятор WinAVR-20090313

 

Неужели ((~PIND) >> 4) и (~(PIND >> 4)) должны давать одинаковый результат?

 

PIND у меня равен 0b1110????

 

~(PIND >> 4) получается 0b11110001 как и должно быть.

 

(~PIND) >> 4 получается тоже 0b11110001, хотя мне кажется должно быть 0b00000001

 

Я ошибаюсь?

Share this post


Link to post
Share on other sites
PIND у меня равен 0b1110????

 

(~PIND) >> 4 получается тоже 0b11110001, хотя мне кажется должно быть 0b00000001

PIND равен 00001110. После инвертирования получится 11110001. А если учесть, что компилятор в выражениях расширяет операнды до int, то единиц будет еще больше. Ну и сдвиг на 4 с расширением знака даст все единицы, причем в обоих случаях. Как у тебя получилось что-то другое - хз

 

Share this post


Link to post
Share on other sites

Под ???? подразумевались недостающие четыре бита?

Share this post


Link to post
Share on other sites

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

Remark[Pa091]: operator operates on value promoted to int (with possibly unexpected result)

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

Share this post


Link to post
Share on other sites
Как определён Ваш PIND?

Он не мой - это регистр ввода с порта.

 

PIND равен 00001110. После инвертирования получится 11110001. А если учесть, что компилятор в выражениях расширяет операнды до int, то единиц будет еще больше. Ну и сдвиг на 4 с расширением знака даст все единицы, причем в обоих случаях. Как у тебя получилось что-то другое - хз

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

 

temp = PIND;
temp = ~temp;
SomeVar = temp >> 4;

Работает адекватно.

 

Под ???? подразумевались недостающие четыре бита?

Любые биты, в данном случае не имеющие значения и ничего не меняющие.

 

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

 

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

И что мне это даст?

Гораздо проще

((~PIND) >> 4) & 0xf;

Но вопрос в другом - мне казалось что сначала должна была быть инверсия, потом сдвиг. Я не прав? Или данная конструкция что-то нарушает и не может быть применена?

Share this post


Link to post
Share on other sites
И что мне это даст?

Гораздо проще

((~PIND) >> 4) & 0xf;

У вас то же самое, что я предлагаю, но по-моему более корректно будет

(((~PIND)&0xFF)>>4)

Но вопрос в другом - мне казалось что сначала должна была быть инверсия, потом сдвиг. Я не прав? Или данная конструкция что-то нарушает и не может быть применена?
Все правильно, инверсия, а потом сдвиг. Только перед инверсией беззнаковая переменная типа volatile unsigned char преобразуется в переменную типа signed int и только потом инвертируется и сдвигается сообразно правилам сдвига для знаковой переменной. Если вы хотите работать именно с байтовой переменной, то пишите

((PIND^0xFF) >> 4)

Share this post


Link to post
Share on other sites
Компилятор WinAVR-20090313

 

Неужели ((~PIND) >> 4) и (~(PIND >> 4)) должны давать одинаковый результат?

 

PIND у меня равен 0b1110????

 

~(PIND >> 4) получается 0b11110001 как и должно быть.

 

(~PIND) >> 4 получается тоже 0b11110001, хотя мне кажется должно быть 0b00000001

 

Я ошибаюсь?

Разбираем по шагам:

PIND = 0b1110**** (PIND это 8 битное число)

результат инвертирования (почему смотри ниже) будет иметь тип int (в avr-gcc тип int это знаковое 16 битное число). поэтому 8 битное беззнаковое число будет расширено до знакового 16 битного

~PIND == ~(0b00000000 1110****) == 0b11111111 0001***

(~PIND) >> 4 с правой стороны этого выражения числовая константа (без явного указания типа), а по стандарту си она должна интерпретироваться как тип int. При операции сдвига меньший операнд по стандарту си должен быть расширен до бОльшего (именно по этой причине компилятор делал инвертирование в 16 битах). т.е. имеем: (~PIND) >> 4 == 0b11111111 0001**** >> 4 == 0b11111111 11110001

итого, если результат приводится к 8ми битному типу то должно получиться 0b11110001.

Если это не так, то надо более точно разбираться.

Share this post


Link to post
Share on other sites
Если это не так, то надо более точно разбираться.

Вот я и пытаюсь добиться определения PIND в WinAVR ибо "Он не мой - это регистр ввода с порта." это не определение на языке C. Отсюда и плясать надо.

Share this post


Link to post
Share on other sites
Вот я и пытаюсь добиться определения PIND в WinAVR ибо "Он не мой - это регистр ввода с порта." это не определение на языке C. Отсюда и плясать надо.

#define PIND    _SFR_IO8(0x09)

Share this post


Link to post
Share on other sites

Да, всё так, большое спасибо. Теперь всё встало на свои места, всё понятно. Прошу прощения за причинённые неудобства 8)

Share this post


Link to post
Share on other sites
#define PIND    _SFR_IO8(0x09)

Если совсем правильно, то

(*(volatile uint8_t *)(mem_addr))

где mem_addr это адрес порта D

таким образом PIND это uint8_t т.е. ровно 8 битное беззнаковое число.

Share this post


Link to post
Share on other sites

Просто мы же в разделе AVR, мне казалось что особо указывать что есть PIND не нужно. Хотя (*(volatile uint8_t *)(mem_addr)) я не нашёл - оно где?

Share this post


Link to post
Share on other sites
Просто мы же в разделе AVR, мне казалось что особо указывать что есть PIND не нужно. Хотя (*(volatile uint8_t *)(mem_addr)) я не нашёл - оно где?

include/avr/sfr_defs.h

Share this post


Link to post
Share on other sites

Не прошло и полгода!

И хоть после драки кулаками не машут, но на будущее. Не у всех установлен WinAVR, а получить результирующий ответ можно было уже после ответа на второй пост.

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this