Теория: Битовые операции и управление выводами через регистры.

usr-bin
Offline
Зарегистрирован: 04.09.2012

Как применяются битовые операции в arduino?

Читал статью "Прямое управления выходами через регистры микроконтроллера Atmega". Там применяются битовые операции. Встречал там и тут примеры разных операций, но не могу найти как сделать "НЕ" для нужных регистров.

Может быть кто-то подскажет, где посмотреть толковую инструкцию на русском языке?

usr-bin
Offline
Зарегистрирован: 04.09.2012

для всей группы нашел: PORTB = ~PORTB;
ищу как сделать для отдельных контактов.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Cyberlib Library

Для 328   http://thechronosproject.com/?ddownload=1579

Там всё это уже есть

maksim
Offline
Зарегистрирован: 12.02.2012

http://arduino.cc/en/Reference/BitwiseXorNot

usr-bin пишет:
ищу как сделать для отдельных контактов.

PORTB ^= 1<<PB5;

usr-bin
Offline
Зарегистрирован: 04.09.2012

Пасиба.
Почему-то когда я задаю вопрос на форуме, я сразу же нахожу путь решения. Наверное это связано со свойствами ноосферы.

Я тоже надумал операцию XOR
что-то вроде этого: PORTB = PORTB ^ B00001000;

trembo, благодарю за библиотеку, изучу,
maksim, благодарю за наводку.

ites
Offline
Зарегистрирован: 26.12.2013

usr-bin пишет:
для всей группы нашел: PORTB = ~PORTB; ищу как сделать для отдельных контактов.

Вот мой вариант. Надо добавить в начало скетча или в какой-либо .h-файл, который затем подключать через #include "ports_fast.h"

#define portWrite(set,mask,port) do {\
		byte state = port;\
		state &= ~mask;\
		state |= set;\
		port = state;\
	} while(0)
#define _digitalWriteFast(P, V) \
	do {\
		if((P) < 8)\
			portWrite((V) << (P),_BV(P), PORTD);\
		else if((P) < 14)\
			portWrite((V) << ((P)-8),_BV((P)-8), PORTB);\
		else\
			portWrite((V) << ((P)-14),_BV((P)-14), PORTC);\
	} while(0)
#define portRead(bit,pin,ret) do {\
		ret = pin;\
		ret >>= bit;\
		ret &= 1;\
	} while(0)

#define _digitalReadFast(P, ret) do {\
	if((P) < 8)\
		portRead((P), PIND, ret);\
	else if((P) < 14)\
		portRead((P)-8, PINB, ret);\
	else\
		portRead((P)-14, PINC, ret);\
	} while(0)

static inline byte digitalReadFast(byte pin) {
	byte ret;
	_digitalReadFast(pin, ret);
	return ret;
}

static inline void digitalWriteFast(byte pin, byte value) {
	_digitalWriteFast(pin, value);
}

 

usr-bin
Offline
Зарегистрирован: 04.09.2012

строчки с побитовым сдвигом мне пока не понятны.

Если кто-то наткнется на тему в поисках ответов на подобные вопросы, укажу источники (рус), которыми сам пользуюсь:
http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry
http://makesystem.net/?p=896
http://fanatnauki.ru/index.php?option=com_content&view=article&id=49&Ite...
http://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_...
http://kolonitsky.org/blog/2011/05/bitmask-into/

ites
Offline
Зарегистрирован: 26.12.2013

usr-bin пишет:
строчки с побитовым сдвигом мне пока не понятны.

Что ж там непонятного? Простая арифметика школьный курс. Следующие записи эквивалентны:

byte a, b;

a = b + b;

 

a = b * 2;

 

a = b << 1;

 

a = b;
a <<= 1;

 

usr-bin
Offline
Зарегистрирован: 04.09.2012

ites пишет:

usr-bin пишет:
строчки с побитовым сдвигом мне пока не понятны.

a = b << 1;


a = b;
a <<= 1;

ну не понятно. что за знак "<<" ? Что он делает?

maksim
Offline
Зарегистрирован: 12.02.2012
gena
Offline
Зарегистрирован: 04.11.2012

  Как на языке Си записать более элегантно (специфично) аналог такой последовательности команд:

  R20 = DDRB;          //R20 не  обязателен, взят для примера
  R20.b2=0;
  R20.b1=1;
  DDRB =R20;
 
Т.е. нужно одномоментно изменить в регистре ввода/вывода биты - одни установить, другие сбросить, при этом не изменить остальные, не задействованные биты.
Arhat109-2
Offline
Зарегистрирован: 24.09.2015
{
  uint8_t _tmpReg = DDRB;
  _tmpReg |= maskSet;
  _tmpReg &= ~maskClr;
  DDRB = _tmpReg;
}

Одной командой нельзя И установить И сбросить биты. Ни в С, ни в Асм. Двумя - пожалуйста.

gena
Offline
Зарегистрирован: 04.11.2012

   Спасибо за отклик. Пока занимался другими делами , придумал такое:

  R16 = DDRB | ((1<< DDB3)|(1<<DDB2));                 // установка нужных разрядов
  DDRB = R16 &  ~((1 << DDB1)|(1 << DDB0));         // сброс нужных разрядов
 
  Что на ассемблере дало такое:
 
;Ftact.c,39 :: R16 = DDRB | ((1<< DDB3)|(1<<DDB2));
                      IN         R16, DDRB+0
                     ORI        R16, 12
;Ftact.c,40 :: DDRB = R16 & ~((1 << DDB1)|(1 << DDB0));
                     ANDI       R16, 252
                     OUT        DDRB+0, R16
 
чего собственно я и добивался от компиллятора.
Мне такие конструкции как то информативнее, особенно когда придётся работать с таймером в МК.