再びマイクロコントローラーのC ++テンプレートについて

前書き

コントローラーのプログラミングにC ++テンプレートを使用するというアイデアは新しいものではありません。Web上には多くの資料があります。主な利点を簡単に思い出してみましょう。厳密な型制御により、エラーの大部分を実行時からコンパイル時に転送することと、オブジェクト指向のアプローチに近似することです。フィールドを静的クラスに格納します(すべてのフィールドはテンプレートパラメーターです)。ただし、ほとんどすべての作成者は、レジスターとI / Oポートを使用した例に限定して作業を行っていることに注意してください。私の記事では、これらのアイデアを継続したいと思います。





あなたは少し妊娠することはできません

オブジェクト指向プログラミングは、プログラム内に相互作用するクラスが存在することを意味します。相互作用は、一部のクラスが他のクラスに依存することで表されます。そして、ここにヘッダーの本質が現れます。静的メソッド持つテンプレートクラスBパラメーターとしてクラスAに渡すに、クラスBもテンプレートにする必要があります。以下同様にチェーン全体に沿って行われます。





たとえば、USARTは少なくともそのレジスタに依存しているため、対応するクラスの宣言は次のようになります(レジスタの宣言に関連付けられたコードは、記事の一貫性を確保するためにここから取得されます。@ lamerokのクールな資料に感謝し、例。ラッパーを渡していませんが、渡す予定です。):





template <typename _Regs>
class Usart
{
public:
  static void Init()
  {
    _Regs::CR1Pack<_Regs::CR1::UE, _Regs::CR1::RE, _Regs::CR1::TE>::Set();
    //  - .
  }
}
      
      



特定のUARTインスタンスを宣言するためにレジスターを見つけました。テンプレートを特殊化する必要があります





using Usart1 = Usart<USART1>;
      
      



すべてが素晴らしいように見えますが、実際には、特定のUSARTインターフェースには異なる依存関係があります。





  1. クロックレジスタ(RCC_APB2)。





  2. 割り込み番号。





  3. 可能なピンのセット(TxおよびRx)。





  4. Dma(TxおよびRx)。





- - , . ,





template <typename _Regs, typename _ClockCtrl>
class Usart
{
public:
  static void Init()
  {
    //       
    _ClockCtrl::Enable()
    _Regs::CR1Pack<_Regs::CR1::UE, _Regs::CR1::RE, _Regs::CR1::TE>::Set();
    ...
  }
}
      
      



. , Init / RCC_ARB2, ?





-, , . , USART






//   TX UART  SPL.
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure); //

      
      



: , , , , . :





//   Tx  Rx .
template<typename _Regs, IRQn_Type _IRQNumber, typename _ClockCtrl, typename _TxPins, typename _RxPins, typename _DmaTx, typename _DmaRx>
template<typename TxPin, typename RxPin>
void Usart<_Regs, _IRQNumber, _ClockCtrl, _TxPins, _RxPins, _DmaTx, _DmaRx>::SelectTxRxPins()
{
  const int8_t txPinIndex = TypeIndex<TxPin, _TxPins>::value;
  const int8_t rxPinIndex = !std::is_same_v<RxPin, IO::NullPin>
        ? TypeIndex<RxPin, typename _RxPins>::value
        : -1; //    ,    NullPin   
  static_assert(txPinIndex >= 0);
  //    Rx 
  static_assert(rxPinIndex >= -1);
  SelectTxRxPins<txPinIndex, rxPinIndex>();
}
      
      



USART SelectTxRxPins , , - static_assert.





, , C++ GPIO, , .





//     DS1307
template <typename _I2CBus>
class Ds1307
{
  ...
  static Time GetDateTime()
  {
    Time time;
    _I2CBus::Read(Ds1307Address, 0x00, &time, sizeof(time));
    ...
      
      



, , :





using Rtc = Ds1307<I2c1>;
      
      



, , ( neiver, - ++ easyelectronics.ru) "". github "Mcucpp", . , , , , , ( , 2019, ). , , , , , Doxy-, , . Zhele, Stm32. , , , .





" , " © ..





, , gpio, , i2c/spi/uart/one-wire, , .





, . custom- CubeIDE. , , , , , , , , , , . .





  1. - ++





  2. Pin. ++ ( CortexM)





  3. ++ ( CortexM)





  4. AVR
















All Articles