Форум РадиоКот • Просмотр темы - Настройка, кучи выводов, с быстрым переназначением,Stm32
Сообщения без ответов | Активные темы
Страница 1 из 1
[ Сообщений: 6 ]
Автор
Сообщение
pokk
Заголовок сообщения: Настройка, кучи выводов, с быстрым переназначением,Stm32
Добавлено: Пт ноя 18, 2016 06:44:03
Зарегистрирован: Вт ноя 02, 2010 17:46:37Сообщений: 574
Рейтинг сообщения: 0
Добрый день, есть 3 Usart +-1UART как сделать инициализацию этого всего с легким переназвачением выводов.
Сначала сделал все в SPL, но это все растянулось на 3 странице, и при переназначение выводов, начал путаться, что где, потом добавил define что бы все настройки были в header, но все равно не айс получилось пришлось тактирование туда вытаскивать и тд опять настроек на 3 странице, и где-то включаешь тактирование не на той шине Usart, или ремапинк теряешь.
Можно как нибудь сделать что бы все настройки были перед глазами? И не надо было листать вниз на 3 страницы.
Даже применив макросы, стало только, чуть чуть легче
http://we.easyelectronics.ru/blog/STM32/3191.html
Вернуться наверх
Реклама
Мурато Мяуконни
Заголовок сообщения: Re: Настройка, кучи выводов, с быстрым переназначением,Stm32
Добавлено: Сб ноя 19, 2016 22:27:59
Карма: -10
Рейтинг сообщений: -27
Зарегистрирован: Сб ноя 19, 2016 21:05:48Сообщений: 203
Рейтинг сообщения: 0
Да очень просто - написать на базовом CMSIS. Вам все три одновременно? Пишите всё друг за другом. Или нужен выбор одного из трех? Напишите драйвер и условной компиляцией (#define USART1 .... ifdef USART1 .... endif и #define USED_USART UASRT1), в котором в блоках ifdef ... endif будут описаны отдельные аппаратно-зависимые компиляции, определяемые конкретным значением дефайна перед использованием.
_________________Подпись убрал вместе с автором. aen
Вернуться наверх
Реклама
_kp
Заголовок сообщения: Re: Настройка, кучи выводов, с быстрым переназначением,Stm32
Добавлено: Вт фев 07, 2017 16:57:40
Зарегистрирован: Вс дек 25, 2016 16:56:37Сообщений: 6
Рейтинг сообщения: 0
С библиотекой SPL это делается примерно так.
Описываем конфигурацию 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 };
Инициализируем сразу все нужные GPIO.
Опять же, это можно вынести в функцию и передавать разные таблицы инициализации.
Код:
//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;
Вернуться наверх
Reflector
Заголовок сообщения: Re: Настройка, кучи выводов, с быстрым переназначением,Stm32
Добавлено: Вт фев 07, 2017 19:24:27
Поставщик валерьянки для Кота
Карма: 20
Рейтинг сообщений: 256
Зарегистрирован: Вс июн 19, 2016 09:32:03Сообщений: 2089
Рейтинг сообщения: 1
Код:
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();
Вернуться наверх
_kp
Заголовок сообщения: Re: Настройка, кучи выводов, с быстрым переназначением,Stm32
Добавлено: Вт фев 14, 2017 12:05:59
Зарегистрирован: Вс дек 25, 2016 16:56:37Сообщений: 6
Рейтинг сообщения: 0
Reflector, можно более полный исходник Вашего примера? Или сслылку на подобный подход.
Вернуться наверх
Реклама
Reflector
Заголовок сообщения: Re: Настройка, кучи выводов, с быстрым переназначением,Stm32
Добавлено: Вт фев 14, 2017 16:08:35
Поставщик валерьянки для Кота
Карма: 20
Рейтинг сообщений: 256
Зарегистрирован: Вс июн 19, 2016 09:32:03Сообщений: 2089
Рейтинг сообщения: 1
_kp писал(а):
Reflector, можно более полный исходник Вашего примера? Или сслылку на подобный подход.
Можно более полный(но все равно обрезанный) пример касающийся работы с портами. Он под F0/F3 и т.п., у F4 есть еще VeryHighSpeed, на F1 все совсем по-другому... И нужен компилятор С++11, у меня gcc.
Спойлер Код:
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();
Класс статический, ничего лишнего не генерится, по сути просто вызывается две функции, одна из которых инлайнится. Но это 1 пин, если хочется инициализировать порт целиком, то нужно написать другой класс, принимающий маску вместо номера пина:
Код:
GpioA<0x00FC> pa; // GpioA<0b1111'1100> pa; pa.altFunc(5);
Если заглянуть в altFunc, то внутри вызывается две функции:
Спойлер Код:
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); }
Но поскольку С++ потенциально способен генерить более эффективный код, чем С, у которого нет шаблонов и constexpr, от этого всего останется(в релизе, естественно) только:
Код:
GPIOA->AFR[0] = GPIOA->AFR[0] & ~0xFFFFFF00 | 0x55555500;
Надеюсь основная идея понятна
Вернуться наверх
Реклама
Страница 1 из 1
[ Сообщений: 6 ]
Кто сейчас на форуме
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения