التحكم في الموانئ من خلال سجلات atmega. برمجة المتحكمات الدقيقة AVR في سجل بيانات المنفذ A - PORTA

قليل

قراءة و كتابة

القيمة البدائية

بت 7 - قم بتمكين كل المقاطعات. لتمكين المقاطعات ، يجب تعيين هذا البت على 1. يتم التحكم في تمكين مقاطعة معينة بواسطة مسجلات قناع المقاطعة EIMSK و TIMSK. إذا تم مسح هذا البت (= 0) ، فلن يتم التعامل مع أي من المقاطعات. يتم مسح البت بواسطة الجهاز بعد حدوث مقاطعة ويتم تعيينه لتمكين المقاطعة لاحقًا باستخدام تعليمات RETI.
بت 6 - حفظ نسخة بت. تستخدم تعليمات نسخ بت BLD و BST هذا البت كمصدر ووجهة لعمليات البت. يقوم الأمر BST بنسخ جزء من السجل العام إلى بت T ، يقوم الأمر BLD بنسخ بت T إلى بت السجل العام.
· بت 5 - علم نصف حمل. يشير إلى انتقال بين tetrads عند إجراء عدد من العمليات الحسابية.
بت 4 - قم بتوقيع. يحتوي بت S على قيمة نتيجة عملية XOR (N (+) V) على أعلام القيمة السالبة (N) ومكمل الاثنين لعلم الفائض (V).

· بت 3 - تكملة Two لعلم تجاوز السعة. وهو يدعم الحساب التكميلي لاثنين.
· بت 2 - العلم السلبي. تشير هذه العلامة إلى نتيجة سلبية لعدد من العمليات الحسابية والمنطقية.
· بت 1 - علم صفري. تشير هذه العلامة إلى النتيجة الصفرية لعدد من العمليات الحسابية والمنطقية.
· بت 0 - حمل العلم. يشير هذا العلم إلى الحمل أثناء العمليات الحسابية والمنطقية.

يحتوي المتحكم AT90S8535 على 4 منافذ إدخال / إخراج متوازية A و B و C و D.
المنفذ A هو منفذ ثنائي الاتجاه 8 بت. يتم التفاعل مع المنفذ A من خلال ثلاثة سجلات في مساحة إدخال / إخراج ذاكرة البيانات: سجل البيانات - PORTA ، $ 1B ($ 3B) ، سجل اتجاه البيانات - DDRA ، $ 1A ($ 3A) ، سجل بيانات الإدخال - PINA ، 19 دولارًا (39 دولارًا). سجل PINA للقراءة فقط ، في حين أن سجلات PORTA و DDRA للقراءة والكتابة. سجل PINA ليس سجلاً بالمعنى الكامل للكلمة. يوفر الوصول إليه قراءة للحالة المادية لكل منفذ منفذ. يستخدم المنفذ A أيضًا لإدخال إشارات A / D التناظرية.

سجل بيانات المنفذ أ -بورتا

قليل

قراءة و كتابة

القيمة البدائية

سجل اتجاه بيانات المنفذ أ -DDRA

قليل

قراءة و كتابة

القيمة البدائية

سجل بيانات إدخال المنفذ A -PINA

قليل

قراءة و كتابة

القيمة البدائية

المنفذ B هو منفذ إدخال / إخراج ثنائي الاتجاه 8 بت. كما هو الحال مع المنفذ A ، يتم الاتصال بالمنفذ B من خلال ثلاثة سجلات في مساحة إدخال / إخراج ذاكرة البيانات: سجل البيانات - PORTB ، 18 دولارًا (38 دولارًا) ، سجل اتجاه البيانات - DDRB ، 17 دولارًا (37 دولارًا) وسجل بيانات الإدخال - PINB ، 16 دولارًا (36 دولارًا). سجل PINB للقراءة فقط. سجل PINB ليس سجلاً بالمعنى الكامل للكلمة. يوفر الوصول إليه قراءة للحالة المادية لكل منفذ منفذ. يمكن أن تؤدي دبابيس المنفذ B الوظائف البديلة الموضحة في الجدول 1. 2.1.

الجدول 2.1. وظائف المنفذ B Pin البديلة

دبوس المنفذ

وظيفة بديلة

T0 - إدخال المؤقت / ساعة العداد 0

T1 - الموقت / عداد 1 ساعة الإدخال

AIN0 - الطرف الموجب للمقارنة

AIN1 - الطرف السالب للمقارنة

- مدخلات اختيار الرقيق SPI

MOSI - إعداد خرج SPI الرئيسي / إدخال الرقيق

MISO - إعداد إدخال / إخراج الرقيق الرئيسي SPI

SCK - إشارة الساعة SPI

عند استخدام دبابيس لوظائف بديلة ، يجب ضبط مسجلات PORTB و DDRB وفقًا لذلك.

سجل بيانات الميناءببورتب

قليل

قراءة و كتابة

القيمة البدائية

تسجيل اتجاه بيانات المنفذ B -DDRB

قليل

قراءة و كتابة

القيمة البدائية

تسجيل بيانات إدخال المنفذ B -PINB

قليل

قراءة و كتابة

القيمة البدائية

المنفذ C هو منفذ إدخال / إخراج ثنائي الاتجاه 8 بت. تمامًا مثل المنفذين A و B ، يتم تنفيذ التفاعل مع المنفذ C من خلال ثلاثة سجلات في مساحة إدخال / إخراج ذاكرة البيانات: سجل البيانات هو PORTC ، 15 دولارًا (35 دولارًا) ، سجل اتجاه البيانات هو DDRC ، 14 دولارًا (34 دولارًا) ) وسجل بيانات الإدخال هو PINC ، 13 دولارًا (33 دولارًا). سجل PINC للقراءة فقط ، في حين أن سجلات PORTC و DDRC للقراءة والكتابة. سجل PINC ليس سجلاً بالمعنى الكامل للكلمة. يوفر الوصول إليه قراءة للحالة المادية لكل منفذ منفذ.
يحتوي المنفذ C على طرفين فقط يمكنهما أداء وظائف بديلة: تؤدي الدبابيس PC6 و PC7 وظائف TOSC1 و TOSC2 في Timer / Counter 2.

سجل بيانات الميناءجPORTC

قليل

قراءة و كتابة

القيمة البدائية

تسجيل اتجاه بيانات المنفذ C -DDRC

قليل

قراءة و كتابة

القيمة البدائية

تسجيل بيانات إدخال المنفذ C -PINC

قليل

قراءة و كتابة

القيمة البدائية

المنفذ D هو منفذ إدخال / إخراج ثنائي الاتجاه 8 بت. كما هو الحال مع المنافذ A و B و C ، يكون الاتصال بالمنفذ D من خلال ثلاثة سجلات في مساحة إدخال / إخراج ذاكرة البيانات: سجل البيانات هو PORTD ، $ 12 ($ 32) ، سجل اتجاه البيانات هو DDRD ، $ 11 ($ 31) ، وسجل بيانات الإدخال - PIND ، 10 دولارات (30 دولارًا). يوفر سجل PIND إمكانية القراءة ، بينما توفر سجلات PORTD و DDRD إمكانية القراءة والكتابة. سجل PIND ليس سجلا بالمعنى الكامل للكلمة. يوفر الوصول إليه قراءة للحالة المادية لكل منفذ منفذ.
يمكن أن تؤدي دبابيس المنفذ D الوظائف البديلة الموضحة في الجدول 1. 2.2.

الجدول 2.2. وظائف المنفذ D البديل

دبوس المنفذ

وظيفة بديلة

