كود تفعيل العضوية - الابلاغ عن روابط لاتعمل - صيانة التلفزيون - الحاسبة - الأعضاء المتميزين - البرامج و المخططات - بث مباشر للقنوات الفضائية - إذاعة - تردد القنوات - بحث
|
التسجيل | اجعل كافة المشاركات مقروءة |
منتدى الإلكترونيات قسم الالكترونكس لمناقشة الافكار والمعلومات المتعلقة بالهندسة الالكترونية للمبتدئين والهواة والفنيين - Electronics |
![]() |
|
أدوات الموضوع |
![]() |
#1 |
استاذ و مشرف قسم الالكترونيات
المشاركات: 6,894
معدل تقييم المستوى: 333
|
![]() الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
1- مقدمة عن الناقل 2IC : الناقل I2C (اختصار Inter-Integrated Circuit ) هو ناقل شائع الاستخدام ، وهو ناقل اتصال متزامن ( أى يوجد نبضات ساعة تزامن) يستخدم خطين (سلكين) : • الخط SDA (اختصار Serial Data Line ) : هو خط بيانات ثنائى الاتجاه . • الخط SCL (اختصار Serial Clock Line ) : هو خط ساعة التزامن ثنائى الاتجاه . ![]() يتم التحكم فى الناقل I2C عن طريق الماستر (السيد) master ( غالبا ما يكون ميكروكونترولر مثل PIC16F877A ) . قد يكون للناقل I2C أكثر من ماستر ، لكننا سوف نتناول حالة وجود ماستر واحد فقط على متن الناقل يتحكم فيه. الناقل I2C قد يكون له تابع (خادم) slave واحد أو أكثر (الناقل I2C بدون توابع لاقيمة له ) . يتم التعرف على التابع slave عن طريق عنوان متفرد يكون فى أغلب الأحيان مكون من 7 بتات 7-bit address . مثال : ساعة التوقيت الحقيقى DS1307 : Address 7 bits (1 1 0 1 0 0 0) . ملحوظة : لا يمكن أبدا أن يكون لتابعين نفس العنوان . كما أن الماستر ليس له عنوان على الإطلاق . المحادثة (التخاطب ) أى الاتصال تتم فقط بين الماستر وتابع . دائما يتم بدء الحادثة عن طريق الماستر وبإطلاقه لحالة البدء (Start condition) . فى الميكروسى برو تستخدم الدالة I2C1_Start(); لتحقيق هذا الغرض . ثم يقوم الماستر باستخدام الناقل I2C لإرسال عنوان تعريف التابع الذى يرغب فى التواصل معه . فى الميكروسى برو تستخدم الدالة I2C1_Write(0xD0); لتحقيق هذا الغرض . دائما يتم إنهاء الاتصال عن طريق الماستر وذلك بإصدارة حالة التوقف (Stop condition) . فى الميكروسى برو تستخدم الدالة I2C1_Stop(); لتحقيق هذا الغرض . يتم توليد إشارة الساعة SCL بواسطة الماستر ، والوضع القياسى لها ، وهو ما سوف نستخدمه ،هو 100 kHz (100 kilobits per second) . فى الميكروسى برو تستخدم الدالة I2C1_Init(100000); لتحقيق هذا الغرض . هذه الدالة يجب أن تكتب فى بداية البرنامج حتى يمكن استخدام باقى دوال الناقل I2C الأخرى . تنتقل البيانات من المرسل إلى المستقبل . ومن ثم يكون لدينا حالتين : • انتقال البيانات من الماستر إلى التابع : فى هذه الحالة يكون المرسل هو الماستر والمستقبل هو التابع .يتم انتقال البيانات على الخط SDA على مسافات مع تزامن الماستر من خلال خط الساعة SCL clock . • انتقال البيانات من التابع إلى الماستر : فى هذه الحالة يكون المرسل هو التابع لمستقبل هو الماستر . يضع التابع البيانات على الخط SDA على مسافات مع تزامن الماستر من خلال خط الساعة SCL clock . ملاحظة : توفر الأجهزة بت الاعتراف والتسليم بالصحة Acknowledge bit لتحقيق انتقال بيانات سلس . 2- تقنية الناقل I2C من نوع خرج مفتوح المصب أو المجمع المفتوح : مخارج الدوائر التى يتم ربطها إلى الناقل I2C هى من نوع المصب المفتوح أو المجمع المفتوح ، لذلك يتم وضع مقاومتين رفع الخطين SDA و SCL ومصدر القدرة الموجب VDD . 3- مثال للاتصال بين الماستر (PIC16F877A) والتابع (DS1307) : ساعة التوقيت الحقيقى DS1307 توفر لبثوانى ،والدقائق،والساعات ، والأيام،والتاريخ ،والشهور،والسنين مع الأخذ فى الاعتبار السنين الكبيسة ، حتى عام 2100 . الساعة DS1307 تعمل فى الوضع القياسى ( تردد نبضات خط الساعة SCL هو 100 كيلوهرتز ) . عنوان ناقل I2C ذات السبع بتات والخاص بالساعة DS1307 هو 1 1 0 1 0 0 0 ( العنوان المحدد بمعرفة الصناع ولا يمكن تغييره ) . مثال للكتابة إلى الساعة DS1307 : المرسل هو الماستر والمستقبل هة التابع . السجل الذى عنوانه 0x04 فى الساعة DS1307 يحتوى على تاريخ اليوم DATE (راجع الداتا شيت ) . الشكل التالى يوضح ذلك . ![]() لضبط تاريخ اليوم من الشهر ليكون يوم 27 ، يجب عليك كتابة البيانات 0x27 ( شفرة ثنائية مكودة عشرى BCD ) فى السجل الذى عنوانه 0x04 بالساعة DS1307 . الناقل I2C يستخدم البروتوكول التالى : ![]() 1- لبدء الاتصال ، يقوم الماستر بإنشاء حالة البدء START . 2- ثم يقوم الماستر بإرسال عنوان التابع وهو(1010100) متبوعا بالبت (0) (بت الكتابة ) ليكون البايت 0xD0 . 3- يستجيب التابع ويرد ببت معلومية وتمام وصول وتنفيذ الأمر . 4- عندئذ يقوم الماستر بإرسال عنوان السجل المطلوب الكتابة إليه وهو (0x04) . 5- يستجيب التابع ويرد ببت معلومية وتمام وصول وتنفيذ الأمر . 6- عندئذ يقوم الماستر بإرسال البيانات المطلوب كتابتها إلى السجل ،ذات العنوان سالف الذكر ، وهى بيانات تاريخ اليوم (0x27) . 7- يقوم التابع بكتابة البيانات وبعد ذلك يرسل بت تمام التنفيذ . 8- فى النهاية ، يقوم الماستر بإنهاء الاتصال بإصدار حالة التوقف STOP . أليست سهلة ؟ يمكن تنفيذ ذلك بلغة السى والمترجم ميكروسى برو كما يلى : كود:
I2C1_Init(100000); // initialize I2C communication //////////////////////////// I2C1_Start(); //1- issue I2C start signal I2C1_Wr(0xD0); // 2-3-send byte via I2C (device address + W) I2C1_Wr(0x04); // 4-5-send byte (address of DATE location) I2C1_Wr(0x27); // 6-7send data (data to be written) I2C1_Stop(); //8- issue I2C stop signal ![]() مثال على القراءة من الساعة DS1307 : فى هذه الحالة يكون المرسل هو التابع والمستقبل هو الماستر . السجلات ذات العناوين من 0x00 إلى 0x06 بالساعة تحتوى على الترتيب على بيانات : الثوانى ، والدقائق ، والساعات ، والأيام (يوم الأسبوع) ، والتواريخ (يوم الشهر) ، والأشهر ، والسنين (راجع الداتا شيت) . هنا سوف نتعرف على كيفية قراءة محتويات العناوين من 0x00 إلى 0x06 للساعة DS1307 ، ودفعة واحدة : ![]() 1- لبدء الاتصال ، يقوم الماستر بإنشاء حالة بدء START . 2- يقوم الماستر بإرسال عنوان التابع (1010100) متبوعا بالبت (0) ، (بت الكتابة) . 3- يجيب التابع ببت المعلومية . 4- يرسل الماستر عنوان السجل المطلوب قراءته (0x00) . 5- يجيب التابع بالمعلومية . 6- يعطى الماستر حالة إعادة البدء Repeated Start . 7- يرسل الماستر عنوان التابع (1010100) متبوعا بالبت (1) (بت القراءة) . 8- يجيب التابع بالمعلومية . 9- يرسل التابع محتويات السجل الذى عنوانه 0x00 إلى الماستر . 10- يجيب الماستر بالمعلومية . 11- يرسل التابع محتويات السجل الذى عنوانه 0x01 (يتزايد تلقائيا) إلى الماستر . 12- يجيب الماستر بالمعلومية . 13- يرسل التابع محتويات السجل الذى عنوانه 0x02 (يتزايد تلقائيا) إلى الماستر . 14- يجيب الماستر بالمعلومية . ......................................... .................................................. ..... 21- يرسل التابع محتويات السجل الذى عنوانه 0x06 (يتزايد تلقائيا) إلى الماستر . 22- يجيب الماستر بالمعلومية . 23- يقوم الماستر بإنهاء الاتصال بإصدار حالة التوقف STOP . فعلى فرض أن محتويات السجل 0x00 هى 0x06 فهذا يعنى 6 ثوانى . وعلى فرض أن محتويات السجل 0x01 هى 0x56 فهذا يعنى 56 دقيقة . وعلى فرض أن محتويات السجل 0x02 هى 0x09 فهذا يعنى 9 ساعات . وعلى فرض أن محتويات السجل 0x03 هى 0x03 فهذا يعنى اليوم الثالث من أيام الإسبوع أى Tuesday . وعلى فرض أن محتويات السجل 0x04 هى 0x20 فهذا يعنى اليوم العشرين من الشهر . وعلى فرض أن محتويات السجل 0x05 هى 0x05 فهذا يعنى شهر May . وعلى فرض أن محتويات السجل 0x06 هى 0x08 فهذا يعنى عام 2008 . ويكون التوقيت والتاريخ : (Tuesday, May 20, 2008, 9 hours 56 minutes and 6 seconds) كود:
I2C1_Init(100000); // initialize I2C communication //////////////////////////// I2C1_Start(); //1- issue I2C start signal I2C1_Wr(0xD0); // 2-send byte via I2C (device address + W) I2C1_Wr(00); //3- send byte (data address) I2C1_Repeated_Start(); // 6-issue I2C signal repeated start I2C1_Wr(0xD1); // 7-send byte (device address + R) PORTB = I2C1_Rd(0u); // 9-Read the data (NO acknowledge) I2C1_Stop(); //23- issue I2C stop signal تنفيذ الكود السابق فى شكل برنامج : كود:
void main() { TRISB=0; I2C1_Init(100000); // initialize I2C communication //////////////////////////// while(1){ I2C1_Start(); //1- issue I2C start signal I2C1_Wr(0xD0); // 2-send byte via I2C (device address + W) I2C1_Wr(00); //3- send byte (data address) I2C1_Repeated_Start(); // 6-issue I2C signal repeated start I2C1_Wr(0xD1); // 7-send byte (device address + R) PORTB = I2C1_Rd(0u); // 9-Read the data (NO acknowledge) I2C1_Stop(); } } ![]()
__________________
مقالات المهندس فتح الله عبدالعزيز |
![]() |
![]() |
اعلانات |
![]() |
#2 |
استاذ و مشرف قسم الالكترونيات
المشاركات: 6,894
معدل تقييم المستوى: 333
|
![]() ساعة التوقيت الحقيقى DS1307 وربطها مع الميكروكونترولر PIC بغرض إنشاء ساعة رقمية :
العديد من الميكروكونترولر PIC يمتلك ضمن بنائه الداخلى ناقل I ![]() بعض الأجهزة ، مثل الحساسات ، تتصل بالميكروكونترولر باستخدام هذا الناقل التسلسلى . العديد من الأجهزة ، حتى وإن كانت من أنواع مختلفة ، يمكن ربطها على نفس خطى الناقل 2IC دون أن تسبب أى خطأ . كل جهاز يمتلك عنوان تعريف متفرد وهو ما يسمح بربط العديد من الأجهزة إلى نفس الناقل I2C . سوف نستخدم ساعة التوقيت الحقيقى DS1307 والتى يمكنها الاتصال خلال الناقل I2C لضبط set (write) التوقيت والتاريخ وكذلك القراءة منها . الدائرة المتكاملة DS1307 هى ساعة توقيت وتقويم تسلسلية ذو قدرة كهربية منخفضة وتعمل بالكامل بنظام الأعداد الثنائى المكود عشرى BCD لكل من بياات التوقيت والتقويم ، بالإضافة إلى أنها تمتلك 56 بايت من ذاكرة RAM الغير متطايرة نتيجة لاستخدام بطارية احتياطية للقدرة الكهربية . يتم نقل البيانات والعنوان تسلسليا من خلال ناقل 2IC ثنائى الاتجاه وهى توفر معلومات التوقيت (الثوانى والدقائق والساعات) والتقويم ( واليوم والشهر والسنة) ، يتم تعديل بيانات تاريخ نهاية الأشهر تلقائيا للشهر الأقل من 31 يوما بما في ذلك تعويض السنة الكبيسة حتى عام 2100 ، ويمكن أن تعمل إما في شكل 24 ساعة أو فى شكل 12 ساعة مع بيان AM/PM . وهى تأتي مع دائرة مدمجة لاستشعار انقطاع التيار الكهربائي والتحويل تلقائيا إلى المصدر الاحتياطي . وتستمر عملية ضبط الوقت أثناء العمل على المصدر الاحتياطى . كما أنها تستخدم مذبذب كريستال بتردد 32.768kHz ولا تحتاج أى مقاومات أو مكثفات خارجية للعمل . الساعة DS1307 تعمل كجهاز تابع slave على الناقل I2C . يتم الوصول إليها بواسطة تنفيذ الأمر SRART مع تقديم كود تعريف الجهاز يليه عنوان سجل . بعد ذلك يمكن الوصول إلى السجلات المتتابعة حتى يتم تنفيذ أمر STOP . توصيل ناقل I2C : ![]() يتم توصيل الطرف SCL للميكروكونترولر بالطرف 6 : DS1307/ SCL وتوصيل الطرف SDA للميكروكونترولر بالطرف 5 : DS1307/ SDA يتم توصيل مقاومتى رفع ، واحدة من "خط الساعة التسلسلية" SCL والأخرى من "خط البيانات التسلسلية" SDL إلى موجب مصدر القدرة . كما يتم توصيل كريستال 32768 إلى الطرف 1 والطرف 2 للساعة DS1307 . يمكن أيضا توصيل بطارية احتياطية إلى الطرف VBAT (pin 3) ، إذا لم ترغب فى ذلك يتم توصيل هذا الطرف إلى الأرضى . يوفر المترجم ميكروسى برو مكتبة مدمجة به خاصة بأجهزة I2C . الساعة DS1307 تعمل كجهاز تابع على الناقل I2C . الوصول إلى سجلات الساعة DS1307 يمكن أن نحصل عليه بواسطة تنفيذ (استدعاء)الدالة START ونتبعها بعنوان address تعريف هوية الجهاز . بعد ذلك يمكن الوصول لكل سجل على التتابع عن طريق استخدام عنوانه حتى يتم تنفيذ الدالة STOP . عنوان الجهاز الخاص بالساعة DS1307 هو 0x68 = 1101000 (صفحة 12 من الداتا شيت ) . هناك وظيفتان شائعتان الاستخدام مع الجهاز : وظيفة تحديد القيم بالذاكرة set values (كتابة البيانات إلى الساعة DS1307 ) ووظيفة الحصول على القيم من الذاكرة get values ( قراءة البيانات من الساعة ds1307 ) سوف نستعرض الوظيفتين باستخدام الأمثلة . القيم الرقمية فى هذا الجهاز يتم تخزينها على شكل 4 بتات ، بصيغة كود ثنائى مكود عشرى BCD . سوف نحتاج للتحويل من BCD إلى ثنائى BINARY ومن ثنائى إلى BCD حتى يتم عرض وتخزين القيم فى الميكروكونترولر PIC بشكل مناسب . ![]() عملية إرسال أو كتابة البيانات للساعة Set RTC Values (ضبط الساعة): فى البداية يتم برمجة الدائرة المتكاملة بالقيم الصحيحة للتوقيت والتقويم . فى المثال التالى ، سوف نقوم بتحديد (ضبط) الدقائق . وبمجرد ضبطها فإن جميع السجلات الأخرى (ساعة، يوم ...) يمكن ضبطها باستخدام نفس الخطوات . مثال على ضبط الدقائق Setting the Minutes : فيما يلى توقيت وتتابع الاتصال عن طريق الناقل I2C : كود:
I2C1_Init(100000); //DS1307 I2C is running at 100KHz /////////////////////////// I2C1_Start(); // begin I2C communications I2C1_Wr(0xD0); // addresses the chip I2C1_Wr( 0x01 ); // access register address for minutes check table 2 above. I2C1_Wr(0b00010011 ); // write value into minutes register I2C1_Stop(); /////////////////// 1- أول شىء نقوم بعمله هو بدء الاتصال عن طريق استخدام الدالة I2C1_Start() . 2- بعد ذلك نستدعى الدالة I2C1_Wr(0xD0) : هذه هى الدالة التى عن طريقها يتم الوصول جهاز تابع محدد عن طريق شفرة تعريف عنوانه الموجودة فى السبع بتات الأعلى لبارامتر هذه الدالة ، وهى هنا 1101000 . فنظرا لأنه يمكن ربط العديد من الأجهزة على نفس الناقل I2C ، فإن هذا العنوان "يوقظ" الجهاز الصحيح . وتتابعات البيانات التالية سوف تقوم فقط بالنظر فى هذا الجهاز فقط من ضمن الأجهزة الموجودة على متن نفس الناقل . عنوان أي جهاز على الناقل I2C عادة (وليس دائما) يتكون من جزئين . الجزء الأول عبارة عن مجموعة من البتات للعنوان الداخلى . ويتكون الجزء الثاني من بتات استخدام أطراف الدائرة المتكاملة ، لكن الساعة DS1307 تمتلك عنوانها بالكامل فى داخل الشريحة . وفقا للداتا شيت ، عنوان ذات الساعة ذات سبع بتات وهو‘1101000’ . فأين البت الثامنة ؟ بعد كل بايت عنوان يتم إرسالة بمعرفة الميكروكونترولر PIC مستخدما الناقل I2C ، فإن البت الثامنة تحدد ما إذا كانت البايت التالية تكون كتابة أو قراءة بمعرفة PIC : فإذا كانت البت الثامنة صفر (0) فهذا يعنى أن البايت التالى مخصص للكتابة أما إذا كانت واحد فهذا يعنى أن البايت التالى مخصص للقراءة . هنا البت ذات الأهمية الأدنى (البت الثامن ) هى الصفر ، لذلك فإن بيانات البايت الكامل سوف تكون ‘11010000 0xD0 . 3- بعد ذلك يتم استدعاء الدالة ة I2C1_Wr(0x01) : فوفقا للجدول أعلاه ، كل سجل من سجلات الساعة DS1307 يكون له عنوان address بقيمة سداسى عشرى سجل مرتبط به . فعلى سبيل المثال ، سجل الدقائق MINUTES register يكون عنوانه 01h (or 0x01) . ولذلك ، للوصول إلى هذا السجل ، فإن PIC يكتب(يرسل) 0x01. الخلاصة الدالة تقوم بتحديد عنوان السجل المراد الكتابة إليه . 4- بعد ذلك يتم استدعاء الدالة I2C1_Wr(0b00010011) أو بالصيغة I2C1_Wr(0x13): مرة أخرى وفقا للجدول أعلاة ، سجل الدقائق MINUTES register مكون من جزئين : النبل الأدنى ( من البت bit0 إلى البت bit3 أى أربعة بتات ) والنبل العلوى ( البت bit4 إلى البت bit6 أى ثلاثة بتات ) . وكلا النبلين تستخدم معا لتمثيل أعداد برقمين double-digit numbers . على سبيل المثال ، العدد “13” مكون من رقم الآحاد “3” ورقم العشرات “1” . كل رقم يتم تخزينه فى نبل مستقل . الرقم “1” يتم تخزينه كعدد ثنائى مكود عشرى فى النبل العلوى فى حين أن العدد “3” يتم تخزينه كعدد BCD فى النبل السفلى . على سبيل المثال ، لتخزين العدد “13” ، يجب ضبط سجل الدقائق MINUTES بالشكل ‘001 0011’ بالصيغة الثنائية . الثنائى “001” هو “1” بالشكل BCD والثنائى “0011” هو "3" بالشكل BCD . ونظرا لأنه لا يوجد دقائق ثنائية الأرقام أعلى من “59” فإننا نحتاج فقط إلى 7 بتات لتمثيل أى عدد مكون من رقمين من 00 إلى 59 . 5- بعد ذلك يتم استدعاء الدالة I2C1_Stop() : بعد القيام بعمل كل شىء يمكننا غلق الناقل I2C بواسطة هذه الدالة . لقد كتبنا الرقم الثنائي 0010011 في سجل الدقائق ، يمكننا أن نكرر نفس الإجراء أو كتابة الدالة التي يمكن أن تستدعى ضبط الساعات للليوم والشهر وهلم جرا. الآن، فإن ساعة التوقيت الحقيقى سوف تتبع مسار الدقائق وبعد 59min:59sec فإن ساعة التوقيت الحقيقى سوف تقوم بتزايد سجل الساعات HOURS register ويتم الدوران 00min:00secs . أطراف الساعة الرقمية DS1307 : الساعة الرقمية DS1307 لها ثمانى أطراف كما يلى : ![]() وصف الأطراف : • الطرف SQW/OUT : طرف الموجة المربعة / وتشغيل الخرج . • الطرف SCL : طرف الساعة التسلسلية المستخدمة من أجل الاتصال IC2 . • الطرف SDA : طرف البيانات التسلسلية من أجل الاتصال التسلسلى I2C . • الطرف GND : طرف أرضى مصدر القدرة . • الطرف VBAT : طرف توصيل البطارية الاحتياطية 3V ، وتستخدم فى حالة انهيار القدرة الرئيسية . • الأطراف X1 , X2 : أطراف توصيل الكريستال 32.768 . • الطرف Vcc : طرف توصيل موجب مصدر القدرة الرئيسى . ربط الساعة الرقمية DS1307 مع الميكروكونترولر : الشكل التالى يبين المخطط الصندوقى العام لربط الساعة الرقمية مع الميكروكونترولر: ![]() في الاتصال التسلسلي I2C ، يعمل أحد الأجهزة باعتبار تابع slave ويعمل الجهاز الأخر باعتبارة السيد master . الجهاز التابع يستجيب فقط لتعليمات الجهاز السيد . الجهاز التابع لا يمكنه أن يعطي تعليمات للجهاز السيد . الساعة الرقمية DS1307 تعمل باعتبارها تابع slave وتستجيب لتعليمات الميكروكونترولر . السجلات المبنية ضمن الساعة الرقمية DS1307 تستخدم للاستجابة (الرد على ) لتعليمات الميكروكونترولر . كما هو مبين في المخطط أعلاه ، يتم توصيل الطرف SCL بالساعة DS1307 إلى الطرف SCL بالميكروكونترولر. يستخدم هذا الطرف (طرف الساعة التسلسلية) لمزامنة البيانات التسلسلية على الخط التسلسلي . كلمة SCL تعنى مدخل الساعة التسلسلية . فى حين أن الكلمة SDA تعنى طرف مدخل/مخرج البيانات التسلسلية . يتم توصيل الطرف SDA بالساعة DS1307 مع الطرف SDA بالميكروكونترولر. يستخدم الطرف SDA كمدخل للبيانات التسلسلية أو كمخرج من أجل الاتصال التسلسلى بخطين . الأطراف SDA و SCL بالساعة DS1307 هى أطراف مصب مفتوح وهذا هو سبب الاحتياج لمقاومة رفع خارجية كما هو مبين بالشكل أعلاه . يستخدم كريستال عيارى32.876KHz مع ساعة الوقت الحقيقى DS1307 .
__________________
مقالات المهندس فتح الله عبدالعزيز |
![]() |
![]() |
احصائية الشكر والاعجاب - 1 شكراً, 0 عدم اعجاب, 1 اعجاب |
![]() ![]() |
|
اعلانات اضافية ( قم بتسجيل الدخول لاخفائها ) | |||
|
![]() |
#3 |
مشرف منتدى الهندسة الكهربائية
الدولة: IRAQ
المشاركات: 10,061
معدل تقييم المستوى: 394
|
![]() شكرا جزيلا ....
__________________
حيدر علاج حسن
|
![]() |
![]() |
احصائية الشكر والاعجاب - 1 شكراً, 0 عدم اعجاب, 0 اعجاب |
![]() |
|
![]() |
#4 |
استاذ و مشرف قسم الالكترونيات
المشاركات: 6,894
معدل تقييم المستوى: 333
|
![]() المشروع التمهيدى لساعة التوقيت الحقيقى DS1307 :
الغرض استعراض : • كيفية التعامل مع دوال مكتبة المترجم ميكروسى . • كيفية قراءة سجلات التوقيت والتقويم من DS1307 عن طريق الميكروكونترولر . • كيفية تحويل القراءة من BCD إلى أحرف يمكن عرضه على وحدة LCD . الدائرة الكهربية : ![]() البرنامج : كود:
/* * Interfacing DS1307 RTC */ // LCD module connections sbit LCD_RS at RB2_bit; sbit LCD_EN at RB3_bit; sbit LCD_D4 at RB4_bit; sbit LCD_D5 at RB5_bit; sbit LCD_D6 at RB6_bit; sbit LCD_D7 at RB7_bit; sbit LCD_RS_Direction at TRISB2_bit; sbit LCD_EN_Direction at TRISB3_bit; sbit LCD_D4_Direction at TRISB4_bit; sbit LCD_D5_Direction at TRISB5_bit; sbit LCD_D6_Direction at TRISB6_bit; sbit LCD_D7_Direction at TRISB7_bit; // End LCD module connections unsigned short read_ds1307(unsigned short address) { unsigned short read_data; I2C1_Start(); I2C1_Wr(0xD0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0 I2C1_Wr(address); I2C1_Repeated_Start(); I2C1_Wr(0xD1); //0x68 followed by 1 --> 0xD1 read_data=I2C1_Rd(0); I2C1_Stop(); return(read_data); } //////////// unsigned char MSB(unsigned char x) //Display Most Significant Bit of BCD number { return ((x >> 4) + '0'); } //////// unsigned char LSB(unsigned char x) //Display Least Significant Bit of BCD number { return ((x & 0x0F) + '0'); } ///////////////////////////////// void init(){ ADCON1=0; CMCON=7; TRISC=0;// //////////// I2C1_Init(100000); //DS1307 I2C is running at 100KHz Lcd_Init(); // Initialize LCD Lcd_Cmd(_LCD_CLEAR); // Clear LCD display Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off Lcd_out(1,1,"Time:"); Lcd_out(2,1,"Date:"); } /////////////////////////////////////////// //Global Variables: int second; int minute; int hour; int hr; int day; int dday; int month; int year; int ap; ///////////////////////// char time[] = "00:00:00 PM"; char date[] = "00-00-00"; //////////////////////////////// void main() { init(); /////////// while(1) { second = read_ds1307(0);//sec minute = read_ds1307(1);//min register hour = read_ds1307(2);//hr register hr = hour & 0b00011111; ap = hour & 0b00100000; dday = read_ds1307(3);//day register day = read_ds1307(4);// month = read_ds1307(5);// month register year = read_ds1307(6);//year month register //////////////////////////////////// time[0] = MSB(hr);// char time[] = "00:00:00 PM"; time[1] = LSB(hr); time[3] = MSB(minute); time[4] = LSB(minute); time[6] = MSB(second); time[7] = LSB(second); ////////////////////////////////// date[0] = MSB(day);// char date[] = "00-00-00"; date[1] = LSB(day); date[3] = MSB(month); date[4] = LSB(month); date[6] = MSB(year); date[7] = LSB(year); if(ap) { time[9] = 'P'; //);// char time[] = "00:00:00 PM"; time[10] = 'M'; } else { time[9] = 'A'; time[10] = 'M'; } Lcd_out(1, 6, time); Lcd_out(2, 6, date); Delay_ms(100); } } شرح أجزاء البرنامج :
__________________
مقالات المهندس فتح الله عبدالعزيز |
![]() |
![]() |
![]() |
#5 |
استاذ و مشرف قسم الالكترونيات
المشاركات: 6,894
معدل تقييم المستوى: 333
|
![]() شرح أجزاء البرنامج :
1- أعدادات توصيل وحدة العرض LCD : كود:
// LCD module connections sbit LCD_RS at RB2_bit; sbit LCD_EN at RB3_bit; sbit LCD_D4 at RB4_bit; sbit LCD_D5 at RB5_bit; sbit LCD_D6 at RB6_bit; sbit LCD_D7 at RB7_bit; sbit LCD_RS_Direction at TRISB2_bit; sbit LCD_EN_Direction at TRISB3_bit; sbit LCD_D4_Direction at TRISB4_bit; sbit LCD_D5_Direction at TRISB5_bit; sbit LCD_D6_Direction at TRISB6_bit; sbit LCD_D7_Direction at TRISB7_bit; // End LCD module connections كود:
unsigned short read_ds1307(unsigned short address) { unsigned short read_data; I2C1_Start(); I2C1_Wr(0xD0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0 I2C1_Wr(address); I2C1_Repeated_Start(); I2C1_Wr(0xD1); //0x68 followed by 1 --> 0xD1 read_data=I2C1_Rd(0); I2C1_Stop(); return(read_data); } • الدالة التالية مباشرة هى دالة كتابة (أرسال) بايت عبر الناقل وهى I2C1_Wr(0xD0); . هذه الدالة تنبه الجهاز الذى عنوان تعريفه هو السبع بتات الأخيرة من البايت D0 وهو على وجه التحديد الجهاز DS1307 ، البت الأولى من اليمين تحدد نوع العملية القادمة ليتأهر لها الجهاز ، فإن كانت البت بصف فإن العملية القادمة تكون عملية كتابة (إرسال من الميكروكونترولر إلى DS1307 ) ، كما هو الحال فى هذه الحالة ، وإن كانت البت بواحد فهذا يعنى أن العملية القادمة هى عملية قراءة (الحصول على بيانات بايت من DS1307 إلى PIC ) . • كما توقعنا الدالة التالية هى دالة كتابة I2C1_Wr(address); وهى تحتاج لتحديد عنوان البايت المراد الكتابة عليه وهو البارامتر الموجود فى نموذج الدالة address . بهذه الطريقة نكون حددنا عنوان لبايت ، ونظرا لأننا بصدد دالة قراءة سجلات DS1307 نتوقع أن تكون الدالة التالية هى دالة قراءة ، ولكننا كنا قد نبهنا الجهاز بدالة كتابة لذلك ينبغى إعادة تنبيهه على أن القادم هى عملية قراءة . • تبدأ عملية القراءة بإعادة البدء بالدالة I2C1_Repeated_Start(); ، ثم يليها دالة الكتابة I2C1_Wr(0xD1); وآخر بت هى الواحد والتى تعنى أن العملية القادمة هى عملية قراءة . • كما توقعنا الدالة التالية read_data=I2C1_Rd(0); هى قراءة بيانات البايت المحدد عنوانه سابقا وحفظه فى المتغير read_data . الصفر (0) أنه لن يتم قراءة بايت أخر حاليا ، إذا كان المطلوب قراءة بيانات السجلات بشكل متتابع نضع واحد بدل الصفر ونليه بدوال القراءة واحدة تلو الأخرى وفى نهاية المطاف نستخدم I2C1_Rd(0); . • يتم تنبيه DS1307 بانتهاء العملية بالدالة I2C1_Stop(); . • فى النهاية نحصل على عائد هذه الدالة باستخدام التعليمة return(read_data); . بعد أن حصلنا على بيانات سجلات التوقيت والتاريخ من DS1307 سوف تقابلنا مشكلة !! وهى أن DS1307 يتعامل فقط مع البيانات بنظام الثنائى المكود عشرى BCD ، وهو ما يعنى أنه ثنائى (مكون من أصفار وآحاد) ولكن فى شكل عشرى أى آحاد وعشرات . بايت البيانات يتكون من من 8 بتات ، كل أربعة بت ، وتسمى نبل، تمثل خانة أو رقم فالأربعة بتات ذات القيمة الأدنى LSB تمثل الآحاد ، والأربعة بتات ذات القيمة الأقصى MSB تمثل رقم العشرات . على سبيل المثال ، سجل الثوانى الذى يعطى 15 SEC يتعامل معه DS1307 فى الشكل (00011001) حيث الأربعة بتات الأدنى تمثل الآحاد وهى 1001=5 والأربعة بتات العليا تمثل العشرات وهى 0001 = 1 ، فما هو الحل ؟ الحل هو أنشاء دالة لتحويل النبل الأدنى ودالة لتحويل النبل الأعلى إلى أحرف ليمكن عرضها على وحدة العرض LCD كما يلى : كود:
unsigned char MSB(unsigned char x) //Display Most Significant Bit of BCD number { return ((x >> 4) + '0'); } /////////////////////////////////////////////////////////////// unsigned char LSB(unsigned char x) //Display Least Significant Bit of BCD number { return ((x & 0x0F) + '0'); } يتم تحويل النبل الأعلى إلى أحرف بزحزحة بيانات البايت جهة اليمين بأربع للتخلص من النبل الأدنى ووضع النبل الأعلى فى بداية بايت العائد ، ثم إضافة حرف الصفر '0' أو العدد 48 لتحويل الرقم إلى حرف من حروف كود أسكى القابل للكتابة والعرض على وحدة LCD . ويتم تحويل النبل الأدنى إلى أحرف بإجراء عملية AND باستخدام المعامل & بين بيانات البايت والقيمة 0X0F بغرض التخلص النبل العلوى مع الحفاظ على النبل السفلى فى بداية بايت العائد ، ثم إضافة حرف الصفر '0' . بعد حل مشكلة اختلاف نوع البيانات نعود للعمل الاعتيادى : • من المفضل وضع جميع الإعدادات فى شكل دالة كما يلى : كود:
void init(){ ADCON1=0; CMCON=7; TRISC=0;// //////////// I2C1_Init(100000); //DS1307 I2C is running at 100KHz Lcd_Init(); // Initialize LCD Lcd_Cmd(_LCD_CLEAR); // Clear LCD display Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off Lcd_out(1,1,"Time:"); Lcd_out(2,1,"Date:"); } بعد ذلك يتم إعلان المتغيرات كما يلى : كود:
//Global Variables: int second; int minute; int hour; int hr; int day; int dday; int month; int year; int ap; ///////////////////////// char time[] = "00:00:00 PM"; char date[] = "00-00-00"; //////////////////////////////// وأخيرا نصل إلى الدالة الرئيسية : نبدأ باستدعاء دالة الإعدادات Init(); ثم ننشىء حلقة غير منتهية كود:
void main() { Init(); /////////// while(1) { • قراءة بيانات جميع سجلات التوقيت والتاريخ من DS1307 بواسطة الدالة read_ds1307(0);// وفى كل مرة نضع عنوان السجل المناسب كما يلى : second = read_ds1307(0);//sec minute = read_ds1307(1);//min register hour = read_ds1307(2);//hr register hr = hour & 0b00011111; ap = hour & 0b00100000; dday = read_ds1307(3);//day register day = read_ds1307(4);// month = read_ds1307(5);// month register year = read_ds1307(6);//year month register • بعد ذلك يتم تحويل البيانات من BCD إلى أحرف كما يلى : //////////////////////////////////// كود:
time[0] = MSB(hr);// char time[] = "00:00:00 PM"; time[1] = LSB(hr); time[3] = MSB(minute); time[4] = LSB(minute); time[6] = MSB(second); time[7] = LSB(second); ////////////////////////////////// date[0] = MSB(day);// char date[] = "00-00-00"; date[1] = LSB(day); date[3] = MSB(month); date[4] = LSB(month); date[6] = MSB(year); date[7] = LSB(year); if(ap) { time[9] = 'P'; //);// char time[] = "00:00:00 PM"; time[10] = 'M'; } else { time[9] = 'A'; time[10] = 'M'; } كود:
Lcd_out(1, 6, time); Lcd_out(2, 6, date); Delay_ms(100); } }
__________________
مقالات المهندس فتح الله عبدالعزيز التعديل الأخير تم بواسطة : F.Abdelaziz بتاريخ 16-04-2016 الساعة 06:09 AM. |
![]() |
![]() |
![]() |
#6 |
استاذ و مشرف قسم الالكترونيات
المشاركات: 6,894
معدل تقييم المستوى: 333
|
![]() ملفات البرنامج والمحاكاة ببرنامج بروتيس على الرابط :
http://www.mediafire.com/download/85...ic-project.zip النتيجة : ![]()
__________________
مقالات المهندس فتح الله عبدالعزيز |
![]() |
![]() |
![]() |
#7 |
استاذ و مشرف قسم الالكترونيات
المشاركات: 6,894
معدل تقييم المستوى: 333
|
![]() المشروع الأول : ساعة بسيطة باستخدام DS1307 و PIC16F877A و LCD :
لكى يعمل المشروع بشكل صحيح فى الواقع أو فى المحاكاة ينبغى وضع بعض القيم فى DS13-7 (ضبط الساعة) قبل القراءة منها وعرض النتائج على وحدة العرض LCD أى مجرد ضبط الساعة قبل عملية القراءة . فى هذا المشروع لن نستخدم أزرار للضبط بغرض تسهيل معرفة مبادىء العمل ، وسوف نستخدم لاحقا فى المشاريع أزرار الضبط للوصول إلى ساعة عملية . علاوة على ذلك يتم توضيح فكرة استخدام طرف الخرج SOUT لتوليد موجة مربعة بتردد 1Hz . الدائرة الكهربية : الدائرة الكهربية للساعة بسيطة جدا وهى مبينة بالشكل التالى : ![]() البرنامج مزد بالتعليقات اللازمة لشرح طريقة العمل : كود:
//DS1307 RTC Interfacing with PIC16F877A // LCD module connections sbit LCD_RS at RB2_bit; sbit LCD_EN at RB3_bit; sbit LCD_D4 at RB4_bit; sbit LCD_D5 at RB5_bit; sbit LCD_D6 at RB6_bit; sbit LCD_D7 at RB7_bit; sbit LCD_RS_Direction at TRISB2_bit; sbit LCD_EN_Direction at TRISB3_bit; sbit LCD_D4_Direction at TRISB4_bit; sbit LCD_D5_Direction at TRISB5_bit; sbit LCD_D6_Direction at TRISB6_bit; sbit LCD_D7_Direction at TRISB7_bit; ///////////////////// ///// global variables//// unsigned short sec; unsigned short minute; unsigned short hour; unsigned short day; unsigned short date; unsigned short month; unsigned short year; unsigned short temp; char time[9]; char ddate[11]; //////functions //////// ////////// unsigned short read_ds1307(unsigned short address)// address byte { I2C1_Start();//Determines if I²C bus is free and issues START signal. I2C1_Wr(0xd0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0 I2C1_Wr(address);//address of ds1307 to be read I2C1_Repeated_Start();//to change from write condition to read condition I2C1_Wr(0xd1); //0x68 followed by 1 --> 0xD1 temp=I2C1_Rd(0);//Reads one byte from the slave, and sends not acknowledge signal I2C1_Stop();//Issues STOP signal return(temp);//BCD byte } ///////// void write_ds1307(unsigned short address,unsigned short w_data)//address and w_data bytes { I2C1_Start(); // issue I2C start signal //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0 I2C1_Wr(0xD0); // send byte via I2C (device address + W) I2C1_Wr(address); // send byte (address of DS1307 location) I2C1_Wr(w_data); // send data (data to be written) I2C1_Stop(); // issue I2C stop signal } ///////////////////////// unsigned char BCD2UpperCh(unsigned char bcd) { return ((bcd >> 4) + '0');//get ASCII character } //////// unsigned char BCD2LowerCh(unsigned char bcd) { return ((bcd & 0x0F) + '0'); } /////// void init(){ I2C1_Init(100000); //DS1307 I2C is running at 100KHz PORTB = 0; TRISB = 0; // Configure PORTB as output TRISC = 0xFF; Lcd_Init(); // Initialize LCD Lcd_Cmd(_LCD_CLEAR); // Clear LCD display Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off Lcd_Out(1, 1, "TIME:"); Lcd_Out(2, 1, "DATE:"); //Set Time write_ds1307(0,0x80); //address 0 , data 10000000 :Reset second to 0 sec. and stop Oscillator ,DS1307 TIMEKEEPER REGISTERS Figure 3 write_ds1307(1,0x06); //write min 06 write_ds1307(2,0x12); //write hour 12 write_ds1307(3,0x07); //write day of week 7:satarday write_ds1307(4,0x16); // write date 16 write_ds1307(5,0x04); // write month 04 write_ds1307(6,0x16); // write year 16 --> 2016 write_ds1307(7,0x10); //SQWE output at 1 Hz , control address 0x07 , enable bit bit4 write_ds1307(0,0x00); //Reset second to 0 sec. and start Oscillator } ///////main function//////////// void main(){ init(); while(1) { sec=read_ds1307(0); // read second minute=read_ds1307(1); // read minute hour=read_ds1307(2); // read hour day=read_ds1307(3); // read day date=read_ds1307(4); // read date month=read_ds1307(5); // read month year=read_ds1307(6); // read year time[0] = BCD2UpperCh(hour); time[1] = BCD2LowerCh(hour); time[2] = ':'; time[3] = BCD2UpperCh(minute); time[4] = BCD2LowerCh(minute); time[5] = ':'; time[6] = BCD2UpperCh(sec); time[7] = BCD2LowerCh(sec); time[8] = '\0'; ddate[0] = BCD2UpperCh(date); ddate[1] = BCD2LowerCh(date); ddate[2] ='/'; ddate[3] = BCD2UpperCh(month); ddate[4] = BCD2LowerCh(month); ddate[5] ='/'; ddate[6] = '2'; ddate[7] = '0'; ddate[8] = BCD2UpperCh(year); ddate[9] = BCD2LowerCh(year); ddate[10] = '\0'; Lcd_Out(1,6,time); Lcd_Out(2,6,ddate); Delay_ms(50); } }
__________________
مقالات المهندس فتح الله عبدالعزيز |
![]() |
![]() |
![]() |
#8 |
استاذ و مشرف قسم الالكترونيات
المشاركات: 6,894
معدل تقييم المستوى: 333
|
![]() تحويل عدد من رقمين من BCD إلى عشرى والعكس :
لعمل ساعة رقمية بجميع الميزات سوف يتم استخدام DS1307 . فى هذه الحالة سوف نستخدم العديد من التحويلات من BCD إلى العشرى والعكس من أجل قراءة وضبط توقيت ساعة التوقيت الحقيقى DS1307 . يوفر مترجم الميكرو سى دوال مدمجة به من أجل مثل هذه التحويلات ولكن الدوال تستهلك معظم كمية حيز ذاكرة الميكروكونترولر ، لذلك يمكن إنشاء دوال بسيطة والتى تستهلك ذاكرة أقل للقيام بتحويل عدد BCD مكون من رقمين إلى عشرى والعكس . 1- دالة تحويل عدد BCD مكون من رقمين 2-digit BCD إلى عدد عشرى Decimal: كود:
unsigned short myBcd2Dec(unsigned short bcd){ return ((bcd >> 4)*10+(bcd & 0x0F)); } Example: myBcd2Dec(01000101) = 45 الشرح : • العدد BCD المكون من رقمين ، كل رقم يمثله 4-bits ويكون الإجمالى 8-bits . • دالة التحويل مكونة من جزءين جزء العشرات وجزء الآحاد يتم جمعهما معا . كل جزء خاص بتحويل 4-bits (نبل) . • النبل العلوى يمثل رقم العشرات ولتحويله نتخلص من النبل السفلى بزحزحة العدد الكلى أربعة مواقع للحصول على العدد العشرى ثم نضربه فى 10 للحصول على قيمة العشرات (bcd >> 4)*10 . • النبل السفلى يمثل رقم الآحاد ولتحويله نتخلص من النبل العلوى بإجراء عملية AND بالعامل 7 بين العدد الكلى والعدد 0x0F (تسمى عملية تغطية mask ) لنحصل على النبل السفلى (المقابل للآحاد) دون أى تغيير وحيث أنه الآحاد يتم الضرب فى واحد (bcd & 0x0F) • فى النهاية تكون النتيجة ((bcd >> 4)*10+(bcd & 0x0F)) ففى المثال : 01000101 نتيجة الجزء الأول تكون 00000100 وهى القيمة (4) تضرب فى 10 فتكون 40 . فى حين أن نتيجة الجزء الثانى 00000101 أى القيمة (5) ويكون المجموع (45) . سهلة 1 أليست كذلك . 2- دالة تحويل عدد عشرى مكون من رقمين 2-digit Decimal إلى عدد BCD : كود:
unsigned short myDec2Bcd(unsigned short dec){ return (((dec/10)<<4)(dec%10)); } Example: myDec2Bcd(45) = 01000101 الشرح : • نحصل على رقم الخانة العلوية بقسمة بايت العدد العشرى على 10 ونزحزح النتيجة 4 مواقع جهة اليمين (dec/10)<<4) ، ونحصل على رقم الخانة السفليى بإيجاد باقى خارج قسمة العدد العشرى على عشرة (dec%10) ، ثم نضع الجزئين بجوار بعضهما بالترتيب المناسب (dec/10)<<4)(dec%10) ملحوظة : تستخدم الأقواس ( ) فى تجميع التعبيرات ، وفصل تعبيرات الشرط ، وفى استدعاء الدوال، وفى احتواء بارامترات الدوال .
__________________
مقالات المهندس فتح الله عبدالعزيز |
![]() |
![]() |
![]() |
العلامات المرجعية |
أدوات الموضوع | |
|
|