Рейтинг: 5 / 5

Звезда активнаЗвезда активнаЗвезда активнаЗвезда активнаЗвезда активна
 

Технология bit-band в Cortex-M3 — это выделение некоторой области памяти, которая служит для побитового доступа к регистрам. Эта технология позволяет напрямую управлять состоянием портов ввода-вывода, что облегчает имплементацию последовательных интерфейсов.

В плате STM32 Value line discovery(процессор SM32F100RBT6B)имеется два светодиода: зелёного и синего цветов.
На PC9зелёный и на PC8 - синий.

Обычным путём установка бита на PC9 происходит следующим образом:

GPIOC->ODR|=GPIO_ODR_ODR9; //set

Снятие:
GPIOC->ODR&=~GPIO_ODR_ODR9; //reset

Или

GPIOC->BSRR=GPIO_BSRR_BS9; // set
GPIOC->BSRR=GPIO_BSRR_BR9; // reset

Аналогично для  PC8.

Приступим. Пишу относительно IAR, статья же актуальна для любого компилятора. Будем управлять регистром ODR PC9 и PC8.

В файле stm32f10x.h находим:

Базовый адрес периферии:

#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */

Начало памяти соответствующего ему блока памяти для bit-band'a:

#define PERIPH_BB_BASE ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */

Далее, смотрим адрес интересующего нас порта:

#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)

При этом:

#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)

 

Т.е. 0X40000000 + 0x10000 + 0x1000 = 0x40011000;

GPIOC_BASE эквивалентно ((uint32_t)0x40011000)

Далее, регистровая структура порта:

#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)

typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
} GPIO_TypeDef;

Таким образом, адреса слов будут (4 байта 410 = 0x416):

0x40011000 + 0 = 0x40011000; //GPIOC-> CRL
0x40011000 + 0x4 = 0x40011004; //GPIOC-> CRH
0x40011000 + 0x8 = 0x40011008; //GPIOC-> IDR
0x40011000 + 0xС = 0x4001100С; //GPIOC-> ODR
0x40011000 + 0x10 = 0x40011010; //GPIOC-> BSRR
0x40011000 + 0x14= 0x40011014; //GPIOC-> BRR
0x40011000 + 0x18 = 0x40011018; //GPIOC-> LCKR

Смещение слова GPIOC-> ODR от базового слова периферии равно:

0x4001100С- 0x40000000 = 0x110

 

К тому же, эти все манипуляции можно было обойти с помощью Си:

unsigned long AddressReg;

далее:

AddressReg = (unsigned long)&(GPIOC->ODR);

Прочитав в watch переменную получим то же:

Watch

Рисунок 1 Watch window

Номера битов 8 и 9 соответственно.

 

Приступим к вычислениям.

Согласно http://easyelectronics.ru/img/ARM_kurs/CMSIS/stm32.pdf формула для вычисления будет:

 

Адрес в области псевдоимен = Начальный адрес области псавдоимен + смещение слова

Смещение слова = Смещение в байтах от начала битовых сегментов * 0x20 + номер в битаx * 4 

Таким образом:

Нужный адрес для PC8:

0x42000000 + 0x110 * 0x20 + 8* 0x4 = 0x42000000 + 0x220180 + 0x20 = 0x422201A0

 

Напишем определение:

#define PC8B (*((volatile unsigned long *) 0x422201A0 ))

P/S не называйте PC8 – слово зарезервировано, работать не будет!

Для PC9:

0x42000000 + 0x220180+ 9* 0x4 = 0x422201A4

#define PC9B (*((volatile unsigned long *) 0x422201A4 ))

 

Теперь устанавливать лог. уровни на ножках можно лаконичными выражениями, без битовых масок.

PC8B=1; // логическая единица на PC8

PC8B=0; // логический ноль на PC8

PC9B=1; // логическая единица на PC9

PC9B=0; // логический ноль на PC9

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

Аналогичным способом можно определить указатели для линий других портов ввода-вывода.

Теперь перенос кода будет несколько легче.

P/S
Аналогично:

#define PA1_IN (*((volatile unsigned long *) 0x42210104)) //bit-band of PA1 as input
#define PA10_IN (*((volatile unsigned long *) 0x4221012C)) //bit-band of PA10 as input
#define PB4_IN (*((volatile unsigned long *) 0x42218110)) //bit-band of PB4 as input 
#define PC14_IN (*((volatile unsigned long *) 0x42220138)) //bit-band of PC14 Input

Немного упростить жизнь поможет калькулятор:
http://www.efton.sk/STM32/bitbandcalc.html

Удачных применений!
А ещё хорошая статья на английском тут:
http://www.scienceprog.com/bit-band-operations-with-arm-cortex-microcontrollers/
Из неё следует (как ессенция), что удобно, особенно при многочисленных применения использовать макросы препроцессора, например

#define PERIPHERAL_BASE 0x40000000

#define BITBAND_PERIPHERAL_BASE 0x42000000
#define BITBAND_PERIPHERAL(a,b) (BITBAND_PERIPHERAL_BASE + (a-PERIPHERAL_BASE)*0x20+(b*4))
//port D output register address
#define GPIOD_ODR 0x4001140C
//create a pointer to bit 5 in bit band location
#define PORTDBIT5 (*((volatile unsigned long *)(BITBAND_PERIPHERAL(GPIOD_ODR,5))))
//use it somewhere to set bit to 1
int main()
{
//...
PORTDBIT5 = 1;

}

Не знаем как Вы, но мы не выдержали и запилили СВОЙ калькулятор:ПОГЛЯДЕТЬ

При использовании материалов сайта ссылка на данный источник обязательна.