RxD - إدخال جهاز الاستقبال UART

TxD - خرج جهاز الإرسال UART

INT0 - إدخال المقاطعة الخارجية 0

INT1 - مدخلات المقاطعة الخارجية 1

OC1B - المؤقت / عداد 1 دبوس مقارنة الإخراج

OC1A - خرج مقارنة المخرجات A للمؤقت / العداد 1

ICP - المؤقت / العداد 1 إدخال مشغل الالتقاط

OC2 - مؤقت / عداد 2 دبوس مقارنة الإخراج

عند استخدام دبابيس لوظائف بديلة ، يجب ضبط سجلات PORTD و DDRD وفقًا لذلك.

سجل بيانات الميناءدبورتد

قليل

قراءة و كتابة

القيمة البدائية

سجل اتجاه بيانات الميناءدDDRD

قليل

قراءة و كتابة

القيمة البدائية

سجل إدخال المنفذدPIND

قليل

قراءة و كتابة

القيمة البدائية

نظرًا لأن العمل قيد الدراسة هو الأول ، فلكي يكتسب الطلاب المهارات اللازمة للعمل مع مجمع المختبر ، يقوم جميع الطلاب أولاً بنفس العمل. من أماكن العمل الخاصة بهم ، يدخلون إلى جهاز الكمبيوتر نفس المهمة المتمثلة في طرح الرقم 3 من الرقم 5 الوارد في الفقرة 1.5.3.1. بعد تجميع البرنامج ، يتم كتابته إلى المتحكم الدقيق في مكان العمل ويتم عرض عمله على المعلم.
بعد هذا التعارف مع المجمع ، يشرع الطالب في أداء مهمة فردية. إذا كان هناك وقت ، يمكن للمدرس أن يعقد المهمة الفردية.

تعتمد عمليات Bitwise على العمليات المنطقية ، والتي سبق أن تناولناها مسبقًا. يلعبون دورًا رئيسيًا في برمجة وحدات التحكم الدقيقة AVR وأنواع أخرى. لا يمكن لأي برنامج تقريبًا الاستغناء عن استخدام العمليات الأحادية. حتى الآن ، تجنبناهم عمدًا لتسهيل تعلم برمجة MK.

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

قبل الانتقال إلى إتقان أجهزة MK المدمجة ، تحتاج إلى معرفة كيفية التحكم أو التحقق من البتات الفردية من سجلات AVR MK. في السابق ، أجرينا فحصًا أو عيّننا أجزاء السجل بالكامل مرة واحدة. دعونا نرى ما هو الفرق ، ثم نواصل أكثر.

عمليات Bitwise

في أغلب الأحيان ، عند برمجة وحدات التحكم الدقيقة AVR ، استخدمناها ، نظرًا لأنها تتميز بدرجة وضوح أكبر مقارنةً بمبرمجي MK المبتدئين ومفهومة جيدًا. على سبيل المثال ، نحتاج إلى تعيين الجزء الثالث فقط من المنفذ D. لهذا ، كما نعلم بالفعل ، يمكننا استخدام الكود الثنائي التالي:

PORTD = 0b00001000 ؛

ومع ذلك ، باستخدام هذا الأمر ، قمنا بتعيين البت الثالث على واحد ، وقمنا بإعادة تعيين جميع البقية الأخرى (0 ، 1 ، 2 ، 4 ، 5 ، 6 و 7) إلى الصفر. والآن دعونا نتخيل الموقف الذي يتم فيه استخدام الرقمين السادس والسابع كمدخلات ADC وفي هذا الوقت تصل إشارة من بعض الأجهزة إلى المخرجات المقابلة لـ MK ، ونقوم بإعادة ضبط هذه الإشارات باستخدام الأمر أعلاه. نتيجة لذلك ، لا يراها المتحكم الدقيق ويعتقد أن الإشارات لم تأت. لذلك ، بدلاً من مثل هذا الأمر ، يجب أن نستخدم أمرًا آخر من شأنه أن يضبط البتة الثالثة فقط على واحد ، مع عدم التأثير على بقية البتات. لهذا ، عادة ما يتم استخدام العملية التالية على مستوى أحادي:

المنفذ | = (1<<3);

سنقوم بتحليل بناء الجملة بالتفصيل أدناه. والآن مثال آخر. لنفترض أننا بحاجة إلى التحقق من حالة الجزء الثالث من سجل PIND ، وبالتالي التحقق من حالة الزر. إذا تمت إعادة تعيين هذا البت إلى الصفر ، فإننا نعلم أنه يتم الضغط على الزر ثم يتم تنفيذ رمز الأمر ، والذي يتوافق مع حالة الزر المضغوط. في السابق ، كنا قد استخدمنا الترميز التالي:

إذا (pind == 0b00000000)

(أي كود)

ومع ذلك ، بمساعدته ، لا نتحقق من أي واحد ، - الثالث ، ولكن كل أجزاء تسجيل PIND مرة واحدة. لذلك ، حتى في حالة الضغط على الزر وإعادة تعيين البت المطلوب ، ولكن في ذلك الوقت يتم تلقي إشارة على أي منفذ D منفذ آخر ، سيتم تعيين البت المقابل على واحد ، وستكون الحالة بين قوسين خاطئة. نتيجة لذلك ، لن يتم تنفيذ الكود الموجود في الأقواس المتعرجة حتى عند الضغط على الزر. لذلك ، للتحقق من حالة البت الثالث الفردي من سجل PIND ، يجب استخدام عملية البت:

إذا كان (~ PIND & (1<<3))

(أي كود)

للعمل مع البتات الفردية من المتحكم الدقيق ، فإن لغة البرمجة C لديها في ترسانتها ، والتي يمكنك من خلالها تغيير أو التحقق من حالة بت واحد أو أكثر في وقت واحد.

تحديد بت واحد

لتعيين بت واحد ، مثل المنفذ D ، يتم استخدام عملية "OR". هذا ما استخدمناه في بداية المقال.

PORTD = 0b00011100 ؛ // القيمة البدائية

PORTD = PORTD | (واحد<<0); применяем побитовую ИЛИ

المنفذ | = (1<<0); // сокращенная форма записи

PORTD == 0b00011101 ؛ // نتيجة

يقوم هذا الأمر بتعيين البت إلى الصفر ويترك الباقي دون تغيير.

على سبيل المثال ، دعنا نضبط البتة السادسة من المنفذ D.

PORTD = 0b00011100 ؛ // حالة المنفذ الأولية

المنفذ | = (1<<6); //

PORTD == 0b01011100 ؛ // نتيجة

لكتابة واحد إلى عدة بتات منفصلة في وقت واحد ، على سبيل المثال ، المنفذ صفر والسادس والسابع بيتم تطبيق التدوين التالي.

PORTB = 0b00011100 ؛ // القيمة البدائية

بورتب | = (1<<0) | (1<<6) | (1<<7); //

PORTB == 0b1011101 ؛ // نتيجة

إعادة تعيين (التصفير) البتات الفردية

لإعادة تعيين بت واحد ، يتم استخدام ثلاثة أوامر تمت مناقشتها مسبقًا مرة واحدة: .

دعنا نعيد ضبط الجزء الثالث من سجل PORTC ونترك الباقي دون تغيير.

PORTC = 0b00011100 ؛

PORTC & = ~ (1<<3);

PORTC == 0b00010100 ؛

لنقم بتنفيذ إجراءات مماثلة للرقمين الثاني والرابع:

PORTC = 0b00111110 ؛

PORTC & = ~ ((1<<2) | (1<<4));

