реклама на сайте
подробности

 
 
> С++ Объявить вариантное перечисление., Шаблонами.
AHTOXA
сообщение Jul 1 2013, 10:49
Сообщение #1


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Есть у меня файл, типа spi.h, в нём - перечисление всех имеющихся SPI:
Код
enum SpiNum {
    SPI_1,
#if (SPI_COUNT>1)
    SPI_2,
#elif (SPI_COUNT>2)
    SPI_3
#endif
};

Захотелось мне избавиться от дефайнов, и переделать это на шаблоны.
Делаю так:
Код
template<int SPI_Count> struct SpiEnumTraits;
template<> struct SpiEnumTraits<1> { enum SpiNum { SPI_1 }; };
template<> struct SpiEnumTraits<2> { enum SpiNum { SPI_1, SPI_2 }; };
template<> struct SpiEnumTraits<3> { enum SpiNum { SPI_1, SPI_2, SPI_3 }; };
template<> struct SpiEnumTraits<4> { enum SpiNum { SPI_1, SPI_2, SPI_3, SPI_4 }; };

typedef typename SpiEnumTraits<chip::spi_count>::SpiNum SpiNum;

На саму эту конструкцию компилятор не ругается, а вот на любые упоминания в тексте программы элементов перечисления (SPI_1 и т. д.) - ругается, мол, символ неопределён. Видимо, я что-то делаю неправильно, но вот что?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Tahoe
сообщение Jul 5 2013, 19:29
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата(AHTOXA @ Jul 1 2013, 14:49) *
Код
enum SpiNum {
    SPI_1,
#if (SPI_COUNT>1)
    SPI_2,
#elif (SPI_COUNT>2)
    SPI_3
#endif
};

Как-то сама идея выглядит не очень. А если в контроллере есть SPI1 и SPI3, но отсутствует SPI2?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Apr 11 2015, 07:25
Сообщение #3


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Недавно вернулся к этой теме, но немного по другому поводу.
Повод такой: бывает так, что, в зависимости от номера периферийного модуля, он может иметь разные свойства.
Например, каждый канал DMA на STM32L0xx может быть подключен только к определённому перечню периферийных устройств.
(Канал 1 может быть подключен к ADC, TIM2_CH3 и AES_IN, канал 2 - к SPI2_RX, USART2_RX, LPUART1_RX и I2C1_TX. И так далее).
Хотелось иметь у каждого канала функцию SelectChannel(), которая бы принимала в качестве аргумента только допустимые для данного канала значения.
И я решил посмотреть, не поможет ли тут C++11. Вот что получилось.

Объявляем шаблонный класс свойств канала:
Код
template<DmaChannelNum chNum> struct DmaChannelTraits;


Определяем свойства для каждого канала:
Код
template<> struct DmaChannelTraits<DMA1_CH1>
{
    enum { CHANNEL_NO = 1 };
    enum { CSELR_SHIFT = (CHANNEL_NO-1)*4 };
    enum class ChannelSelection : uint32_t  // possible CSELR values
    {
        CH_SEL_ADC             = (0x00 << CSELR_SHIFT),
        CH_SEL_TIM2_CH3        = (0x08 << CSELR_SHIFT),
        CH_SEL_AES_IN          = (0x0B << CSELR_SHIFT),
        CH_SEL_MASK            = (0x0F << CSELR_SHIFT),
    };
};


И так для всех каналов:
Код
template<> struct DmaChannelTraits<DMA1_CH6>
{
    enum { CHANNEL_NO = 1 };
    enum { CSELR_SHIFT = (CHANNEL_NO-1)*4 };
    enum class ChannelSelection : uint32_t  // possible CSELR values
    {
        CH_SEL_SPI2_RX         = (0x02 << CSELR_SHIFT),
        CH_SEL_USART2_RX       = (0x04 << CSELR_SHIFT),
        CH_SEL_LPUART1_RX      = (0x05 << CSELR_SHIFT),
        CH_SEL_I2C1_TX         = (0x06 << CSELR_SHIFT),
        CH_SEL_MASK            = (0x0F << CSELR_SHIFT),
    };
};


