Дано, скажем:
#define PIN0 (1u<<0)
#define PIN1 (1u<<1)
#define PIN2 (1u<<2)
// etc...
Затем:
char process_key(int a)
{
if( a != 0 )
{
// Set bit
GPIO_PORTC_DATA_R |= PIN0 ;
}
else
{
// Clear bit
GPIO_PORTC_DATA_R &= ~PIN0 ;
}
}
Обобщение этой идиоматической техники c представлено в Как вы устанавливаете, очищаете и переключаете один бит?
Однако чтение-изменение-запись, подразумеваемое |=
/ &=
, может быть проблематично c, если к регистру можно получить доступ в разных контекстах потока / прерывания как добавление возможно нежелательных накладных расходов. Части Cortex-M3 / 4 имеют функцию, известную как разбиение на биты, которая позволяет адресовать отдельные биты напрямую и атомарно. Дано:
volatile uint32_t* getBitBandAddress( volatile const void* address, int bit )
{
__IO uint32_t* bit_address = 0;
uint32_t addr = reinterpret_cast<uint32_t>(address);
// This bit maniplation makes the function valid for RAM
// and Peripheral bitband regions
uint32_t word_band_base = addr & 0xf0000000u;
uint32_t bit_band_base = word_band_base | 0x02000000u;
uint32_t offset = addr - word_band_base;
// Calculate bit band address
bit_address = reinterpret_cast<__IO uint32_t*>(bit_band_base + (offset * 32u) + (static_cast<uint32_t>(bit) * 4u));
return bit_address ;
}
Тогда вы можете получить:
char process_key(int a)
{
static volatile uint32_t* PC0_BB_ADDR = getBitBandAddress( &GPIO_PORTC_DATA_R, 0 ) ;
*PC0_BB_ADDR = a ;
}
Конечно, вы можете определить и жестко запрограммировать адрес битовой полосы; например:
#define PC0 (*((volatile uint32_t *)0x420C7F88u))
Тогда:
char process_key(int a)
{
PC0 = a ;
}
Подробную информацию о вычислении адреса битовой полосы можно найти Техническое справочное руководство ARM Cortex-M , а там это он-лайн калькулятор здесь .