PORTC == 0b00101010 ؛

تبديل الإيقاع

بالإضافة إلى الضبط وإعادة التعيين ، يتم أيضًا استخدام أمر مفيد يقوم بتبديل بت واحد إلى الحالة المعاكسة: واحد إلى صفر والعكس صحيح. تُستخدم هذه العملية المنطقية على نطاق واسع في بناء تأثيرات الإضاءة المختلفة ، على سبيل المثال ، إكليل رأس السنة الجديدة. تأمل في مثال PORTA

PORTA = 0b00011111 ؛

بورتا ^ = (1<<2);

PORTA == 0b00011011 ؛

غيّر حالة البتات الصفرية والثانية والسادسة:

PORTA = 0b00011111 ؛

بورتا ^ = (1<<0) | (1<<2) | (1<<6);

PORTA == 0b01011010 ؛

التحقق من حالة بت فردي. دعني أذكرك بأن التحقق (على عكس الكتابة) من منفذ الإدخال / الإخراج يتم عن طريق قراءة البيانات من سجل PIN.

يتم إجراء الاختبار الأكثر شيوعًا بواسطة إحدى عبارتين حلقتين: if و while. نحن نعرف بالفعل هؤلاء المشغلين في وقت سابق.

التحقق من التفريغ لوجود صفر منطقي (إعادة تعيين) مع إذا

إذا كان (0 == (PIND & (1<<3)))

إذا تم مسح البتة الثالثة من المنفذ D ، فسيتم تنفيذ Code1. خلاف ذلك ، يتم تنفيذ Code2.

يتم تنفيذ إجراءات مماثلة مع وفي هذا النوع من التسجيل:

إذا كان (~ PIND & (1<<3))

التحقق من التفريغ لوجود الوحدة المنطقية (الإعداد) مع إذا

إذا كان (0! = (PIND & (1<<3)))

إذا كان (PIND & (1<<3))

تعمل الحلقتان المذكورتان أعلاه بشكل مشابه ، ولكن نظرًا لمرونة لغة البرمجة C ، يمكن كتابتها بشكل مختلف. العملية! = تعني عدم المساواة. إذا تم تعيين البت الثالث من منفذ الإدخال / الإخراج PD (واحد) ، فسيتم تنفيذ Code1 ، وإذا لم يكن الأمر كذلك ، فسيتم تنفيذ Code2.

في انتظار إعادة تعيين قليلا مع في حين

بينما (PIND & (1<<5))

سيتم تنفيذ الكود 1 طالما تم ضبط البتة الخامسة من سجل PIND. ستؤدي إعادة تعيينه إلى بدء تنفيذ Code2.

في انتظار البت ليتم ضبطها في حين

هنا ، يسمح لك بناء جملة لغة سي بكتابة التعليمات البرمجية بطريقتين من أكثر الطرق شيوعًا. في الممارسة العملية ، يتم استخدام كلا النوعين من التسجيل.

لفترة طويلة غادرنا دون اهتمام ميكروكنترولر AVRوالآن حان الوقت لتصحيح سوء التفاهم هذا! بالنسبة لعناصر التحكم الأخرى ، سننظر تدريجيًا في العديد من ملحقات AVR ، أولاً النظرية ، وجميع أنواع السجلات ، وأخيراً ، أمثلة صغيرة.

بصفتي IDE أستخدمه AVR ستوديو 5، الإصدار السادس ستوديو AVRلم أجربه حتى الآن ، ولم أجد مهام لـ AVR كثيرًا مؤخرًا) بشكل عام ، ليس من السيئ تثبيت AVR Studio 4 أيضًا ، لأنه يحدث أحيانًا أنك تحتاج إلى برمجة وحدة التحكم من AVR ستوديو 5لا يبدو ممكنا. في الآونة الأخيرة فقط ، أردت وميض ATMega2560 باستخدام مبرمج STK500 ، واتضح أن هذا مستحيل بعد Studio 5) لقد بقي جيدًا منذ الأيام الخوالي لـ AVR Studio 4 ، وتم حل المشكلة في غضون دقيقتين.

ماذا يمكنني أن أقول أيضًا؟ .. نعم ، من حيث المبدأ ، هذا كل شيء ، يمكنك البدء في العمل ؛)

بطبيعة الحال ، سنبدأ بـ GPIO - منافذ الإدخال والإخراجلأنه بدونهم لا يوجد مكان) وقبل أن أصف السجلات التي تتحكم في تشغيل الموانئ ، سأذكر بضع لحظات "كهربائية".

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

الآن للتسجيلات. يتركز كل العمل مع منافذ الإدخال / الإخراج في AVRs في ثلاثة سجلات - DDRx و PORTx و PINx. يتم استبدال الحرف "x" باسم المنفذ المقابل (A ، B ...). بمعنى ، إذا أردنا العمل مع المنفذ A من وحدة التحكم الدقيقة ، فنحن بحاجة إلى سجلات DDRA و PORTA و PINA. إذا أردنا العمل مع الجزء الخامس من المنفذ A (PA5) ، فنحن مهتمون بالجزء الخامس من السجلات المذكورة أعلاه. كما ترى ، كل شيء بسيط للغاية) يبقى فقط معرفة ماذا وأين تكتب ، ما هي مسؤولية كل من هذه السجلات. لذلك بدأنا ...

سجل DDRx.

DDRx هي المسؤولة عن اتجاه تشغيل المسامير المقابلة للميكروكونترولر. يمكن أن يكون كل دبوس إما مدخلاً أو مخرجًا ، ولا يوجد ثالث. لتكوين الإخراج للعمل في وضع إدخال سجل DDR ، تحتاج إلى كتابة 0 لهذا المنفذ ، و 1 للإخراج. دعنا نقول أننا نحتاج إلى تكوين PA6 كمدخل ، و PA3 كمخرج. ماذا نفعل؟ هذا صحيح ، قمنا بتعيين البت الثالث من سجل DDRA على 1 ، وكتبنا 0 إلى الجزء السادس من نفس سجل DDRA.

تسجيل PINx.

لا يمكننا كتابة أي شيء في هذا السجل ، فهو مخصص حصريًا لقراءة البيانات. يحتوي هذا السجل على معلومات حول مستوى الإشارة على المنفذ المقابل. كما نتذكر ، فإن الميكروكونترولر هو جهاز رقمي ، ويمكن أن تكون الإشارات الموجودة على ساقيه إما عالية (منطقية 1) أو منخفضة (منطقية 0). إذا أردنا معرفة ما لدينا هناك عند إدخال PB4 ، فنحن مهتمون بالجزء الرابع من سجل PINB.

سجل PORTx.

هذا السجل أكثر تعقيدًا بقليل من السجلات السابقة. تعتمد وظيفتها على الاتجاه الذي تعمل فيه دبابيس المتحكم الدقيق. إذا تم استخدام الدبوس كمدخل ، فإن سجل PORTx يحدد نوع الإدخال. يوجد خياران محتملان هنا:

PORTx = 1 - باستخدام هذا التكوين ، نحصل على إدخال مع سحب (PullUp)

PORTX = 0 - مدخلات مقاومة عالية (Hi-Z) - وهذا يعني أن مقاومة المنفذ عالية جدًا بحيث يمكن اعتبارها غير محدودة)

لذلك دعنا نواصل مع سجل PORTx. إذا كان الإخراج يعمل كمخرج ، وكان سجل PORTx واحدًا ، فسيكون الناتج مستوى إشارة مرتفعًا ، وبالمثل ، PORTx \ u003d 0 - مستوى منخفض.

