تنفيذ ضوء التنفس LED باستخدام المتحكم الدقيق 51

Jun 11, 2026 ترك رسالة

[مقدمة]


تعد تقنية المتحكم الدقيق تقنية سائدة لا غنى عنها في الأتمتة الصناعية الحديثة والإلكترونيات والهندسة الكهربائية وإنترنت الأشياء (IoT). نظرًا لأن حياتنا أصبحت ذكية بشكل متزايد، فقد تغلغلت تكنولوجيا المتحكمات الدقيقة تقريبًا في كل جانب من جوانب حياتنا اليومية، كما هو الحال في أجهزة طهي الأرز الذكية، ومكبرات الصوت الذكية، والمزيد.


مع أخذ ذلك في الاعتبار، تهدف سلسلة المقالات "إعادة تعلم 51 وحدة تحكم دقيقة" إلى مساعدة المبتدئين على البدء في استخدام تقنية وحدات التحكم الدقيقة. سنبدأ بأبسط مهمة-تشغيل مصباح LED واحد-ونتقدم تدريجيًا إلى تنفيذ وحدات مثل عناصر التحكم بالأزرار، وشاشة LCD1602، وأجهزة استشعار درجة الحرارة DS18B20 وDS1302، والاتصال بين وحدتي تحكم دقيقتين. سنغطي أيضًا بروتوكولات اتصالات الأجهزة مثل UART وI²C وSPI. من خلال الجمع بين هذه المفاهيم وتقنيات البرمجة بلغة C، سنستخدم{10}}مشاريع هندسية حقيقية لتوضيح أساليب البرمجة، مما يتيح لك تطبيق مؤشرات وهياكل لغة C بمرونة لتحقيق البرمجة المعيارية.


الآن، دعنا نعود إلى الموضوع الرئيسي: استخدام متحكم 51 للتحكم في مصباح LED وإنشاء تأثير ضوء التنفس.

 

[كيف تعمل أضواء التنفس]


دعونا أولاً نلقي نظرة على كيفية عمل تأثير ضوء التنفس.
يضيء ضوء التنفس تدريجيًا ثم يخفت تدريجيًا، ويكرر هذه الدورة بطريقة تشبه التنفس. ومع ذلك، بما أن أطراف المتحكم الدقيق يمكنها فقط إخراج إما 1 (تشغيل) أو 0 (إيقاف)، فكيف يمكن تحقيق تأثير الانتقال التدريجي؟
ويرجع ذلك إلى استمرار الرؤية في أعيننا. عندما ننظر إلى شيء ما، فإن الصورة التي تشكلها أعيننا تستمر لمدة 0.04 ثانية (تم العثور على هذا الرقم عبر الإنترنت).
إذا حسبنا على أساس 0.04 ثانية، فهذا يساوي 40 مللي ثانية. لذلك، عندما يتم تشغيل وإيقاف مؤشر LED لمدة 20 مللي ثانية لكل منهما، فإنه يبدو للعين البشرية كما لو كان مضاءً باستمرار.

图片

هل تأثير وميض مؤشر LED لمدة 20 مللي ثانية وإيقافه لمدة 20 مللي ثانية هو نفس تأثير إبقائه مضاءً طوال الوقت؟

 

هههه أكيد مختلف عندما يتناوب الضوء بين التشغيل والإيقاف كل 20 مللي ثانية، يكون التأثير الذي نراه خافتًا مقارنة بإبقائه مضاءً بشكل مستمر. إذا افترضنا أن سطوع الضوء المضاء باستمرار هو 100%، فإن سطوع الضوء الذي يتناوب بين التشغيل والإيقاف كل 20 مللي ثانية هو 50%. وبناءً على ذلك، يمكننا ضبط سطوع LED.

图片

 

عند هذه النقطة، يمكننا ضبط سطوع مؤشر LED (عن طريق تحديد مدة المستوى العالي خلال دورة 40 مللي ثانية). هذا هو المبدأ الكامن وراء طريقة -PWM (تعديل عرض النبض) المعروفة للتحكم في السطوع، وتحديد مدة المستوى العالي يعادل ضبط دورة العمل (أي مدة المستوى العالي مقسومة على الدورة الإجمالية: 20/40=50%)).