И затем, уже в шаблоне канала:
Код
template<DmaChannelNum chNum>
class DmaChannel
{
private:
    typedef DmaChannelTraits<chNum> ChannelTraits;
public:
    using ChannelSelection = typename ChannelTraits::ChannelSelection;
    static void SelectChannel(ChannelSelection cs)
    {
        DMA->CSELR =
                (DMA->CSELR & ~static_cast<uint32_t>(ChannelSelection::CH_SEL_MASK))
                | static_cast<uint32_t>(cs);
    }
}


Теперь, если мы попробуем выбрать для канала неверный источник:

Код
typedef DmaChannel<DMA1_CH1> Dma1Channel1;
Dma1Channel1::SelectChannel(Dma1Channel1::ChannelSelection::CH_SEL_SPI2_RX);

,то получим ошибку времени компиляции.
Кроме того, парсер эклипсы настолько умён, что в автоподстановке показывает правильные возможные значения для параметра.

ЗЫ. Результат целиком можно посмотреть здесь.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Apr 30 2015, 10:33
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Цитата(AHTOXA @ Apr 11 2015, 10:25) *
Недавно вернулся к этой теме, но немного по другому поводу.
ЗЫ. Результат целиком можно посмотреть здесь.

Во-первых, спасибо. Получилось довольно аккуратно, микро-классы для пинов - вообще отличные.

А во-вторых, как всем этим пользоваться?

Код
namespace STM32 {
namespace SPI {

struct SpiProps
{
    static const SpiNum   NUMBER           = SPI_1;
    static const Remap    REMAP            = REMAP_NONE;
    static const Divisor  InitialDivisor   = SPI_DIV_2;
    static const Cpol     InitialCPOL      = CPOL_L;
    static const Cpha     InitialCPHA      = CPHA_1;
};
}
}

STM32::SPI::Spi<STM32::SPI::SpiProps>        MySPI;

Работает, но выглядит некрасиво. Сделать using namespace не получилось - почему-то из области видимости пропадают enum'ы.


Цитата(AHTOXA @ Apr 11 2015, 10:25) *
Кроме того, парсер эклипсы настолько умён, что в автоподстановке показывает правильные возможные значения для параметра.

Это тоже не работает, даже в вышеприведённом варианте - предлагает всё подряд. Где-то есть галка?


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- AHTOXA   С++ Объявить вариантное перечисление.   Jul 1 2013, 10:49
- - neiver   Если строчка: typedef typename SpiEnumTraits<ch...   Jul 1 2013, 17:40
|- - AHTOXA   Это я уже от безысходности добавил. И без typename...   Jul 1 2013, 18:50
- - XVR   Цитата(AHTOXA @ Jul 1 2013, 14:49) Делаю ...   Jul 2 2013, 08:29
|- - AHTOXA   Так я тоже пробовал, и это тоже не работает: Кодif...   Jul 2 2013, 08:49
|- - XVR   Цитата(AHTOXA @ Jul 2 2013, 12:49) Так я ...   Jul 2 2013, 08:51
|- - AHTOXA   А, пардон, я невнимательно прочитал. Да, так работ...   Jul 2 2013, 09:10
|- - AHTOXA   Цитата(esaulenka @ Apr 30 2015, 15:33) Во...   Apr 30 2015, 11:08
- - Сергей Борщ   Интересно, взял на заметку.   Apr 11 2015, 08:08
- - shreck   ОФФ. А мне вот интересно, IAR будет воплощать у се...   Apr 20 2015, 10:16
- - esaulenka   Это некорректный пример, так у меня тоже работает ...   Apr 30 2015, 12:54
|- - AHTOXA   Цитата(esaulenka @ Apr 30 2015, 17:54) Эт...   Apr 30 2015, 20:01
- - esaulenka   С автодополнением я понял, почему у меня не работа...   May 7 2015, 12:58
|- - AHTOXA   Цитата(esaulenka @ May 7 2015, 17:58) Что...   May 7 2015, 18:39
- - esaulenka   О, спасибо большое. Хватило одной __cxa_pure_virtu...   May 8 2015, 06:47


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 02:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.0141 секунд с 7
ELECTRONIX ©2004-2016