لنأخذ مثالًا صغيرًا لتوضيح 😉

لنقم بتهيئة دبوس PC4 ليعمل في وضع إدخال السحب. للقيام بذلك ، اكتب 0 (وضع الإدخال) إلى البتة الرابعة من سجل DDRC ، واضبط البتة الرابعة في سجل PORTC على 1 (سحب لأعلى). هذا كل شئ.

من حيث المبدأ ، هذا هو كل ما يتعلق بالنظرية ، لن نتعمق أكثر. يبقى مراقبة التقاليد واللعب مع الصمام الثنائي. دع الصمام الثنائي متصلاً بالدبوس PV5. دعونا نجعله يرمش! وقبل كل شيء ، دعونا ننشئ مشروعًا. أنا ، كما قلت بالفعل ، استخدم AVR Studio 5 ، وكوحدة تحكم سأختار ATMega88 المفضل لدي)

// قم بتوصيل الملف المطلوب#تتضمن /*******************************************************************/ // وظيفة بسيطة لتوليد تأخيرتأخير باطل (وقت int غير موقع) (بدون إشارة int i = 0 ؛ لـ (i = 0 ؛ i< time ; i++ ) ; } /*******************************************************************/ // تهيئة إخراجنا ، فهو يعمل على الإخراج initAll باطلة (DDRB = 0b00100000 ؛) /*******************************************************************/ // الجسم الفعلي للوظيفة الرئيسية () int main (void) (initAll () ؛ while (1) (// قم بتشغيل الصمام الثنائي PORTB = 0b00100000 ؛ // بقية تأخير (50000) ؛ // إيقاف تشغيل الصمام الثنائي PORTB = 0b00000000 ؛ تأخير (50000) ؛)) /*******************************************************************/

هذه هي الطريقة الأولى لتواصلنا مع ميكروكنترولر AVR. قريباً سننظر ، إن أمكن ، في محيطهم بالكامل ، وبعد ذلك يمكننا إثارة شيء أكثر إثارة للاهتمام 😉

أنت الآن تقرأ هذا وتفكر - الذاكرة والسجلات والمكدس وما إلى ذلك جيدة. لكن لا يمكنك الشعور به ، لا يمكنك رؤيته. ما لم يكن في المحاكاة ، لكن يمكنني كتابة التعليمات البرمجية على دلفي بنفس الحالة. اين اللحم !!!

في الدورات الأخرى هناك ، تقريبًا من الأسطر الأولى ، يفعلون شيئًا مهمًا - يرمشون بصمام ثنائي ويقولون أن هذا هو Hello World. و هنا؟ جيد ؟؟؟

نعم ، نعم ، نعم ، أفهمك. علاوة على ذلك ، ربما ركضت بالفعل إلى منافسيك وأومضت في وجههم الصمام الثنائي ؛)))) لا شيء ، مسامحة.

لم أرغب في التوقف عند نفس الديودك الوامضين ، والتقدم يتطلب فهمًا واضحًا للأساسيات والمبادئ - قاعدة نظرية قوية. ولكن الآن حان وقت التدريب.

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

أدوات
عادةً ما يعني العمل مع المنافذ العمل مع وحدات البت. هذا هو وضع قليلا ، إعادة تعيين قليلا ، عكس قليلا. نعم ، بالطبع ، هناك أوامر مناسبة في المجمع

cbi / sbi ، لكنها تعمل فقط في نطاق عناوين صغير (من 0 إلى 1F ، لذلك دعونا نكتب وحدات ماكرو عالمية أولاً حتى نتمكن من استخدامها في المستقبل ولا نقلق بشأن مساحة العنوان.

سيتم استدعاء وحدات الماكرو:

  • بايت SETB ، بت ، درجة الحرارة
  • CLRB بايت ، بت ، درجة الحرارة
  • INVB بايت ، بت ، درجة حرارة ، درجة حرارة 2

علاوة على ذلك ، عند العمل مع وحدات بت من RVV السفلي (عنوان 0-1F) ، قد لا يتم تحديد قيمة معلمة TEMP - لن يتم استبدالها على أي حال. باستثناء أوامر الانعكاس ، ستكون هناك حاجة إلى سجلات وسيطة.

من المفيد أيضًا أن يكون لديك مجموعة من وحدات الماكرو لا تستخدم السجلات. بتعبير أدق ، سيستخدمون السجلات ، لكن بعد حفظها في المكدس. يمكن دفعهم بلا تفكير مثل الفرق العادية. لكنها ستستغرق وقتًا أطول للتشغيل وستتطلب ذاكرة وصول عشوائي.

  • بايت SETBM ، بت
  • CLRBM بايت ، بت
  • INVBM بايت ، بت

هنا هو رمز المصدر الخاص بهم. كما ترى ، يتم استخدام شروط لغة الماكرو بشكل نشط ، مما يجعل من الممكن إنشاء وحدات ماكرو عالمية. سيحدد المترجم الإصدار الذي سيضعه في مكانه :)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 < 0x20 SBI @0,@1 .else .if @0<0x40 PUSH R17 IN R17,@0 ORI R17,1<<@1 OUT @0,R17 POP R17 .else PUSH R17 LDS R17,@0 ORI R17,1<<@1 STS @0,R17 POP R17 .endif .endif .ENDM ;SET BIT with REG .MACRO SETB .if @0 < 0x20 ; Low IO SBI @0,@1 .else .if @0<0x40 ; High IO IN @2,@0 ORI @2,1<<@1 OUT @0,@2 .else ; Memory LDS @2,@0 ORI @2,1<<@1 STS @0,@2 .endif .endif .ENDM ;............................................................. ;Clear BIT with REG .MACRO CLRB .if @0 < 0x20 ; Low IO CBI @0,@1 .else .if @0<0x40 ; High IO IN @2,@0 ANDI @2,~(1<<@1) OUT @0,@2 .else ; Memory LDS @2,@0 ANDI @2,~(1<<@1) STS @0,@2 .endif .endif .ENDM ;Clear BIT with STACK .MACRO CLRBM .if @0 < 0x20 CBI @0,@1 .else .if @0<0x40 PUSH R17 IN R17,@0 ANDI R17,~(1<<@1) OUT @0,R17 POP R17 .else PUSH R17 LDS R17,@0 ANDI R17,~(1<<@1) STS @0,R17 POP R17 .endif .endif .ENDM ;............................................................. .MACRO INVB .if @0 < 0x40 IN @2,@0 LDI @3,1<<@1 EOR @3,@2 OUT @0,@3 .else LDS @2,@0 LDI @3,1<<@1 EOR @2,@3 STS @0,@2 .endif .ENDM .MACRO INVBM .if @0 < 0x40 PUSH R16 PUSH R17 IN R16,@0 LDI R17,1<<@1 EOR R17,R16 OUT @0,R17 POP R17 POP R16 .else PUSH R16 PUSH R17 LDS R16,@0 LDI R17,1<<@1 EOR R17,R16 STS @0,R17 POP R17 POP R16 .endif .ENDM ;= End macro.inc ========================================

