Добрый день, есть 3 Usart +-1UART как сделать инициализацию этого всего с легким переназвачением выводов.
Сначала сделал все в SPL, но это все растянулось на 3 странице, и при переназначение выводов, начал путаться, что где, потом добавил define что бы все настройки были в header, но все равно не айс получилось пришлось тактирование туда вытаскивать и тд опять настроек на 3 странице, и где-то включаешь тактирование не на той шине Usart, или ремапинк теряешь.
Можно как нибудь сделать что бы все настройки были перед глазами? И не надо было листать вниз на 3 страницы.
Даже применив макросы, стало только, чуть чуть легче
http://we.easyelectronics.ru/blog/STM32/3191.html
Настройка, кучи выводов, с быстрым переназначением,Stm32
- Реклама
-
Мурато Мяуконни
- Прорезались зубы
- Сообщения: 203
- Зарегистрирован: Сб ноя 19, 2016 21:05:48
Re: Настройка, кучи выводов, с быстрым переназначением,Stm32
Да очень просто - написать на базовом CMSIS. Вам все три одновременно? Пишите всё друг за другом. Или нужен выбор одного из трех? Напишите драйвер и условной компиляцией (#define USART1 .... ifdef USART1 .... endif и #define USED_USART UASRT1), в котором в блоках ifdef ... endif будут описаны отдельные аппаратно-зависимые компиляции, определяемые конкретным значением дефайна перед использованием.
Подпись убрал вместе с автором. aen
Re: Настройка, кучи выводов, с быстрым переназначением,Stm32
С библиотекой SPL это делается примерно так.
Описываем конфигурацию GPIO в массиве (код весьма компактен )
Инициализируем сразу все нужные GPIO.
Опять же, это можно вынести в функцию и передавать разные таблицы инициализации.
Дополнительно, для работы с битами GPIO можно воспользоваться побитным доступом
После чего можно писать такой код (без всяких битовых масок)
Описываем конфигурацию GPIO в массиве (код весьма компактен )
Код: Выделить всё
typedef struct {
GPIO_TypeDef* GPIOx;
GPIO_InitTypeDef Config;
}gpio_init_t;
gpio_init_t pincfg1[]={
{ GPIOA,{ 9 , GPIO_Speed_2MHz, GPIO_Mode_AF_PP } }, //UART1.TX
{ GPIOA,{ 10 , 0 , GPIO_Mode_IN_FLOATING } }, //UART1.RX
{ GPIOA,{ 2 , GPIO_Speed_2MHz, GPIO_Mode_AF_PP } }, //LED1
{ GPIOA,{ 3 , GPIO_Speed_2MHz, GPIO_Mode_AF_PP } }, //LED2
{ GPIOC,{ 13 , GPIO_Speed_2MHz, GPIO_Mode_AF_PP } }, //LED13
{ GPIOA,{ 10 , 0 , GPIO_Mode_IPU} }, //KEY1
};
Опять же, это можно вынести в функцию и передавать разные таблицы инициализации.
Код: Выделить всё
//Enable clocking GPIO BEFORE set mode
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
unsigned size= (sizeof(GPIO_inits1) / sizeof(gpio_init_t)) ; //Число элементов в массиве
for( unsigned i=0; i< size ; i++ ){
GPIO_Init(pincfg1[i].GPIOx, &pincfg1[i].Config);
}
Дополнительно, для работы с битами GPIO можно воспользоваться побитным доступом
Код: Выделить всё
//Cortex-M* specific fastest bit access (not supported in ARM7,ARM9?)
#define DEF_GPIO_BIT(ADDR,BIT) (*((volatile uint32_t *) (32*(((uint32_t)ADDR)-PERIPH_BASE) + (4*BIT) +PERIPH_BB_BASE) ))
#define LED1 DEF_GPIO_BIT( &GPIOA->ODR, 2 )
#define LED2 DEF_GPIO_BIT( &GPIOA->IDR, 3 )
#define LED13 DEF_GPIO_BIT( &GPIOC->ODR, 12 )
#define KEY1 DEF_GPIO_BIT( &GPIOB->IDR, 15 )
#define KEY2 DEF_GPIO_BIT( &GPIOC->IDR, 14 )
После чего можно писать такой код (без всяких битовых масок)
Код: Выделить всё
LED13 =!LED13;
LED1 = KEY1;
if(!KEY2) LED2=0;
Re: Настройка, кучи выводов, с быстрым переназначением,Stm32
Код: Выделить всё
template<int usart>
class Usart
{
public:
template<class Tx, class Rx, uint32_t af_tx = 7, uint32_t af_rx = af_tx>
static void init(uint32_t baudRate)
{
Tx::mode(PinMode::AF_PushPull_HighSpeed, af_tx);
Rx::mode(PinMode::AF_PullUp, af_rx);
...
}
...
};
using Usart1 = Usart<USART1_BASE>;
using Usart2 = Usart<USART2_BASE>;
...
Код: Выделить всё
Usart1 usart1;
Usart6 usart6;
usart1.init<PinA<9>, PinA<10>>(115200);
usart6.init<PinC<6>, PinC<7>, 8>(9600);
char a = usart1.get();
Re: Настройка, кучи выводов, с быстрым переназначением,Stm32
Reflector, можно более полный исходник Вашего примера? Или сслылку на подобный подход.
- Реклама
Re: Настройка, кучи выводов, с быстрым переназначением,Stm32
Можно более полный(но все равно обрезанный) пример касающийся работы с портами. Он под F0/F3 и т.п., у F4 есть еще VeryHighSpeed, на F1 все совсем по-другому... И нужен компилятор С++11, у меня gcc._kp писал(а):Reflector, можно более полный исходник Вашего примера? Или сслылку на подобный подход.
Спойлер
Код: Выделить всё
enum class PinMode : uint32_t
{
Floating = 0x00, // PUPDR[6:5] : OTYPER[4] : OSPEEDR[3:2] : MODER[1:0]
PullUp = 0x20,
PullDown = 0x40,
Analog = 0x03,
OpenDrain_LowSpeed = 0x11,
OpenDrain_MediumSpeed = 0x15,
OpenDrain_HighSpeed = 0x1D,
OpenDrain_LowSpeed_PullUp = 0x31,
OpenDrain_MediumSpeed_PullUp = 0x35,
OpenDrain_HighSpeed_PullUp = 0x3D,
PushPull_LowSpeed = 0x01,
PushPull_MediumSpeed = 0x05,
PushPull_HighSpeed = 0x0D,
AF_Floating = 0x02,
AF_PullUp = 0x22,
AF_PullDown = 0x42,
AF_OpenDrain_LowSpeed = 0x12,
AF_OpenDrain_MediumSpeed = 0x16,
AF_OpenDrain_HighSpeed = 0x1E,
AF_OpenDrain_LowSpeed_PullUp = 0x32,
AF_OpenDrain_MediumSpeed_PullUp = 0x36,
AF_OpenDrain_HighSpeed_PullUp = 0x3E,
AF_PushPull_LowSpeed = 0x02,
AF_PushPull_MediumSpeed = 0x06,
AF_PushPull_HighSpeed = 0x0E
};
template<uint32_t gpio, uint32_t pin, uint32_t af_>
struct PinT
{
static auto base() { return (GPIO_TypeDef*)gpio; }
const static uint32_t _af = af_;
PinT() {}
PinT(PinMode mode) { init(mode); }
PinT(PinMode mode, uint32_t af) : PinT(mode) { altFunc(af); }
static void init(PinMode mode)
{
pinMode(base(), pin, mode);
}
static void init(PinMode mode, uint32_t af)
{
pinMode(base(), pin, mode);
altFunc(af);
}
static void altFunc(uint32_t af)
{
int shift = (pin & 7) * 4;
base()->AFR[pin >> 3] = base()->AFR[pin >> 3] & ~(0x0F << shift) | (af << shift);
}
static void set() { base()->BSRR = 1 << pin; }
static void clear() { base()->BSRR = 0x10000 << pin; }
static void inverse() { base()->ODR ^= (1 << pin); }
static void write(bool data) { base()->BSRR = (0x10000 << pin) | (data << pin); }
static bool read() { return base()->IDR & (1 << pin); }
private:
static void pinMode(GPIO_TypeDef* gpio_, uint32_t pin_, PinMode mode);
};
template<uint32_t gpio, uint32_t pin, uint32_t af_>
void PinT<gpio, pin, af_>::pinMode(GPIO_TypeDef* gpio_, uint32_t pin_, PinMode mode)
{
uint32_t moder = uint32_t(mode) & 3;
uint32_t ospeedr = (uint32_t(mode) >> 2) & 3;
uint32_t otyper = (uint32_t(mode) >> 4) & 1;
uint32_t pupdr = (uint32_t(mode) >> 5) & 3;
gpio_->MODER = gpio_->MODER & ~(3 << pin_ * 2) | (moder << pin_ * 2);
gpio_->OTYPER = gpio_->OTYPER & ~(1 << pin_) | (otyper << pin_);
gpio_->OSPEEDR = gpio_->OSPEEDR & ~(3 << pin_ * 2) | (ospeedr << pin_ * 2);
gpio_->PUPDR = gpio_->PUPDR & ~(3 << pin_ * 2) | (pupdr << pin_ * 2);
}
template<uint32_t pin, uint32_t af_ = 0>
using PinA = PinT<GPIOA_BASE, pin, af_>;
template<uint32_t pin, uint32_t af_ = 0>
using PinB = PinT<GPIOB_BASE, pin, af_>;
template<uint32_t pin, uint32_t af_ = 0>
using PinC = ......
Код: Выделить всё
PinA<5> led(PinMode::PushPull_HighSpeed);
led.inverse(); // или PinA<5>::inverse();
Код: Выделить всё
GpioA<0x00FC> pa; // GpioA<0b1111'1100> pa;
pa.altFunc(5);
Спойлер
Код: Выделить всё
static void altFunc(uint32_t af) __attribute__((always_inline))
{
if (pinsMask & 0x00FF) base()->AFR[0] = base()->AFR[0] & ~qmask(pinsMask) | (qmul(af) & qmask(pinsMask));
if (pinsMask & 0xFF00) base()->AFR[1] = base()->AFR[1] & ~qmask(pinsMask >> 8) | (qmul(af) & qmask(pinsMask >> 8));
}
static constexpr uint32_t qmask(uint32_t val) __attribute__((always_inline))
{
uint32_t mask = 0;
for (int i = 0; i < 8; i++)
{
mask >>= 4;
if (val & 1) mask |= 0xF0000000;
val >>= 1;
}
return mask;
}
static constexpr uint32_t qmul(uint32_t af) __attribute__((always_inline))
{
return af | (af << 4) | (af << 8) | (af << 12) | (af << 16) | (af << 20) | (af << 24) | (af << 28);
}Код: Выделить всё
GPIOA->AFR[0] = GPIOA->AFR[0] & ~0xFFFFFF00 | 0x55555500;


