وكيف تستعملها؟
في المقالة السابقة ، أنشأنا فصلًا للعمل مع منافذ الإدخال / الإخراج ، محددًا. إذن ، ما التالي؟ لماذا كل هذا في الفصل؟
لنأخذ استطلاع زر بسيط على سبيل المثال:

بالنسبة لهذا المخطط ، في أبسط الحالات ، سيبدو المسح كما يلي:
int GetKey()
{
volatile uint32_t* addr = reinterpret_cast<uint32_t*>(GPIOA_IDR);
uint32_t ret_val = *addr;
return ret_val & 0x0F;
}
ولكن إذا قمت بتغيير المنافذ المتصلة بالأزرار الموجودة في الدائرة ، فسيتعين عليك تغيير وظيفة الاقتراع. وهكذا في كل مشروع. هذا ليس دائما مناسبا أرغب في الكتابة والاختبار والاستخدام مرة واحدة.
دعنا نعيد كتابة هذه الوظيفة ضمن الفئة التي تم إنشاؤها مسبقًا:
int GetKey(Pin* p0, Pin* p1, Pin* p2, Pin* p3)
{
int ret_val = p0->Get() + (p1->Get() << 1) + (p2->Get() << 2) + (p3->Get() << 3);
return ret_val;
}
يبقى في البرنامج الرئيسي تهيئة المنافذ وتمريرها إلى الوظيفة:
...
using namespace STM32F1xx;
Pin key0('a', 0);
Pin key1('a', 1);
Pin key2('a', 2);
Pin key3('a', 3);
...
int main()
{
key0.ModeInput();
key1.ModeInput();
key2.ModeInput();
key3.ModeInput();
int key_code = GetKey(&key0, &key1, &key2, &key3);
...
return 0;
}
أين الواجهات؟
والآن دعونا نتخيل أن وحدات التحكم من سلسلة f10x قد نفدت ، ولكن هناك مجموعة من f030s. من حيث الأداء وعدد المسامير ، يكفي ، ما عليك سوى تغيير رأس وظيفة GetKey أو استخدام ... #ifdef. قم بإنشاء ملف رأس عام ، حيث يتم استخدام نوع وحدة التحكم (شيء مثل #define STM32F030) وكومة مجموعة من التعريفات. لا ، ليس هذا هو السبب وراء إنشاء لغات عالية المستوى ليتم الخلط بينها في وحدات الماكرو!
دعنا نذهب في الاتجاه الآخر. لنقم بإنشاء فصل ندرج فيه الطرق الافتراضية التي نحتاجها في الحياة للعمل مع المنافذ:
iPin.h
#pragma once
class iPin
{
public:
virtual void ModeInput() = 0;
virtual void ModeAnalogInput() = 0;
virtual void ModeInputPulled() = 0;
virtual void ModeOutput() = 0;
virtual void ModeOutputOpenDrain() = 0;
virtual void Set(bool st) = 0;
virtual bool Get() = 0;
virtual void Reverse() { Set(!Get());}
void On() { Set(true); }
void Off() { Set(false); }
};
(يجب تحديد تلك الطرق التي تساوي 0 في الفئة المشتقة!)
وسنستخدمها كطريقة أساسية في فئة Pin:
...
#include "iPin.h"
...
class Pin : public iPin
...
ثم ستتغير وظيفة GetKey قليلاً:
int GetKey(iPin* p0, iPin* p1, iPin* p2, iPin* p3)
{
int ret_val = p0->Get() + (p1->Get() << 1) + (p2->Get() << 2) + (p3->Get() << 3);
return ret_val;
}
الآن نحن لا نهتم بأي وحدة تحكم! حتى لو كان موسع ناقل يعمل على SPI أو I2C. سننظر في الواجهات التسلسلية في المقالات التالية.
إذن ، ما التالي؟
بعد ذلك ، تحتاج إلى تصميم فصل دراسي للعمل باستخدام مؤقت النظام. لكن هذا موجود بالفعل في المنشور التالي.