؛ = بدء الماكرو .inc ======================================== ؛ ضبط BIT مع المكدس .MACRO SETBM .if @ 0< 0x20 SBI @0,@1 .else .if @0<0x40 PUSH R17 IN R17,@0 ORI R17,1<<@1 OUT @0,R17 POP R17 .else PUSH R17 LDS R17,@0 ORI R17,1<<@1 STS @0,R17 POP R17 .endif .endif .ENDM ;SET BIT with REG .MACRO SETB .if @0 < 0x20 ; Low IO SBI @0,@1 .else .if @0<0x40 ; High IO IN @2,@0 ORI @2,1<<@1 OUT @0,@2 .else ; Memory LDS @2,@0 ORI @2,1<<@1 STS @0,@2 .endif .endif .ENDM ;............................................................. ;Clear BIT with REG .MACRO CLRB .if @0 < 0x20 ; Low IO CBI @0,@1 .else .if @0<0x40 ; High IO IN @2,@0 ANDI @2,~(1<<@1) OUT @0,@2 .else ; Memory LDS @2,@0 ANDI @2,~(1<<@1) STS @0,@2 .endif .endif .ENDM ;Clear BIT with STACK .MACRO CLRBM .if @0 < 0x20 CBI @0,@1 .else .if @0<0x40 PUSH R17 IN R17,@0 ANDI R17,~(1<<@1) OUT @0,R17 POP R17 .else PUSH R17 LDS R17,@0 ANDI R17,~(1<<@1) STS @0,R17 POP R17 .endif .endif .ENDM ;............................................................. .MACRO INVB .if @0 < 0x40 IN @2,@0 LDI @3,1<<@1 EOR @3,@2 OUT @0,@3 .else LDS @2,@0 LDI @3,1<<@1 EOR @2,@3 STS @0,@2 .endif .ENDM .MACRO INVBM .if @0 < 0x40 PUSH R16 PUSH R17 IN R16,@0 LDI R17,1<<@1 EOR R17,R16 OUT @0,R17 POP R17 POP R16 .else PUSH R16 PUSH R17 LDS R16,@0 LDI R17,1<<@1 EOR R17,R16 STS @0,R17 POP R17 POP R16 .endif .ENDM ;= End macro.inc ========================================

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

لكن بالعودة إلى الكود ،
دعنا نرمش LED ، إذن ، أخيرًا؟

بالتأكيد ، ليست مشكلة. مصابيح LED مثبتة بالفعل على اللوحة التجريبية ، فلماذا لا تستخدمها؟ يعلقون على دبابيس المنفذ PD4 ، PD5 ، PD7. أنت فقط بحاجة لارتداء صداري.

؛ تهيئة الأجهزة الداخلية ====================================== SETB DDRD، 4، R16؛ DDRD.4 = 1 SETB DDRD، 5، R16 ؛ DDRD.5 = 1 SETB DDRD، 7، R16 ؛ DDRD.7 = 1 ؛ End Internal Hardware Init ====================================

يبقى أن تضيء الثنائيات لدينا. تضاء عن طريق كتابة البتات في سجل PORT. تم ذلك بالفعل في القسم الرئيسي من البرنامج.

؛ الرئيسي ================================================== = ======= الرئيسية: SETB PORTD، 4، R16؛ مضاءة LED1 SETB PORTD ، 7 ، R16 ؛ مضاءة LED3 JMP الرئيسية ؛ نهاية الصفحة الرئيسية ================================================ = ====

نقوم بتجميعها ، يمكنك تشغيلها في التتبع ، سترى على الفور كيف تتغير البتات. نحن يومض ... وبعد النقر على RESET وتفريغ محمل الإقلاع (ما لم يكن لديك بالطبع) سترى هذه الصورة:


وللنسخة الثانية


في! إنه نوع من الملل. دعونا نغمز بهم.

دعنا فقط نستبدل وحدات الماكرو الخاصة بنا.

؛ الرئيسي ================================================== = ======= الرئيسية: SETB PORTD، 4، R16؛ مضاءة LED1 INVB PORTD ، 7 ، R16 ، R17 ؛ عكس LED3 JMP الرئيسي ؛ نهاية الصفحة الرئيسية ================================================ = ====

وميض ...

لكن التين - كلاهما يعمل ، لكن أحدهما قاتم قليلاً. إنه يومض في الواقع ، لكنه سريع جدًا. إذا أدخلت راسم تذبذب في خرج PD7 ، فسترى أن المستوى يتغير هناك بتردد محموم:


ما يجب القيام به؟ من الواضح أن تبطئ. كيف؟ أسهل طريقة ، والتي تتم ممارستها في الغالبية العظمى من البرامج التعليمية والبدء السريع ، هي التأخير الغبي. أولئك. احصل على كود مثل:

؛ الرئيسي ================================================== = ======= الرئيسية: SETB PORTD، 4، R16؛ مضاءة LED1 INVB PORTD ، 7 ، R16 ، R17 ؛ عكس LED3 RCALL تأخير JMP الرئيسي ؛ نهاية الصفحة الرئيسية ================================================ = ==== ؛ = الإجراء ================================================ = == .equ LowByte = 255 .equ MedByte = 255 .equ HighByte = 255 تأخير: LDI R16، LowByte؛ تحميل ثلاثة بايت LDI R17 ، MedByte ؛ مقتطفاتنا LDI R18 ، حلقة HighByte: SUBI R16،1 ؛ اطرح 1 SBCI R17.0 ؛ اطرح فقط C SBCI R18.0 ؛ طرح حلقة C BRCC فقط ؛ إذا لم يكن هناك نقل - الانتقال RET ؛ إجراء الإنهاء ================================================

قمنا بوميضه ، أطلقناه ... أوه نعم ، الآن سيكون الوميض ملحوظًا.

مع المعلمات 255.255.255 ، ستكون سرعة الغالق عند 8 ميجاهرتز حوالي 2.1 ثانية. يمكنك زيادة طول التأخير بمقدار بضع وحدات بايت أخرى. ثم يمكنك شحن ساعة على الأقل.

لكن هذه الطريقة معيبة ، والآن سأوضح لك السبب.

دعونا نضيف زر. دع LED3 يومض في الانعكاس. وسنقوم بذلك بحيث يكون LED1 قيد التشغيل عند الضغط على الزر ، وعندما يتم تحريره ، يكون LED2 قيد التشغيل.

لنأخذ الساعة A كزر ، ونوصلها بمنفذ PD6.


بالنسبة للإصدار الثاني فهو مشابه. ما عليك سوى سحب الزر من مجموعة الأزرار وتوصيل مخرج PD6 لوحدة التحكم بالرمز COL1 على لوحة المفاتيح.

فقط انتبه إلى وصلات العبور الموجودة على وصلات العبور في حقل الزر. تلك الزرقاء هي. وأيضًا رابط أسود غير واضح يشير إليه السهم الأيمن. يقوم بتوصيل عمود الأزرار في أقصى اليسار بالأرض. ينقض على دبابيس GND و ROW1. تم توقيع كل شيء على السبورة.

يتم التحقق من الزر بواسطة أمر SBIC ، ولكن يجب تهيئته أولاً. اجعل DDR = 0 ، PORT = 1 - إدخال سحب.

أضف هذه الأسطر إلى قسم التهيئة (Internal Hardware Init):

؛ الرئيسي ================================================== = ======= الأساسي: SBIS PIND، 6 ؛ إذا تم الضغط على الزر - انتقال RJMP BT_Push SETB PORTD ، 5 ؛ تضيء LED2 CLRB PORTD ، 4 ؛ قم بإيقاف تشغيل مؤشر LED1 التالي: INVB PORTD ، 7 ، R16 ، R17 ؛ عكس LED3 RCALL Delay JMP الرئيسي BT_Push: SETB PORTD ، 4 ؛ تضيء LED1 CLRB PORTD ، 5 ؛ قم بإيقاف تشغيل LED2 RJMP التالي ؛ نهاية الصفحة الرئيسية ================================================ = ====

