Обращение к контактам регистра в микроконтроллерах - PullRequest
0 голосов
/ 26 мая 2020

Я работаю над программой Keil и использую микроконтроллер LM3S316. Обычно мы адресуем регистры в микроконтроллерах в виде:

#define GPIO_PORTC_DATA_R       (*((volatile uint32_t *)0x400063FC))

Мой вопрос в том, как я могу получить доступ, например, к одному контакту регистра, если у меня есть этот метод:

char process_key(int a)
{  PC_0 = a ;}

Как можно ли получить PC_0 и как его определить?

Спасибо

1 Ответ

0 голосов
/ 26 мая 2020

Дано, скажем:

#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 , а там это он-лайн калькулятор здесь .

...