Мигаем светодиодиком чуть по новому.

Блог им. Vasiliy_Br
Пишу статью для того, что бы самому всегда иметь к своим макросам доступ.
Сделал простые макросы для инициализации, включения, выключения, установку состояния, и переключения состояния пинов на stm32f1xx. По максимуму использованы библиотечные функции. Собственно все понятно из кода.

#include "stm32f10x_conf.h"

#define A0adg439 B,2

#define PinInit_mkr(Port,Pin) PinInit(RCC_APB2Periph_GPIO##Port, GPIO##Port, GPIO_Pin_##Pin)
#define PinInit_mkr(...) PinInit_mkr(__VA_ARGS_)

#define GPIO_SetBits_(Port,Pin) GPIO_SetBits(GPIO##Port, GPIO_Pin_##Pin)
#define GPIO_SetBits_mrk(...) GPIO_SetBits_(__VA_ARGS__)

#define GPIO_ResetBits_(Port,Pin) GPIO_ResetBits(GPIO##Port, GPIO_Pin_##Pin)
#define GPIO_ResetBits_mrk(...) GPIO_ResetBits_(__VA_ARGS__)

#define GPIO_WriteBit_(Port,Pin,State) GPIO_WriteBit(GPIO##Port, GPIO_Pin_##Pin,State)
#define GPIO_WriteBit_mrk(...) GPIO_WriteBit_(__VA_ARGS__)

#define GPIO_TogleBit_(Port,Pin) GPIO_TogleBit(GPIO##Port, GPIO_Pin_##Pin)
#define GPIO_TogleBit_mrk(...) GPIO_TogleBit_(__VA_ARGS__)

void GPIO_TogleBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin){
    if (GPIOx->ODR&GPIO_Pin){
           GPIOx->ODR &=  ~GPIO_Pin;
    }
    else GPIOx->ODR |= GPIO_Pin;
}

void PinInit (uint32_t tkt, GPIO_TypeDef* port,uint16_t pin)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
 RCC_APB2PeriphClockCmd(tkt, ENABLE);
 GPIO_InitStructure.GPIO_Pin    = pin;//leds
 GPIO_InitStructure.GPIO_Speed  = GPIO_Speed_50MHz;  //GPIO_Speed_10MHz,GPIO_Speed_2MHz,  GPIO_Speed_50MHz
 GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_Out_PP;  //GPIO_Mode_AIN, GPIO_Mode_IN_FLOATING, GPIO_Mode_IPD, GPIO_Mode_IPU
                                                     //GPIO_Mode_Out_OD, GPIO_Mode_Out_PP, GPIO_Mode_AF_OD, GPIO_Mode_AF_PP
 GPIO_Init(port, &GPIO_InitStructure);
}

int main(void)
{
    volatile int i;
  PinInit_mkr_(A0adg439);
  GPIO_SetBits_mrk(B,2);
  while(1)
  {
    for(i=0;i<400000;i++){}
    GPIO_TogleBit_mrk(A0adg439);
  }
}

4 комментария

avatar
Очень похожие макросы для кучи разных stm-ок есть у ziblog'га только их там найти нужно.
avatar
Не совсем понятно зачем делать манипуляции с ODR, которые совсем не атомарные, если специально для этого существуют BSRR и BRR
avatar
Переключение нельзя сделать атомарно, потокобезопасность нужно организовывать в другом месте. Поэтому особо не важно ODR or BSRR / BRR. Решение о состоянии бита зафиксировалось в момент считывания ODR в аргументах if. Но мне Ваше решение нравится больше, оно однозначно будет быстрее. И, кстати, нужно ввести ограничения на второй аргумент, в маске может быть установлен только один бит.
Комментарий отредактирован 2014-11-30 23:21:33 пользователем Vasiliy_Br
avatar
Вообще на практике у меня задача инвертирования бита встречается крайне редко. Всегда требуется установка в определённое состояние, но не инверсия. Но даже в случае необходимости инверсии мне кажется есть смысл использовать кеширование, менять состояние переменной в ОЗУ и выводить в порт, без чтения состояния порта. Потокобезопасность предпочитаю организовывать насколько это возможно путём выбора соответствующих решений, а не обвешивания всех подозрительных мест запретами прерываний.

HINT1: Регистр BSRR позволяет одновременно устанавливать и сбрасывать биты.

HINT2: Иногда применение Bit Banding может оказаться весьма полезным. Например, Ваше инвертирование одного бита порта через ODR делается намного безопаснее (в плане случайного изменения не тех битов при многопоточности) как раз с его помощью.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.