حسنًا ، إنه يعمل. يتم الضغط على الزر - تتغير الثنائيات. يغمز الثالث بمرح. لكن هناك قبض:

البرنامج يبطئ! ضغطت على الزر ولكن الصورة لم تتغير ، تحتاج إلى الانتظار ، والاحتفاظ بها ... لماذا؟ وهذا بسبب وضعنا bydlokoding.

تذكر أني أخبرتك أن التأخير الغبي الذي لا يفعل فيه عضو الكنيست شيئًا هو شر جهنمي؟ هنا! الآن رأيت ذلك بنفسك. حسنًا ، يجب محاربة الشر. كيف؟ حسنًا ، لقد قلت هذا بالفعل - للقيام بدورة مستمرة مع الأعلام. على الأقل أضف بعض الأعمال المفيدة لتأخيرنا.

الإرغن اليدوي
الآن سأوضح لك كيف يمكنك صنع عضو أسطواني رقمي. هل تتذكر كيف صنعت؟

هناك طبلة ذات مسامير بارزة ونوابض بألوان مختلفة. الأظافر تدور ، والينابيع ترتعش - فهي ترن. اتضح راسكولباسني موزون. وماذا لو تم توسيع أداة hurdy-gurdy إلى شريط. أليس صحيحا أن الأظافر تشبه الوحدات؟ ؛))))

سيكون الشريط عداد عد من الصفر ، على سبيل المثال ، إلى FF.FF.FF.FF ثم مرة أخرى إلى الصفر أو أي قيمة أخرى ، بقدر ما نحتاج إليه وسنفعل. وستلعب الإجراءات الفرعية الخاصة بنا دور الزنبركات ، والتشبث بالأماكن الصحيحة - مقارنة ثابتها بالقيمة الحالية للعداد.

تزامنت؟ دعونا نفعل القرف!

يبقى فقط أن يصف على الدورة الزمنية من منطقتنا hurdy-gurdy أين وماذا يجب أن تطلق. وهنا توجد ميزة واحدة مريحة للغاية - لبناء تسلسلات دورية ، يكفي أن نلتقط بت واحد.

لنفترض أن العضو البرميلي يحسب من 0 إلى 1000 ، ونحن بحاجة إلى وميض الصمام الثنائي 10 مرات. ليس من الضروري التمسك بـ 10 معالجات بقيم مختلفة. يكفي واحد ، لكن ليحقق القيمة ** 10. كل شيء آخر ليس مهم بالنسبة لنا. وسيعمل على 0010 ، 0110 ، 0210 ، 0310 ، 0410 ، 0510 ، 0610 ، 0710 ، 0810 ، 0910. يتم أيضًا تقسيم الفترات الأكثر تكرارًا حسب الحاجة ، ويكفي الوصول إلى فئة أخرى. هنا من الضروري فقط عدم نسيان قطع الأرقام الكبيرة nafig حتى لا تتدخل.

هيا بنا نبدأ. أولاً ، لنقم بإنشاء العداد الخاص بنا في مقطع البيانات:

LDS R16، CCNT LDS R17، CCNT + 1 LDS R18، CCNT + 2 LDS R19، CCNT + 3

كل شيء ، الآن في R16 هو أصغر بايت في عدادنا ، وفي R19 هو الأقدم.

يمكن دفع التسجيلات مسبقًا إلى المكدس ، لكنني سأقدم لك نصيحة أفضل - عند كتابة برنامج ، فكر في الخوارزمية بطريقة تستخدم السجلات باعتبارها TEMP مستمرًا تكون بياناته ذات صلة هنا والآن فقط. وما سيحدث لهم في الإجراء التالي لم يعد مهمًا - كل ما يجب تخزينه في ذاكرة الوصول العشوائي.

يمكنك القيام بذلك على النحو التالي:

LDI R20.1 ؛ نحتاج إلى CLR R15 واحدة ؛ وكذلك صفر. إضافة R16 ، R20 ؛ نضيف 1 إذا كان السجل 255 ، فسيكون C ADC R17 ، R15 ؛ أضف 0 + C ADC R18، R15 ؛ أضف 0 + С ADC R19 ، R15 ؛ أضف 0 + C.

كان علينا إنفاق سجلين إضافيين لتخزين ثوابت الإضافة. كل ذلك من حقيقة أن AVR غير قادر على إضافة سجلات برقم مباشر. لكنه يستطيع القراءة.

لقد أوضحت بالفعل أن R - (- 1) = R + 1 ، لكن لا أحد يمنعنا من ترتيب نفس الحيلة هنا - للقيام بالجمع من خلال الطرح.

1 2 3 4 SUBI R16 ، (- 1) SBCI R17 ، (- 1) SBCI R18 ، (- 1) SBCI R19 ، (- 1)

SUBI R16 ، (- 1) SBCI R17 ، (- 1) SBCI R18 ، (- 1) SBCI R19 ، (- 1)

سيعطينا زيادة في عدد أربعة بايت R19: R18: R17: R16

والآن سأريكم بعض سحر الأعداد الصحيحة.
لماذا ستعمل؟ الق نظرة بنفسك:

SUBI R16 ، (-1) هو ، في الواقع ، R16 - 255 وفي جميع الحالات تقريبًا سيمنحنا قرضًا من الفئة التالية - C. والرقم الذي سيظل به المزيد في السجل.

أولئك. انظر كيف تعمل هذه الرياضيات ، تذكر الرقم في أكواد إضافية. سأعرض مثالاً عشريًا مكونًا من أربعة أرقام. لدينا أربعة اختلافات فقط ، لا أكثر ولا أقل. الرقم السالب هو 0-1 صحيح؟ نعم.

1 ج 0000-1 = 9999 + ج

أولئك. نحن ، كما كان ، أخذنا 1 من 1 C 0000 المكون من خمسة أرقام ، لكن لدينا أربعة أرقام فقط! تلقيت رمزًا إضافيًا 9999 وعلامة قرض C (تشير إلى وجود قرض)

أولئك. في الرياضيات الصحيحة 9999 = -1 :) من السهل التحقق من -1 + 1 = 0 أليس كذلك؟

9999 + 1 = 1 C 0000 صحيح! :))) والرقم الأول الأكثر أهمية لم يتناسب مع السعة وذهب إلى علامة الحمل C ، والتي تشير أيضًا إلى تجاوز.

حسنًا ، لنأخذ الآن ونفعل R - (- 1). دع R = 4

1 C 0004-9999 = 0005 + C.

فأخذوها وجمعوها من خلال عملية الطرح. مجرد سحر ، أليس كذلك؟ ؛)

نكتة المجمع هي أن هذه مجرد أوامر وليست عقيدة وليست قاعدة. والأوامر التي تتضمن حسابات الإشارات يمكن استخدامها في أي مكان ، طالما أنها تعطي النتيجة التي نحتاجها!

هنا وهنا - العداد الخاص بنا غير موقّع أيضًا ، لكننا نستخدم ميزات حساب التفاضل والتكامل الموقع لأنه أكثر ملاءمة لنا.

لن تظهر علامة C فقط عندما نضع علامة فوق 255 (9999 في المثال العشري) ، فسيكون 255-255 = 0 وسيظهر Z فقط ، لكننا لسنا بحاجة إليه.

STS CCNT ، R16 STS CCNT + 1 ، R17 STS CCNT + 2 ، R18 STS CCNT + 3 ، R19

يمكن طي رمز الزيادة لثابت رباعي البايت في الذاكرة في ماكرو حتى لا يفسد الكود

