STM32 BSRR
BSRR (Bit Set/Reset Register) — это регистр установки и сброса битов для управления выводами GPIO в микроконтроллерах STM32. Он позволяет изменять состояние определённых пинов без влияния на другие, что делает его более эффективным и удобным по сравнению с обычной записью в регистр ODR (Output Data Register).
Преимущества BSRR:
-
Позволяет установить или сбросить биты атомарно (без необходимости чтения, изменения и записи).
-
Исключает возможность возникновения "глюков" из-за прерываний при изменении состояния пинов.
-
Позволяет изменять несколько пинов одновременно, записывая одно 32-битное значение.
Как устроен BSRR?
BSRR — это 32-битный регистр, который разделен на две части:
-
Младшие 16 бит (0–15): устанавливают пины (1 → HIGH).
-
Старшие 16 бит (16–31): сбрасывают пины (1 → LOW).
Когда мы записываем 1 в младшие 16 бит, соответствующий GPIO-пин устанавливается в HIGH
.
Когда мы записываем 1 в старшие 16 бит, соответствующий GPIO-пин сбрасывается в LOW
.
Регистр BSRR состоит из двух 16-битных полей:
-
LOW (LSB) — первые 16 бит (0-15): Установка пинов (логическая "1" устанавливает пин в HIGH).
-
HIGH (MSB) — вторые 16 бит (16-31): Сброс пинов (логическая "1" сбрасывает пин в LOW).
Формат регистра:
Бит | Значение |
---|---|
0-15 | Устанавливает соответствующие биты GPIO (1 = HIGH) |
16-31 | Сбрасывает соответствующие биты GPIO (1 = LOW) |
Важно: Если записать 1
в оба поля (в один и тот же бит установки и сброса), то установка имеет приоритет.
Пример использования
Допустим, у нас есть порт GPIOA, и мы хотим:
-
Установить PA5 в HIGH.
-
Сбросить PA6 в LOW.
Используем BSRR
так:
GPIOA->BSRR = (1 << 5); // Установить PA5 в HIGH GPIOA->BSRR = (1 << 22); // Сбросить PA6 в LOW (6 + 16 = 22)
Аналогичный вариант, если нужно изменить несколько пинов одновременно:
GPIOA->BSRR = (1 << 5) | (1 << 7); // Устанавливаем PA5 и PA7 GPIOA->BSRR = (1 << (6 + 16)) | (1 << (8 + 16)); // Сбрасываем PA6 и PA8
Сравнение с обычной записью в ODR
Если бы мы использовали ODR, то это выглядело бы так:
GPIOA->ODR |= (1 << 5); // Установить PA5 в HIGH GPIOA->ODR &= ~(1 << 6); // Сбросить PA6 в LOW
Однако здесь есть проблема: если в этот момент произойдет прерывание и изменит другие биты ODR, то при GPIOA->ODR &= ~(1 << 6);
мы могли бы случайно стереть изменения.
BSRR решает эту проблему: он атомарен, и ни одно прерывание не может изменить другие биты.