هنا، العامل الأكثر أهمية هو دورة العمل هذه. على سبيل المثال، إذا كانت الفترة 20 مللي ثانية، مع تبديل مؤشر LED بين 10 مللي ثانية في وضع التشغيل و10 مللي ثانية في وضع الإيقاف، فإن السطوع المدرك يظل 50% (أي دورة التشغيل هي 10/20=50%)).

بعد ذلك، دعونا نرى كيف يتم تنفيذ ذلك في البرنامج.

 

[تنفيذ البرنامج]


تشغيل الصمام
أولاً، لنبدأ بتشغيل مصباح LED، ثم سنقوم تدريجيًا بتنفيذ تأثير ضوء التنفس. الأجهزة التي سنستخدمها هي كما يلي:

مجلس التنمية مجلس تطوير التدريب على المتحكمات الدقيقة ZeroOne
نموذج المتحكم الدقيق STC89C52
واجهة الصمام دبوس P4^4
图片

 

من المخطط، يمكننا أن نرى أن مؤشر LED متصل بالطرف P4^4 الخاص بالمتحكم الدقيق. عندما يقوم المتحكم الدقيق بإخراج الرقم 1، يتم تشغيل مؤشر LED؛ عندما يخرج 0، ينطفئ مؤشر LED. ولذلك، فإن برنامج تشغيل LED بسيط للغاية، كما هو موضح أدناه:

info-299-230

 

 

برنامج تشغيل LED بسيط للغاية؛ أنا متأكد من أن الجميع يعرف كيفية القيام بذلك.
 

ضبط سطوع LED


بعد ذلك، سنقوم بتنفيذ وظيفة تسمح لنا بضبط السطوع (أي ضبط دورة التشغيل)، على النحو التالي:

info-400-538


 

حدد متغيرًا ثابتًا "duty_cycle" لتخزين دورة العمل. عندما تكون قيمة "العلم" 1، تزيد دورة العمل تدريجيًا إلى 255، ثم اضبط "العلم" على 0، وتنخفض "دورة_العمل" تدريجيًا من 255 إلى 0. كرر هذه الدورة.
هاها، في هذه المرحلة، قد تعتقد أن ضوء التنفس يعمل بالفعل، لكنه ليس كذلك. إذا كنت لا تصدقني، جرب الكود أعلاه بنفسك.

إذن أين المشكلة بالضبط؟


تكمن المشكلة في اتصالنا المباشر بوظيفة ضبط السطوع-`set_led_luminance()`. تستغرق هذه الوظيفة 40 مللي ثانية لإكمال دورة واحدة، مما يعني أنه لا يمكن تغيير دورة العمل خلال تلك الـ 40 مللي ثانية؛ وإلا فإن تعديل السطوع لن يعمل. دعونا نلقي نظرة أخرى على وظيفة "breath_led". بعد كل استدعاء لـ `set_led_luminance()` لتعيين دورة العمل، فإنه يغير قيمة `duty_cycle` على الفور دون الانتظار لمدة 40 مللي ثانية.


في هذه المرحلة، نحتاج إلى إضافة مؤقت برمجي لتحديث قيمة `duty_cycle` بعد انقضاء 40 مللي ثانية. البرنامج المعدل هو كما يلي:

info-495-656

 

 

ملاحظة: يجب أن تكون مدة المؤقت أكبر من 40 مللي ثانية (أي أن قيمة `s_breathCounter` يجب أن تكون أكبر من 255)، ولكن من الأفضل ضبطها على مضاعفات الدورة. على سبيل المثال، إذا كانت دورتنا هي 255 (أي 256 قيمة من 0 إلى 255)، فيمكننا ضبطها على ضعف هذه القيمة: 256 * 2 - 1=511 (أي 512 قيمة من 0 إلى 511).
والآن أصبح الأمر -اكتمل ضوء التنفس لدينا! أليس هذا بسيطا؟ (* ̄︶ ̄)

 

التالي هو قسم المكافآت اليوم.

على الرغم من أننا حققنا تأثيرًا خفيفًا، إلا أن الشفرة ليست موجزة أو أنيقة بدرجة كافية-فهي تستخدم مجموعة من عبارات if و else. دعونا نرى ما إذا كان بإمكاننا تبسيط الأمر أكثر.

