pengantar
Ide menggunakan template C ++ untuk pengontrol pemrograman bukanlah hal baru; ada banyak materi yang tersedia di web. Izinkan saya mengingat secara singkat keuntungan utama: mentransfer sebagian besar kesalahan dari runtime ke waktu kompilasi karena kontrol tipe yang ketat, serta pendekatan ke pendekatan berorientasi objek, yang dekat dan nyaman bagi banyak orang, tanpa perlu menyimpan bidang dalam kelas statis (semua bidang adalah parameter template). Namun, perlu dicatat bahwa hampir semua penulis pada umumnya membatasi diri mereka dalam pekerjaan mereka pada contoh-contoh bekerja dengan register dan port I / O. Dalam artikel saya, saya ingin melanjutkan ide-ide ini.
Anda tidak bisa hamil kecil
Pemrograman berorientasi objek menyiratkan keberadaan kelas dalam program yang berinteraksi satu sama lain. Interaksi diekspresikan oleh ketergantungan beberapa kelas pada kelas lainnya. Dan di sini esensi dari header muncul: untuk melewatkan template kelas B dengan metode statis ke kelas A sebagai parameter , maka kelas B juga harus dibuat template, dan seterusnya sepanjang seluruh rantai.
Misalnya, USART setidaknya bergantung pada registernya, maka deklarasi kelas yang sesuai akan terlihat seperti ini (kode yang terkait dengan deklarasi register diambil dari sini untuk memastikan konsistensi artikel, terima kasih @lamerok untuk bahannya yang keren dan contoh. Saya belum memberikan bungkusnya, tetapi saya berencana untuk.):
template <typename _Regs>
class Usart
{
public:
static void Init()
{
_Regs::CR1Pack<_Regs::CR1::UE, _Regs::CR1::RE, _Regs::CR1::TE>::Set();
// - .
}
}
Kami menemukan register untuk mendeklarasikan instance UART tertentu, Anda perlu mengkhususkan templatnya
using Usart1 = Usart<USART1>;
Semuanya tampak bagus, tetapi kenyataannya, antarmuka USART tertentu memiliki dependensi yang berbeda:
Register jam (RCC_APB2).
Interupsi nomor.
Satu set pin yang mungkin (Tx dan Rx).
Dma (Tx dan 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. , , , , , , , , , , . .