؛ الرئيسي ================================================== = ======= الأساسي: SETB PORTD، 4 ؛ مضاءة LED1 INVB PORTD ، 7 ، R16 ، R17 ؛ LED3 المقلوب التالي: INCM CCNT JMP Main

ابدأ وضع التصحيح وضع نقطة توقف (F9) على التسمية الرئيسية وحرك المؤشر إلى نقطة الإيقاف الأولى.

0xB6 (CCNT) 0x9F (CCNT + 1) 0x04 (CCNT + 2) 0x00 (CCNT + 3)

يبقى الآن فقط مقارنة الرقم مع هذا الممثلين.

كيف تقارن؟ نعم ، الأمر بسيط جدًا. كل هذا يتوقف على ما نريد الحصول عليه. إذا كان هناك حدث واحد للفترة الكاملة للعداد العالمي الخاص بنا ، فحينئذٍ بغباء ، بايت بايت. في هذه الحالة ، سوف يومض الصمام الثنائي الخاص بك بعد ثانية من البداية ، ثم ستنتظر نصف ساعة حتى يفيض العداد الكامل المكون من أربعة بايت.

من أجل أن تومض كل ثانية ، تحتاج إلى إخفاء البتات العالية من العداد العام عند المقارنة ، كما لو كان عرضها قليلاً ليس 32 بتًا ، ولكن أقل (وتفيض في كثير من الأحيان).

تتم مقارنة البايتات الأقل كما هي ، والأقدم يصل إلى أقصى رقم له ، ويجب قطع الباقي.

أولئك. وأهم بت في هذه الحالة هو CCNT + 2 = 0x04 إذا كان التمثيل الثنائي هو 0x04 = 00000 100 إذن ، لدينا عداد مكون من أربعة أرقام ، وهو ما يعني حدثًا بقناع

00 04 9F B6 ( 00000000 00000 100 10011111 10110110)

قبل الفائض سيكون هناك عدد مرات dofiga. كما ترى ، قمت بتمييز الأصفار بالخط العريض. لن نقارن الأقدم على الإطلاق ، ولكن قبل الأقدم ، من الضروري الضغط على القناع و 00000111 لقطع البتات العالية.

لا يزال يتعين ملؤها قبل تجاوز وتصفير العداد. لكن إذا قمنا بإخفائهم ، فلن يزعجنا مصيرهم الإضافي. دعها تدق حتى المجيء الثاني ، نحن لا نهتم.

LDS R16 ، CCNT ؛ نقوم بتحميل الأرقام في السجلات LDS R17، CCNT + 1 LDS R18، CCNT + 2 ANDI R18،0x07 ؛ نفرض قناع CPI R16،0xB6 ؛ قارن البايت بالبايت BRNE NoMatch CPI R17.0x9F BRNE NoMatch CPI R18.0x04 BRNE NoMatch ؛ إذا كانت مطابقة ، فسنقوم بمطابقة الحركة: INVB PORTD، 7، R16، R17؛ LED3 مقلوب ؛ غير متطابق - لا تفعل ذلك :) NoMatch: التالي: INCM CCNT؛ تحول الجهاز البرميل JMP الرئيسي

في تحميل وامض الآن. لا توجد أي أخطاء ، ولا شيء معلق في أي مكان ، والدورة الرئيسية تطير من خلال صافرة ، فقط لديك الوقت لتشغيل الطبلة القوية :)

هذا مجرد وميض بشكل ملحوظ أبطأ مما أردنا. ليس ثانية واحدة ، ولكن 8. حسنًا ، ماذا كنت تريد - بإضافة إجراء المقارنة ، قمنا بإطالة الدورة بعدد قليل من الأوامر. والآن لا يتم إجراؤه لـ 25 دورة ، ولكن لـ 36. أعد حساب جميع الأرقام مرة أخرى :))))))

لكن هذا ليس معظم الوقت! النكتة هي أن لديك جزءًا من الكود قيد التشغيل ، والبعض الآخر لا يعمل - أوامر المقارنة والانتقال. لذلك ، من الأسهل حساب التأخير حسب الدورات بدقة - تحتاج إلى حساب لكل تكرار متى وعدد الانتقالات التي ستحصل عليها وعدد الدورات التي ستستغرقها ...

وإذا كان الرمز أكبر من ذلك ، فعندئذٍ في النهاية يتراكم الأنبوب والخطأ مع كل تكرار!

ولكن إذا قمت بإضافة رمز معالجة الزر:

؛ الرئيسي ================================================== = ======= الأساسي: SBIS PIND، 6 ؛ إذا تم الضغط على الزر - انتقال RJMP BT_Push SETB PORTD ، 5 ؛ تضيء LED2 CLRB PORTD ، 4 ؛ قم بإيقاف تشغيل LED1 التالي: LDS R16 ، CCNT ؛ تحميل الأرقام في السجلات LDS R17، CCNT + 1 LDS R18، CCNT + 2 ANDI R18.0x07 CPI R16.0xB6 ؛ قارن البايت بالبايت BRNE NoMatch CPI R17.0x9F BRNE NoMatch CPI R18.0x04 BRNE NoMatch ؛ إذا كانت مطابقة ، فسنقوم بمطابقة الحركة: INVB PORTD، 7، R16، R17؛ LED3 مقلوب ؛ غير متطابق - لا تفعل ذلك :) NoMatch: NOP INCM CCNT JMP Main BT_Push: SETB PORTD، 4؛ تضيء LED1 CLRB PORTD ، 5 ؛ قم بإيقاف تشغيل LED2 RJMP التالي ؛ نهاية الصفحة الرئيسية ================================================ = ====

ثم سنرى أنه لا توجد آثار متبقية للمكابح. تستجيب الأزرار على الفور للضغط ، ويومض المصباح من تلقاء نفسه. تعدد المهام! :)

بشكل عام ، فإن أداة Hurdy-gurdy ليست مناسبة عند الحاجة إلى حسابات دقيقة. ولكن إذا كانت المهمة من السلسلة "تحتاج إلى رعشة بشكل دوري ولا يهم مدى الدقة" ، فهذا كل شيء. لأن لا تأخذ موارد الأجهزة مثل جهاز ضبط الوقت.

على سبيل المثال ، قم بفحص لوحة المفاتيح بشكل دوري ، على سبيل المثال ، كل 2048 دورة من الحلقة الرئيسية. قدر نفسك ما هو الرقم الذي تريد تحميله للمقارنة وما هو القناع الذي يجب تطبيقه :)

يمكنك التنزيل وإلقاء نظرة ، وتتبعه لترى كيف يدور كل شيء.

ولحسابات الوقت الدقيقة ، هناك مؤقتات. لكن هناك مناقشة منفصلة حولهم.

  • الدورة التعليمية

تشغيل منافذ الإدخال / الإخراج

بعد دراسة هذه المادة ، التي يتم فيها وصف كل شيء بتفصيل كبير وبالتفصيل مع عدد كبير من الأمثلة ، يمكنك بسهولة إتقان وبرمجة منافذ الإدخال / الإخراج لوحدات التحكم الدقيقة AVR.

سيتم النظر في مثال على متحكم دقيق ATMega8 .

سنكتب البرنامج باللغة Atmel Studio 6.0.0 تحديث .

سنقوم بمحاكاة الدائرة في بروتيوس 7 بروفيشنال .

يتصل المتحكم الدقيق بالعالم الخارجي من خلال منافذ الإدخال / الإخراج. يشار إلى مخطط منفذ الإدخال / الإخراج في ورقة البيانات:

لكن من الصعب جدًا على المبتدئين فهم المخطط. لذلك دعونا نبسط الرسم التخطيطي:

يحتوي كل منفذ متحكم AVR (يُسمى عادةً A و B وأحيانًا C أو حتى D) على 8 بتات ، كل منها مرتبط بدبوس معين من الهيكل المعدني. كل منفذ له ثلاثة سجلات خاصة DDRx, بورتكسو بينكس(حيث x هو حرف المنفذ A أو B أو C أو D). الغرض من السجلات:

DDRx- اضبط بتات المنفذ x للإدخال أو الإخراج.

بورتكس- التحكم في حالة نواتج المنفذ x (إذا تم تكوين البت المقابل كمخرج) ، أو عن طريق توصيل مقاوم سحب داخلي (إذا تم تكوين البت المقابل كمدخل).

بينكس- قراءة مستويات البت المنطقية للمنفذ x.

بينينهو سجل القراءة. لا يمكن قراءتها إلا من. في التسجيل PINxnيحتوي على معلومات حول مستوى المنطق الحالي الفعلي على دبابيس المنفذ. بغض النظر عن إعدادات المنفذ. لذلك إذا أردنا معرفة ما لدينا في الإدخال ، نقرأ الجزء المقابل من السجل PINxn. علاوة على ذلك ، هناك حدين: حد الصفر المضمون وحدود واحد مضمون - العتبات التي يمكننا بعدها تحديد المستوى المنطقي الحالي بوضوح لا لبس فيه. بالنسبة للإمداد بخمسة فولت ، فهذه هي 1.4 و 1.8 فولت على التوالي. أي عندما ينخفض ​​الجهد من الحد الأقصى إلى الحد الأدنى ، فإن البتات في السجل بينكسسوف يتحول من 1 إلى 0 فقط عندما ينخفض ​​الجهد إلى أقل من 1.4 فولت ، ولكن عندما يرتفع الجهد من الحد الأدنى إلى الحد الأقصى ، سيتحول البت من 0 إلى 1 فقط عندما يصل الجهد إلى 1.8 فولت. أي أن هناك تباطؤ تبديل من 0 إلى 1 ، مما يلغي التبديل الفوضوي تحت تأثير التداخل والتداخل ، كما يلغي القراءة الخاطئة للمستوى المنطقي بين عتبات التبديل.

مع انخفاض جهد الإمداد ، بالطبع ، تنخفض هذه العتبات أيضًا.

DDRxnهو سجل اتجاه الميناء. يمكن أن يكون المنفذ في وقت معين إما إدخالًا أو مخرجًا (ولكن بالنسبة لحالة بتات PINxn ، لا يهم هذا. قراءة من PINxnالقيمة الحقيقية ممكنة دائمًا).

DDRxy= 0 - الناتج يعمل كمدخل.

DDRxy= 1 - الناتج يعمل كمخرج.

بورتكسن- وضع التحكم في حالة الإخراج. عندما نضبط الإخراج على الإدخال ، ثم من بورتكسيعتمد نوع الإدخال (Hi-Z أو PullUp ، والمزيد على ذلك أدناه).

عندما يتم ضبط الدبوس على الإخراج ، فإن قيمة البت المقابل في السجل بورتكسيحدد حالة الإخراج. إذا بورتكسن= 1 ثم الناتج هو log.1 ، إذا بورتكسن= 0 ثم الناتج هو log.0.

عندما يتم تكوين الساق للإدخال ، ثم إذا بورتكسن= 0 ، ثم يكون الإخراج في وضع Hi-Z. إذا بورتكسن\ u003d 1 ثم يكون الإخراج في وضع PullUp بمقاومة سحب تصل إلى 100 كيلو بايت للطاقة.

جدول. تكوين دبوس المنفذ.

DDRxn PORTxn I / O تعليق
0 0 I (إدخال) إدخال مدخلات مقاومة عالية. (لا أوصي باستخدامه ، حيث قد يحدث تداخل من مصدر الطاقة)
0 1 I (إدخال) تم سحب المقاومة الداخلية للأعلى.
1 0 O (Output) Output الناتج منخفض.
1 1 O (Output) Output الناتج مرتفع.

تظهر الصورة العامة لتشغيل الميناء في الأشكال:

أرز. DDRxn=0 بورتكسن= 0 - الوضع: مرحبا زي- مدخلات مقاومة عالية.

أرز. DDRxn=0 بورتكسن= 1 - الوضع: اسحب- الإدخال مع سحب إلى السجل 1.

أرز. DDRxn=1 بورتكسن= 0 - الوضع: انتاج |- إخراج سجل .0. (تقريبا GND)

أرز. DDRxn=1 بورتكسن= 1 - الوضع: انتاج |- في سجل الإخراج 1. (تقريبا VCC)

مدخل مرحبا- Z- وضع الإدخال عالي المقاومة.
يتم تمكين هذا الوضع افتراضيًا. جميع المفاتيح مفتوحة ومقاومة المنفذ عالية جدًا. من حيث المبدأ ، بالمقارنة مع الأنماط الأخرى ، يمكن اعتباره لا نهاية. أي ، كهربائيًا ، الناتج ، كما كان ، غير متصل في أي مكان على الإطلاق ولا يؤثر على أي شيء. ولكن! في الوقت نفسه ، يقرأ باستمرار حالته في السجل بينويمكننا دائمًا اكتشاف ما لدينا عند الإدخال - واحد أو صفر. هذا الوضع جيد للاستماع إلى أي ناقل بيانات ، لأن. ليس له تأثير على الحافلة. ماذا يحدث إذا كان المدخل في الهواء؟ وفي هذه الحالة ، سيقفز الجهد عليه اعتمادًا على التقاطات الخارجية ، والتداخل الكهرومغناطيسي ، وبشكل عام ، على مرحلة القمر والطقس على المريخ (طريقة مثالية لتقطيع الأرقام العشوائية!). في كثير من الأحيان ، في هذه الحالة ، يكون الجيب غير المستقر 50 هرتز على المنفذ عبارة عن التقاط من شبكة 220 فولت وفي السجل بينسيتغير 0 و 1 بتردد حوالي 50 هرتز

مدخل اسحب- دخول سحب.
في DDRxn= 0 و بورتكسن= 1 ، يتم إغلاق مفتاح السحب ويتم توصيل المقاوم 100 kΩ بالخط ، مما يؤدي على الفور إلى توصيل الخط غير المتصل في أي مكان بحالة السجل. الغرض من السحب واضح - لمنع التغيير الفوضوي في الحالة عند المدخلات تحت تأثير التقاطات. ولكن إذا ظهر صفر منطقي عند الإدخال (تم إغلاق الخط على الأرض بواسطة زر أو متحكم / دائرة دقيقة أخرى) ، فلن يتمكن المقاوم الضعيف 100kΩ من الحفاظ على الجهد على الخط عند مستوى السجل 1 و سيكون الإدخال log.0.

وضع الخروج.
هنا ، أعتقد أن كل شيء واضح - إذا احتجنا إلى إصدار السجل 1 إلى المنفذ ، فإننا نقوم بتشغيل منفذ الإخراج ( DDRxn= 1) وسجل الإخراج 1 ( بورتكسن\ u003d 1) - في نفس الوقت ، يتم إغلاق المفتاح العلوي ويظهر جهد قريب من الطاقة في الإخراج. وإذا كنت بحاجة إلى log.0 ، فقم بتشغيل منفذ الإخراج ( DDRxn= 1) وسجل الإخراج 0 ( بورتكسن\ u003d 1) - في نفس الوقت ، يفتح الصمام السفلي ، والذي يعطي حوالي صفر فولت عند الخرج.