أولاً، دعونا نبسط هذا القسم من الدالة set_led_luminance()، كما هو موضح في الشكل أدناه.
 

图片

 

قبل أن نقوم بتبسيط ذلك، دعونا نغطي نصيحة سريعة حول لغة C: عملية التشغيل AND.

info-600-117

 

من هذا، نعلم أنه سواء كانت 1 أو 0، فإن إجراء عملية AND مع 0 يؤدي إلى 0.

سواء كانت 1 أو 0، فإن تنفيذ عملية AND برقم 1 يؤدي إلى القيمة الأصلية.

للراحة، نستخدم التدوين السداسي العشري (يسبقه "0x")؛ على سبيل المثال، 0xff يتوافق مع 255 بالنظام العشري. لذلك،

 

عندما يتم ربط رقم أقل من أو يساوي 0xff بـ ANDed مع 0xff، تكون النتيجة هي الرقم نفسه، كما هو موضح أدناه

info-534-63

 

 

ماذا يحدث إذا قمت بإجراء عملية AND على مستوى البت بين رقم أكبر من 0xff و0xff؟

info-551-63

والنتيجة هي الباقي عند قسمة هذا الرقم على (0xff + 1) (أي أن النتيجة لا تزال بين 0 و0xff).
باستخدام عملية AND هذه، يمكن تبسيط الكود أعلاه

info-550-64

 

 

بهذه الطريقة، ستكون قيمة s_Counter دائمًا ضمن النطاق من 0x00 إلى 0xff.
وبالمثل، يمكن أيضًا تبسيط مؤقت البرنامج في وظيفة Breath_led أعلاه على النحو التالي:

info-389-353

في السطر 3، 0x1ff هو 511 بالنظام العشري. يكون الشرط صحيحًا عندما تكون قيمة s_breathCounter هي (0x1ff+1)، أو 512، لأن 512 & 0x1ff=0. علامة التعجب قبل أن تشير إلى عملية NOT للبت (على وجه الدقة، يتم استيفاء الشرط عندما تكون قيمة `s_breathCounter` من مضاعفات 512؛ وهذا يلغي الحاجة إلى إعادة تعيين `s_breathCounter`. آمل هذا الشرح واضح-يُرجى التفكير مليًا). إذا تم استيفاء الشرط، تبدأ دورة العمل في الزيادة أو النقصان.


لكن أليست دورة العمل تتراوح من 0 إلى 255؟ لماذا يصبح السطر 5 أيضًا 0x1ff (511)؟ لا تقلق-انظر إلى السطر 8. قمنا بطرح 0xff مرة أخرى، بحيث يظل نطاق دورة الخدمة من 0 إلى 255.


تعني الأسطر 7-10: عندما تكون `duty_cycle > (0xff)`، أي 256–511، فإن طرح 0xff يعادل الزيادة من 1 إلى 255، وبالتالي يزداد السطوع تدريجيًا.


عندما Duty_cycle<= 0xff, the duty_cycle increases from 0 to 255, while the set brightness is 255 - duty_cycle. This effectively decreases the brightness from 255 to 0, causing the light to gradually dim. This achieves the breathing light effect.


هاها، هل تعتقد أن تبسيطنا قد انتهى؟

 

لا، لا، لا

في الواقع، يمكن تبسيط الأسطر من 7 إلى 10 بشكل أكبر. هذا هو المكان الذي تكون فيه دالة القيمة المطلقة مفيدة.

ماذا؟ لماذا نستخدم دالة القيمة المطلقة؟

 

انظر إلى السطر 10: 0xff - Duty_cycle تعادل دورة Duty_cycle - 0xff ثم تأخذ القيمة المطلقة. حسنًا، إليك الكود المبسط:

set_led_luminance(ABS(duty_cycle - (0xff)));

 

 

وظيفة الماكرو لأخذ القيمة المطلقة هي كما يلي

#define ABS(N) ((N) < 0 ? -(N) : (N))

 

وأخيرًا، قمت بتضمين الكود المبسط بالكامل أدناه

 

info-562-684

ماذا تعتقد؟ أليس الأمر بسيطا؟ (* ̄︶ ̄)

إرسال التحقيق

whatsapp

الهاتف

البريد الإلكتروني

التحقيق