في برنامجنا التعليمي السابق ، تعلمنا عن وميض LED باستخدام متحكم PIC وقمنا ببناء نفس الدائرة على لوحة Perf. ثم استخدمنا PICkit 3 و ICSP و MPLAB IPE لإلقاء البرنامج على لوحة الأداء الخاصة بنا. الآن ، في هذا البرنامج التعليمي ، سوف نطور أنفسنا لاستخدام المزيد من الدبابيس في الميكروكونترولر PIC. سوف نستخدم 7 مخرجات (LED) ومدخل واحد. في هذا البرنامج التعليمي ، سنستخدم لوحة Perf القديمة (كما هو موضح أدناه) وسنضيف عصي berg لسحب المسامير المطلوبة على لوحة LED الثانية. في نهاية هذا البرنامج التعليمي ، سنقوم بإنشاء تسلسل لمصابيح LED الوامضة باستخدام متحكم PIC PIC16F877A وسنتعلم كيفية استخدام مدخلات ومخرجات متعددة ، وبعض الأساسيات على استدعاء الحلقة والوظيفة.
لوحة LED ليست سوى لوحة أداء أخرى ، حيث سنلحم مصابيح LED بمقاوم محدد حالي (كما هو موضح أدناه). سنضيف أيضًا زر ضغط لبدء وميض LED المتسلسل.
مخطط الرسم البياني:
متحكم PIC PIC16F877A LED رمز تسلسل وامض وشرح العمل:
تم إعطاء الرمز الكامل أدناه (تحقق في النهاية) ، هنا سنحصل عليه من خلال سطر بسطر. سيبدأ هذا الرمز في توهج مصابيح LED بطريقة متسلسلة عند الضغط على زر الضغط. لفهم التسلسل يرجى مشاهدة الفيديو في نهاية البرنامج التعليمي. أوصيك بمقارنة الإخراج الموضح في الفيديو مع الكود أدناه ومحاولة فهم البرنامج.
لنلق نظرة على الكود سطرًا بسطر. الأسطر القليلة الأولى مخصصة لإعداد بتات التكوين التي تم شرحها في البرنامج التعليمي السابق لذا فأنا أتخطىها الآن. أفضل طريقة لفهم أي برنامج هي البدء من الوظيفة الرئيسية ( void main () ) ، لذلك دعونا نفعل ذلك
TRISB0 = 1 ؛ // إرشاد MCU إلى استخدام PORTB pin 0 كمدخل للزر. TRISD = 0x00 ؛ // إرشاد MCU إلى أن جميع المسامير هي إخراج PORTD = 0x00 ؛ // تهيئة جميع المسامير على 0
يتم استخدام كلمة TRIS لتحديد ما إذا كان يتم استخدام الدبوس كمدخل / إخراج أم لا ، ويتم استخدام كلمة PORT لإنشاء دبوس مرتفع / منخفض. سيجعل الخط TRISB0 = 1 السن 0 من المنفذ B كمدخل. سيكون هذا هو زر الضغط لدينا. الخطوط TRISD = 0x00 ؛ PORTD = 0x00 ؛ ستجعل جميع دبابيس المنفذ D كإخراج وتعيين قيمة أولية منخفضة لتلك المسامير.
نظرًا لأننا قلنا أنه يتم استخدام B0 كمدخل ، سنقوم بتوصيل أحد طرفي زر الضغط بالدبوس B0 والطرف الآخر بالأرض. بحلول ذلك الوقت ، عندما نضغط على الزر ، سيتم تثبيت الدبوس على الأرض كما هو موضح في مخطط الاتصال أعلاه. ولكن لتحقيق ذلك ، يتعين علينا استخدام مقاومة سحب بحيث يتم تعليق الدبوس عالياً عند عدم الضغط على الزر. مقاومة سحب شيء من هذا القبيل.
لكن PIC MCU الخاص بنا يحتوي على مقاوم سحب داخلي ضعيف يمكن تنشيطه بواسطة البرنامج بهذه الطريقة مما يوفر الكثير من المتاعب (عندما يتم توصيل المزيد من الأزرار).
ما هو مقاومة السحب الضعيفة؟
هناك نوعان من مقاومة السحب ، أحدهما هو السحب الضعيف والآخر هو السحب القوي. تعتبر مقاومات السحب الضعيفة ذات قيمة عالية وبالتالي تسمح لتيار ضعيف بالتدفق من خلاله وتكون مقاومات السحب القوية ذات قيمة منخفضة مما يسمح بتدفق تيار قوي. تستخدم جميع MCU في الغالب مقاومات سحب ضعيفة. لتفعيل هذا في PIC MCU الخاص بنا ، يتعين علينا النظر في ورقة البيانات الخاصة بنا لـ OPTION_REG (تسجيل الخيار) كما هو موضح في اللقطة أدناه.
كما هو موضح ، فإن البت 7 يتعامل مع المقاوم سحب ضعيف. يجب أن يكون صفرًا لتنشيطه. يتم ذلك عن طريق OPTION_REG <7> = 0 . يتعامل هذا تحديدًا مع البت 7 مع ترك البتات الأخرى لقيمها الافتراضية. مع هذا ندخل في حلقة while الخاصة بنا ، حيث تتحقق مما إذا كان الزر مضغوطًا باستخدام if (RB0 == 0). إذا تم استيفاء الشرط ، نسمي وظيفتنا بالمعلمات 1 و 3 و 7 و 15.
سبلينك (1) ؛ // FUNCTION CALL 1 مع المعلمة 1 sblink (3) ؛ // FUNCTION CALL 3 مع المعلمة 3 sblink (7) ؛ // FUNCTION CALL 7 مع المعلمة 7 sblink (15) ؛ // FUNCTION CALL 4 مع المعلمة 15
لماذا نستخدم الوظائف؟
تستخدم الوظائف لتقليل عدد الأسطر في الكود الخاص بنا. هذا ما كان سيعرفه معظمنا. لكن لماذا نحتاج إلى تقليل عدد الأسطر ، خاصة عندما يتعلق الأمر ببرمجة MCU. و السبب هو مساحة محدودة في الذاكرة برنامجنا. إذا لم نحسن الشفرة بشكل صحيح ، فقد تنفد مساحة الذاكرة. سيكون هذا مفيدًا عندما نكتب صفحات طويلة من الرموز.
أي وظيفة سيكون لها تعريف وظيفة ( sblink (int get) في حالتنا) ودالة استدعاء ( sblink (1) في حالتنا). من الاختياري أن يكون لديك إعلان عن الوظيفة ، لتجنب ذلك ، قمت بوضع تعريف الوظيفة الخاص بي قبل استدعاء الوظيفة في وظيفتي الرئيسية.
معلمات الوظيفة هي القيمة التي سيتم تمريرها من استدعاء الوظيفة إلى تعريف الوظيفة. في حالتنا ، فإن قيم الأعداد الصحيحة (1 ، 3 ، 7 ، 15) هي المعلمات التي يتم تمريرها من استدعاء الدالة والمتغير "get" يحصل على قيمة المعلمات في تعريف الدالة لمعالجتها. يمكن أن تحتوي الوظيفة على أكثر من معلمة.
بمجرد استدعاء الوظيفة ، سيتم تنفيذ الأسطر أدناه في تعريف الوظيفة.
لـ (int i = 0؛ i <= 7 && RB0 == 0؛ i ++) {PORTD = get << i؛ // تسلسل نقل LED الأيسر __delay_ms (50) ؛ } لـ (int i = 7؛ i> = 0 && RB0 == 0؛ i--) {PORTD = get << i؛ // تسلسل نقل LED الأيسر __delay_ms (50) ؛ }
الآن يبدو أن هذا السطر غريب: PORTD = get << i . سأشرح ما يحدث بالفعل هنا.
"<<" هو عامل إزاحة لليسار ينقل كل وحدات البت إلى موضعها الأيسر. الآن عندما نطلق على دالة sblink (int get) مع المعلمة '1' مثل sblink (1) ، فإنها ستجعل قيمة 'get' كـ 1 ، والتي في النظام الثنائي هي 0b00000001. ومن ثم سيكون هذا الخط مثل PORTD = 0b00000001 << i .
ستختلف قيمة "i" من 0 إلى 7 نظرًا لأننا استخدمنا "for loop" لـ (int i = 0 ؛ i <= 7 && RB0 == 0 ؛ i ++). قيمة "أنا" من 0 إلى 7 ستغير النتيجة كما يلي:
كما ترى ، قمنا بتشغيل مؤشر LED واحد في كل مرة (من اليسار إلى اليمين) عن طريق إبقاء الباقي مطفأ. "الحلقة التالية" لـ (int i = 7 ؛ i> = 0 && RB0 == 0 ؛ i--) ، ستفعل الشيء نفسه أيضًا ولكن هذه المرة سيتم تشغيل LED من اليمين إلى اليسار بالتسلسل ، حيث بدأنا من 7 ونزلنا إلى 0. استخدمنا تأخيرًا قدره 200 مللي ثانية حتى نتمكن من تصور تشغيل وإيقاف تشغيل LED.
الآن عندما نمرر القيمة 3 في وظيفة sblink (int get) ، لذلك سيتم تنفيذ الوظيفة sblink (3) مما يجعل قيمة 'get' كـ 0b00000011 ، وبالتالي ستكون النتيجة على PORTD:
الآن هذه المرة سيتم تشغيل اثنين من مصابيح LED في أي وقت باستخدام sblink (3). وبالمثل بالنسبة لـ sblink (7) و sblink (15) ، سيتم تشغيل ثلاثة وأربعة مصابيح LED بالتسلسل. بمجرد اكتمال ذلك ، سنجعل كل مؤشر LED قيد التشغيل باستخدام السطر PORTD = 0xFF . تحقق من الفيديو أدناه للحصول على شرح كامل.
آمل أن تكون قد فهمت الكود ، وبالتالي تعلمت كيفية استخدام الدوال ، حلقة "for" و "while" للحصول على المخرجات المرغوبة. يمكنك الآن تعديل التعليمات البرمجية للحصول على تسلسل مختلف من وميض LED. امض قدمًا في تجميع الكود الخاص بك وتفريغه في MCU والاستمتاع بالإخراج. يمكنك استخدام قسم التعليقات إذا واجهتك مشكلة في مكان ما. لقد أرفقت أيضًا ملفات المحاكاة والبرامج هنا.
هذا كل شيء الآن في برنامجنا التعليمي التالي سنتعلم كيفية استخدام أجهزة ضبط الوقت PIC16F877A بدلاً من استخدام وظائف التأخير. يمكنك تصفح جميع دروس الميكروكونترولر PIC هنا.