قسم الميكروكنترولر والروبوت ودوائر الاتصال بالحاسب الالي قسم المتحكمات الـ microcontroller و المعالجات microprocessor و التحكم الرقمي بالكمبيوتر CNC والانظمة الآلية والروبوت Robots

أدوات الموضوع

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 06-07-2017, 08:07 PM المشاركة 1   
افتراضي الاتصال التسلسلى بين الدوائر المتكاملة   I2C Inter-Integrated Circuit Twitter FaceBook Google+



الاتصال التسلسلى بين الدوائر المتكاملة   I2C Inter-Integrated Circuit
المرجع :
http://embedded-lab.com/blog/?p=2583

مقدمة :
نظام I2C هو واجة ربط متسلسلة لمسافة قصيرة والتى تتطلب ناقل ذو خطين فقط لنقل البيانات . ولقد أخترعت من قبل شركة فيليبس عام 1980 ، وذلك لتوفير اتصالات سهلة على اللوحة المطبوعة بين وحدة المعالجة المركزية CPU ورقائق الطرفيات المختلفة فى جهاز التليفزيون . اليوم يتم استخدامها على نطاق واسع فى أنواع متعددة من الأنظمة المدمجة لربط الأجهزة الطرفية ذات السرعة المنخفضة ( الذاكرات EEPROMs الخارجية وأجهزة الاستشعار الرقمية ومشغلات وحدات العرض LCD ..ألخ ) بالمتحكم الرئيسى .
سوف نتناول لمحة عامة عن بروتوكول I2C وتنفيذه فى الميكروكونترولر PIC وطريقة توصيل جهاز مفرد أو عدد من الأجهزة بناقل I2C مشترك . سوف نوضح هذه التقنية بتوصيل 2 دائرة متكاملة EEPROM نوع (24LC512) وجهاز الاستشعار بالحرارة (DS1631) مع الميكروكونترولر PIC18F2550 .

مبدأ العمل :
نظام الناقل I2C له خطين : خط البيانات التسلسلية SDA وخط الساعة التسلسلية SCL . أى بيانات ترسل من أحد الأجهزة إلى الجهاز الآخر تمر خلال خط البيانات التسلسلية SDA ، فى حين أن خط الساعة التسلسلية يوفر ساعة التزامن اللازمة لنقل البيانات .
الأجزة الموجودة على الناقل I2C إما أن تكون "سيد" Masters (ماستر) أو "تابع" Slaves . فقط الجهاز الماستر هو الذى يمكنه بدء نقل البيانات بينما التابع يستجيب للماستر . من الممكن أن يكون لدينا أجهزة ماستر متعددة على نفس الناقل المشترك ، ولكن جهاز ماستر واحد فقط يمكن أن يكون فعال فى زمن معين . خط الساعة SCL دائما يتم قيادته عن طريق الماستر . سوف نتناول حالة جهاز ماستر واحد وهو الميكروكونترولرPIC18F2550 .
الشكل التالى يبين ناقل I2C بماستر منفرد وثلاثة توابع . التوابع لا يمكنها أبدا بدء نقل البيانات ولكن يمكنها نقل البيانات عبر الناقل I2C ودائما يكون ذلك تحت سيطرة الماستر .



كل من الخط SCL والخط SDA ذات دوائر قيادة بمصب مفتوح open drain drivers ، وبالتالى يتم توصيلها بالجهد الموجب للمصدر من خلال مقاومات سحب لأعلى pull-up resistors . وهذا يعنى أن أجهزة I2C يمكنها فقط سحب الخط لأسفل ولكن لا يمكنها جعله مرتفعا . عندما لا يقوم أى جهاز بسحب الخط فسوف يكون هذا الخط طافيا لأعلى float high من خلال مقاومة السحب لأعلى . وهذا هو السبب فى أهمية مقاومات السحب فى نظام I2C .
يمكن نقل البيانات بالناقل I2C بمعدل حتى  100 Kbps ( فى النظام القياسى standard) أو بمعدل  400 Kbps ( فى النظام السريع fast) أو حتى  3.4 Mbps ( فى نظام السرعة المرتفعة high-speed) .

أحوال البدء والإيقاف Start and Stop conditions
قبل القيام بأى تعامل على الناقل ، يتم إصدار حالة "البدء" Start  عن طريق الجهاز الماستر لإبلاغ جميع الأجهزة التابعة أن شيئا ما على وشك أن ينتقل على الناقل . ونتيجة لذلك ، فإن جميع الأجهزة التابعة الموصلة تكون فى حالة إستماع لخط البيانات التسلسلية إنتظارا للتعليمات ( بمعنى أن الناقل مشغول) .
يتم إصدار حالة البدء عن طريق سحب خط البيانات التسلسلية SDA إلى الحالة المنخفضة يليه خط الساعة التسلسلية SCL .
بمجرد الانتهاء من نقل البيانات يقوم الجهاز الماستر للناقل بإرسال حالة  " الإيقاف" (الانتهاء) Stop لإبلاغ الأجهزة الأخرى بالرغبة فى الإفراج (تحرير) عن الناقل (بمعنى أن الناقل غير مشغول) . الإشارات المستخدمة فى حالة الإيقاف هى تحرير خط الساعة SCL يليه تحرير خط البيانات SDA .
تذكر أنه عندما يتم تحرير الخطوط ، فإنها تكون طافية لأعلى بسبب مقاومات السحب لأعلى . وهكذا فإن تتابع البدء والإنتهاء يعتبر بمثابة إشارة أو علامة لبداية ونهاية التعامل مع الجهاز التابع .



عنونة أجهزة الناقل I2CI2C device addressing :
كل جهاز متصل بالناقل I2C يكون قابل للعنونة برمجيا عن طريق عنوان منفرد ذو 7 بت 7-bit أو 10 بت 10-bit . استخدام العنوان ذو 10 بت غير شائع وبالتالى لن يتم تناوله هنا.
البايت الأول الذى يرسل بعد حالة البدء يعرف ببايت التحكم Control byte . السبعة بتات الأولى لبايت التحكم تشكل عناوين الأجهزة التابعة ، فى حين أن البت الثامن (LSB) هو بت اتجاه البيانات (R/W) :
• عندما يكون هذا البت بصفر (0) فهذا يشير على أن الجهاز الماستر سوف "يكتب" (يرسل) معلومات إلى الجهاز التابع المختار ( بالسبعة بتات الأولى) .
• وعندما يكون هذا البت بواحد (1) فهذا يشير على أن جهاز الماستر سوف "يقرأ" (يستقبل) البيانات من الجهاز التابع المختار ( بالسبعة بتات الأولى) .
فى أجهزة السبعة بت ،  عادة تكون الأربعة بتات الأولى ثابتة fixed لنفس الجهاز ،  ويتم تعيين الثلاثة بتات التالية عن طريق أطراف عناوين الأجهزة hardware (A0, A1, A2) وهذا يسمح للمستخدم بتعديل عناوين ناقل I2C بما يصل حتى ثمانية من نفس الأجهزة بالعمل على الناقل I2C . هذه الأطراف يتم حفظها فى الحالة المرتفعة عن طريق VCC أو الحالة المنخفضة عن طريق الأرضى GND . سوف يتم ماقشة ذلك فى الدائرة الكهربية وكيفية تحديد عنوان الجهاز على الناقل .




عندما يتم إرسال بايت التحكم ، فإن كل جهاز بالنظام يقارن السبعة بتات الأولى المستقبلة مع عنوانه . إذا تطابقا ، فإن الجهاز يعتبر نفسه المخاطب بواسطة (تحت أمر) الجهاز الماستر ليكون إما " مستقبل – تابع "
slave-receiver أو " مرسل- تابع " slave-transmitter وهذا يتوقف على قيمة بت اتجاه البيانات (البت الثامنة) .

نقل البيانات Data transfer :
كل بايت يوضع على خط البيانات SDA يجب أن يكون بطول 8 بتات 8-bits . ترسل البيانات على خط البيانات SDA بدءا بالبت الأكثر أهمية(MSB) أولا وينتج خط الساعة SCL ساعة التزامن . تعتبر البيانات على الخط SDA صالحة (صحيحة) عندما يكون الخط SCL فى الحالة المرتفعة ، وبالتالى يجب أن تستقر البيانات خلال فترة الحالة المرتفعة للساعة . الحالة المرتفعة أو المنخفضة لحالة خط البيانات يجب أن تتغير عندما تكون الإشارة على الخط  SCL فى الحالة المنخفضة . الشكل التالى يبين توقيت عمل كل بت :



إذا كان الجهاز التابع ليس فى وضع يمكنه من استقبال أو إرسال بايت كامل من البيانات حتى يؤدى مهمة أخرى ، على سبيل المثال خدمة مقاطعة داخلية ، فإنه يمكنه الحفاظ على الخط SCL منخفضا لإجبار الجهاز الماستر على حالة الانتظار . يستمر نقل البيانات عندما يكون الجهاز التابع جاهزا لبايت آخر من البيانات ويحرر خط الساعة .
دائما يتم إنهاء عملية نقل البيانات بحالة الإنهاء Stop التى تتولد عن طريق الجهاز الماستر . ومع ذلك ، إذا رغب الجهاز الماستر فى البقاء بالاتصال بالناقل ، فيمكنه توليد حالة "تكرار- البدء" repeated-Start وعنونة جهاز تابع آخر دون أن يولد حالة الإيقاف أولا .
التسلم (الإشعار بالاستلام أو المعرفة) Acknowledgment :
عادة يتم إلزام المستقبل الذى تمت عنونته بتوليد إشارة "إستلام" acknowledge (ACK)  بعد كل بايت يتم استقباله . تحدث إشارة الاستلام بعد نقل البت الثامنة لأى تعامل . خلال تلك الحالة يجب على المرسل تحرير الخط SDA للسماح للمستقبل بقيادته . يقوم المستقبل بقيادة إشارة SDA للحالة المنخفضة للدلالة على استلام البايت . إذا لم يقم المستقبل بقيادة الخط SDA للحالة المنخفضة ، فإن الحالة تكون حالة عدم إستلام no-acknowledge (NACK) ويتم إلغاء (إجهاض) العملية . إذا كان البايت المرسل هو بايت التحكم (slave address + R/W bit) ، عند ذلك فقط الجهاز التابع الذى له عنوان متطابق سوف يستجيب بإشارة الاستلام .

الآن دعنا نناقش كيف يمكن لهذه العملية ، بمختلف تسلسلها فى العمل ، أن تحدث أثناء اتصال الميكروكونترولر PIC18F2550 مع الذاكرة 24LC512 EEPROM  و مستشعر درجة الحرارة DS1631 من خلال الناقل I2C .
الوحدة أو الموديول MSSP (Master Synchronous Serial Port) بالميكروكونترولر PIC18F2550 يسمح بالاتصالI2C خلال طرفى الدخل / الخرج RB0/SDA (21) و RB1/SCL (22) .
لن يتم هنا مناقشة تفاصيل عمل هذه الوحدة بسبب استخدم المترجم ميكروسى الذى يوفر دوال روتينات لمكتبة الاتصال I2C .

الدائرة المتكاملة (24LC512) ذاكرة EEPROM تسلسلية:
الدائرة المتكاملة 24LC512 هى ذاكرة EEPROM تسلسلية من شركة ميكروشيب بسعة 64K x 8 (512 Kbits) ، متوافقة مع الاتصال I2C . مخطط الأطراف مبين بالشكل أدناه  .



الأربعة بتات الأولى ، الثابتة ، من السبعة بتات الخاصة بالعنوان لهذه الشريحة يتم تحديدها بالشكل ’1010′ أى A . الثلاثة بتات التالية قابلة للبرمجة من خلال أطرافها A0, A1, A2 . على سبيل المثال ، للجهاز 24LC512 عندما يكون A0 بالمنطق المرتفع ومع توصيل الأطراف A1،A2 بالأرضى فسوف يكون لدينا عنوان من السبعة بتات التالية ’1010001′ . وهذا التخطيط يسمح بعنونة ثمانى أجهزة متشابهة كحد أقصى على نفس الناقل I2C .

عملية كتابة البايت Byte Write operation :
لعملية كتابة بايت يتطلب 2 بايت من العناوين لاختيار واحد من أصل 65536 موقع فى ذاكرة EEPROM . الجهاز الماستر يوفرهما ، بعد إرسال بايت التحكم . الشريحة 24LC512  تستجيب بنبضة التسلم (كتوقيع بالاستلام ) acknowledge بعد استقبال كل بايت للعنوان . بعد ذلك يرسل الماستر بايت البيانات المطلوب كتابته بالذاكرة . عند استلام (استقبال) هذه البيانات ترسل الشريحة 24LC512  نبضة التسلم . عندئذ يقوم الماستر بإنهاء نقل البيانات عن طريق إصدار حالة الإيقاف .



عملية كتابة صفحة Page Write operation :
لتقليل زمن دورة الكتابة ، تقدم الشريحة 24LC512 ميزة كتابة صفحة ، والتى تسمح بالكتابة فى وقت واحد حتى 128 بايت متجاورة . يتم بدء كتابة الصفحة بنقس طريقة كتابة البايت ، ولكن بدلا من توليد حالة الإيقاف ، يقوم الماستر بإرسال حتى 127 بايت إضافى ، والتى تخزن مؤقتا فى المخزن المؤقت للصفحة بالشريحة on-chip page buffer وسوف يتم كتابتها بالذاكرة بعد أن يرسل الماستر حالة الإيقاف .



عملية القراءة Read operation :
بدء عملية القراءة تتم بنفس الطريقة مثل عملية الكتابة باستثناء أنه يتم تعيين البت R/W ،اى بايت التحكم فى القراءة / الكتابة ، بواحد ‘1’ . الشريحة 24LC512 تسمح بثلاثة أنواع أساسية من عمليات القراءة : قراءة العنوان الحالى ، والقراءة العشوائية والقراءة المتسلسلة (المتتابعة) .
داخليا ، تحتوى شريحة EEPROM على عداد عنوان والذى يحفظ عنوان آخر كلمة وصلت ، ويتزايد بواحد . ولذلك ، إذا كانت القراءة التى وصلت سابقا previous كانت للعنوان ‘n’ فإن العنوان الحالى لعملية القراءة يجب أن يصل للبيانات من العنوان n + 1 . عند استلام بايت التحكم مع تحديد البت R/W بواحد (1)  فإن EEPROM تصدر إشارة التسلم وترسل بايت البيانات للعنوان الحالى . الماستر سوف لا يتسلم عملية النقل لكن يولد حالة الإيقاف التالية ويقطع EEPROM الإرسال .




عمليات القراءة العشوائية تسمح للماستر بالوصول لأى موقع ذاكرة بطريقة عشوائية . لتنفيذ هذا النوع من عمليات القراءة ، لابد أولا من تحديد عنوان الكلمة . يتم ذلك عن طريق إرسال عنوان الكلمة للشريحة 24LC512  كجزء من عملية الكتابة ( تحديد البت R/W بصفر ) . بعد إرسال عنوان الكلمة ، يولد الماستر حالة "تكرار البدء" بعد التسلم . وهذا ينهى عملية الكتابة . عندئذ يصدر الماستر بايت التحكم مرة أخرى ولكن مع تحديد البت R/W بواحد . عندئذ سوف تقوم EEPROM بإصدار التسلم وترسل بيانات8-bit للكلمة . الماستر سوف لا يتسلم النقل ولكن يولد حالة الإيقاف والتى تتسبب فى أن ينهى EEPROM الإرسال .



يتم بدء القراءة التتابعية عن طريق إما العنوان الحالى أو قراءة العنوان عشوائيا . بعد استقبال البايت الأول من 24LC512 ، يصدر الماستر التسلم بدلا من حالة الإيقاف المستخدمة فى العنوان الحالى أو القراءة العشوائية . هذا التسلم يوجه 24LC512 لإرسال الكلمة 8 بت التالية بالعنوان التتابعى . بعد إرسال آخر بايت إلى الماستر ، فإن الماستر سوف لا يولد تسلم ، لكن يولد حالة إيقاف .




حماية الكتابة Write Protect WP :
الطرف رقم 7 بالشريحة 24LC512 هو مدخل حماية الكتابة بالأجهزة hardware  . إذا تم ربط هذا الطرف بالجهد الموجب Vcc ، فإن ذلك يحول دون عمليات الكتابة ولكن عمليات القراءة لا تتأثر . هنا سوف نوصل هذا الطرف بالأرضى .

الناقل I2C لمستشعر درجة الحرارة (DS1631) :
الشريحة DS1631 هى مقياس رقمى لدرجة الحرارة ، مصنع بمعرفة شركة Dallas  ، والذى يوفر حساسية قياس بدقة
9, 10, 11, 12-bit ( حسب اختيار المستخدم) ، لقياس درجة الحرارة فى المدى -55 °C to 125 °C  . الدقة الافتراضية عند توصيل القدرة هى 12-bit ،  والمقابلة لتزايد فى درجة الحرارة قدره 0.0625  °C (الحساسية). يتحقق الاتصال مع DS1631 من خلال واجهة الناقل I2C وثلاثة أطراف للعنونة (A0, A1, A2) بما يسمح لثمانى أجهزة من نفس النوع بالاتصال بنفس الخطين للناقل . العنوان ذات السبع بتات لكل جهاز تابع هى 1 0 0 1 A2 A1 A0 حيث A0, A1, A2  هى اختيارات المستخدم من خلال أطراف الدخل المناظرة .

قياس درجة الحرارة Temperature measurement :
يوصى بقراءة الداتا شيت الخاصة بالشريحة DS1631 للاطلاع على تفاصيل بناؤها وعملية تحويل درجة الحرارة .
هنا ، سوف نتناول فقط نظام الطلقة (الدفعة) الواحدة one-shot mode لتحويل درجة الحرارة . لنفترض ، أن الجهاز تم توصيله بالقدرة للتو ، وأن دقة التحويل محددة بقيمة 12-bit . فى نظام الطلقة الواحدة يبدأ المستشعر DS1631 بتحويل درحة الحرارة إلى كلمة رقمية مكونة من 12-bit بعد استقبال بايت الأمر 51h من الماستر .وهو ما يعرف بأمر بدء تحويل درجة الحرارة Start Convert T . بعد التحويل ، يتم تخزين درجة الحرارة الرقمية كعدد 16-bit فى شكل
two’s complement  ، فى سجلى درجة الحرارة المكونة من 2 بايت : TH و TL كما فى الشكل أدناه . بت الإشارة Sign bit (S) تشير إلى ما إذا كانت درجة الحرارة موجبة (S=0) أو سالبة (S=1) .





يمكن للماستر قراءة بيانات درجة الحرارة من DS1631 عن طريق إرسال أمر قراءة درجة الحرارة
Read Temperature (AAh) . بعد استقبال التسلم ACK استجابة للأمر ، يجب أن يولد الماستر حالة تكرار البدء repeated Start يليها بايت التحكم بعنوان نفس التابع كما فى بايت التحكم الأول . مع ذلك ، هذه المرة البت R/W يجب أن تكون بواحد (1) ، والتى تخبر DS1631 بأنه يتم إجراء "قراءة" . يرسل DS1631 التسلم ACK كاستجابة لبايت التحكم هذا ، ويبدأ فى إرسال البيانات المطلوبة فى دورة الساعة التالية . لقراءة 2 بايت (TH and TL registers) ، يجب أن يستجيب الماستر لبيانات أول بايت بالتسلم ACK ولبيانات ثانى بايت بعدم التسلم NACK متبوعة بحالة إيقاف . إذا كان هناك حاجة فقط لبيانات البايت الأكثر أهمية ، عندئذ يمكن للماستر أن يصدر عدم التسلم NACK متبوعة بحالة إيقاف بعد قراءة بيانات أول بايت .



اعلانات

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 07-07-2017, 11:31 AM المشاركة 2   
افتراضي


المترجم ميكروسى برو والاتصال التسلسلى I2C :
المترجم mikroC Pro for PIC يقدم مكتبة دوال (روتينات) للتعامل مع الاتصال بالناقل I2C ، فيما يلى ملخص لها :
الدالة :

كود:
void I2C1_Init(const unsigned long clock);
أول شىء يتعين علينا القيام به هو تهيئة ( إعداد ) الوحدة (الموديول) MSSP للاتصال I2C . يمكن أن يتم ذلك بالدالة I2C1_Init ، على سبيل المثال الدالة :

كود:
 I2C_Init(100000)
سوف تهىء الموديول MSSP من أجل الاتصال I2C بتردد (سرعة) KHz100 .

الدالة :

كود:
unsigned short I2C1_Start(void);
هذه الدالة تحدد ما إذا كان الناقل IC حرا free فيتم إصدار إشارة حالة "البدء" Start .
عائد (نتيجة) هذه الدالة بالصفر إذا لم يكن هناك خطأ .
مثال :

كود:
 I2C1_Start();
الدالة :

كود:
void I2C1_Repeated_Start(void);
لإصدار حالة "تكرار البدء" repeated-start .
مثال :

كود:
I2C1_Repeated_Start();
الدالة :

كود:
 unsigned short I2C1_Is_Idle(void);
تتحقق مما إذا كان الناقل I2Cحرا . إذا كان حرا تعود بواحد وإن لم يكن حرا (مشغول) تعود بالصفر .
مثال :

كود:
if (I2C1_Is_Idle()) {...}
الدالة :

كود:
unsigned short I2C1_Rd(unsigned short ack);
لقراءة بايت واحد من التابع وإرسال إشارة "عدم التسلم" NACK إذا كان البارامتر ack بصفر (0) وإلا ترسل "التسلم" acknowledge .
مثال :

كود:
 //Read data and send not acknowledge signal:
unsigned short take;
...
take = I2C1_Rd(0);
على سبيل المثال ، إذا احتاج الميكروكونترولر لقراءة درجة حرارة فى شكل 2 بايت من DS1631 فيجب عليه استخدام I2C1_Rd(1) لقراءة البايت الأول (مع إشارة استلام) و I2C1_Rd(0) لقراءة البايت الثانى (بدون إشارة إستلام) .

الدالة :

كود:
unsigned short I2C1_Wr(unsigned short data_);
لإرسال بيانات بايت data_ من خلال الناقل I2C . هذه الدالة تعود بالصفر إذا لم يكن هناك خطأ .
مثال :

كود:
I2C1_Wr(0xA3);
الدالة :

كود:
void I2C1_Stop(void);
لإصدار حالة الإيقاف Stop .
مثال :

كود:
I2C1_Stop();
مثال مكتبة الميكروسى :
هذا الكود يستعرض استخدام مكتبة I2C . يتم توصيل الأطراف SCL و SDA للميكروكونترولر بالأطراف المناظرة بذاكرة EEPROM .
يقوم البرنامج بإرسال بيانات إلى EEPROM (يتم كتابة البيانات 0xAA على العنوان 2 ) . بعد ذلك ، يتم قراءة البيانات من خلال الناقل I2C من EEPROM وإرسال قيمتها إلى المنفذ PORTB .

كود:
 void main(){
  PORTB = 0;
  TRISB = 0;                 // Configure PORTB as output

  I2C1_Init(100000);         // initialize I2C communication
//==== Writing operation =========
  I2C1_Start();              // issue I2C start signal
  I2C1_Wr(0xA2);        // send byte via I2C  (device address + W), (1010-001-0)
  I2C1_Wr(2);                // send byte (address of EEPROM location)
  I2C1_Wr(0xAA);             // send data (data to be written)
  I2C1_Stop();               // issue I2C stop signal

  Delay_100ms();

//===== Reading operation ======== 
  I2C1_Start();              // issue I2C start signal
  I2C1_Wr(0xA2);             // send byte via I2C  (device address + W)
  I2C1_Wr(2);                // send byte (data address)
  I2C1_Repeated_Start();     // issue I2C signal repeated start
  I2C1_Wr(0xA3);             // send byte (device address + R),(1010-001-1)
  PORTB = I2C1_Rd(0u);       // Read the data (NO acknowledge)
  I2C1_Stop();               // issue I2C stop signal
}



تدريب :
فى هذا التدريب سوف نستخدم شريحة الذاكرة 24C64 EEPROM كجهاز تابع ، وسوف نستعرض عملية الكتابة إلى والقراءة من جهاز يمتلك وحدة I2C مع بيان الخرج على ليدات . فى برنامج Proteus سوف نحتاج إلى جهاز I2C Debugger والذى يتم توصيله على التوازى مع كل من الميكروكونترولر PIC16F877A والذاكرة عبر خط الساعة SCL وخط البيانات SDA كما هو مبين بالدائرة الكهربية .
فى هذا التدريب سوف نكتب 00000001 إلى أول موقع ذاكرة ، ونكتب 00000010 إلى ثانى موقع ذاكرة ونكتب 00000100 إلى ثالث موفع ذاكرة وهكذا على التتابع حتى الموقع الثامن 10000000 ، بعد ذلك يتم القراءة المتتابعة وعرض النتيجة على ليدات متصلة بالمنفذ PORTB .
الدائرة الكهربية :



البرنامج :

كود:
void write_EEPROM(unsigned int address, unsigned int dat)
{

unsigned int temp;
  I2C1_Start();            // issue I2C start signal
  I2C1_Wr(0xA0);           // send byte via I2C (device address + W)
temp = address >> 8;     //saving higher order address to temp
  I2C1_Wr(temp);           //sending higher order address
  I2C1_Wr(address);        //sending lower order address
  I2C1_Wr(dat);            // send data (data to be written)
  I2C1_Stop();             // issue I2C stop signal
Delay_ms(20);
}

unsigned int read_EEPROM(unsigned int address)
{
unsigned int temp;
  I2C1_Start();            // issue I2C start signal
  I2C1_Wr(0xA0);           // send byte via I2C (device address + W)
temp = address >> 8;     //saving higher order address to temp
  I2C1_Wr(temp);           //sending higher order address
  I2C1_Wr(address);        //sending lower order address
  I2C1_Repeated_Start();   // issue I2C signal repeated start
  I2C1_Wr(0xA1);           // send byte (device address + R)
temp = I2C1_Rd(0u);      // Read the data (NO acknowledge)
  I2C1_Stop();
return temp;
}

void main()
{
unsigned int a, i;
TRISB  = 0;             // To make it output port
   PORTB = 0;              // To make it output port
   CMCON = 0x07;           // To turn off comparators
   ADCON1 = 0x06;          // To turn off analog to digital converters
   I2C1_Init(100000);
do
   {
for(i=0,a=1;i<8;i++)
      {
write_EEPROM(i, a);
Delay_ms(30);
        a = a<<1;
      }

for(i=0;i<8;i++)
      {
         PORTB = read_EEPROM(i);
Delay_ms(100);
      }
}while(1);

}



اعلانات اضافية ( قم بتسجيل الدخول لاخفائها )
  

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 07-07-2017, 11:44 AM المشاركة 3   
افتراضي


تدريب : توصيل أجهزة متعددة على متن ناقل I2C مشترك :
الدائرة الكهربية :




يوجد 2 ذاكرة EEPROM تسلسلية نوع 24LC512 و مستشعر لدرجة الحرارة DS1631 متصلة على ناقل I2C مشترك . يتم تجنب الصراع conflict بين شريحتى الذاكرة EEPROMs بتوصيل الطرف A0 لأحدهما بالأرضى والطرف A0 للثانى بالجهد Vcc . العناوين ذات السبع بتات للثلاثة أجهزة مبينة بالشكل . المقاومتين 10K هى مقاومات السحب لأعلى لخطى الناقل I2C . خط البيانات SDA وخط الساعة SCL متصلان بالأطراف RB0 و RB1 للميكروكونترولر PIC18F2550 على الترتيب .
كما يتم توصيل وحدة عرض LCD لعرض عمليات القراءة والكتابة على الناقل I2C .

البرنامج :
سوف نكتب برنامج لاختبار الاتصال بالناقل I2C بين الميكروكونترولر PIC18F2550 والثلاثة أجهزة المتصلة بالناقل المشترك . سوف يقوم البرنامح أولا بالتحقق (اختبار) من وجود جميع الأجهزة الثلاثة على الناقل ، ثم يرسل أمر تحويل درجة الحرارة إلى الجهاز DS1631 . عندئذ يتم قراءة درجة الحرارة فى شكل 2 بايت وتخزينها فى شريحتى الذاكرة
( البايت المرتفع فى شريحة EEPROM الأولى والبايت المنخفض فى شريحة EEPROM الثانية ، بدءا من الموقع صفر ). بعد تسجيل خمس عينات ، يتم قراءتها بشكل تسلسلى من مواقع ذاكرة EEPROM ، وتحويلها إلى وحدات درجة حرارة فعلية (°C) وعرضها على شاشة وحدة العرض LCD .
فى برنامجنا ، سوف يقوم PIC18F2550 أولا بالتحقق من تواجد (إتاحة) الثلاثة أجهزة على الناقل . يتم ذلك بإرسال عنوان الجهاز لكل منهم فإذا تسلمه ، فهذا يعنى أنه موجود . دالة (روتين) الميكروسى للتحقق من وجود الجهاز على الناقل I2C كما يلى :

كود:
void check_device(unsigned short dev_address){
 I2C1_Start();
 if (I2C1_Wr(dev_address)){ //I2C1_Wr Returns 0 if there were no errors.

  Lcd_Out(2,1,"Device not found");
 }
 else Lcd_Out(2,1,"Device is OK");
 I2C1_Stop();
}
جزء البرنامج التالى يسمح للميكروكونترولر PIC18F2550 بإرسال أمر "بدء تحويل درجة الحرارة"
Start Convert T إلى DS1631 ، ثم الانتظار لمدة 750 ms حتى يتم إجراء تحويل درجة الحرارة فى شكل 12-bit ، وفى النهاية يتم استقبال قراءة درجة الحرارة المكونة من 2 بايت .

كود:
 // Read temperature
 I2C1_Start();
 I2C1_Wr(DS1631);               // Send device address
 I2C1_Wr(0x51);                 // Start Convert Temp command
 I2C1_Stop();
 Delay_ms(750);

 I2C1_Start();
 I2C1_Wr(DS1631);               // DS1631 Address again , with write 
 I2C1_Wr(0xAA);                 // Read Temperature command
 I2C1_Repeated_Start();
 I2C1_Wr(DS1631+1);              // Address with Read
 MS_Byte = I2C1_Rd(1);           // Read MSB and send ACK
 LS_Byte = I2C1_Rd(0);            // Read LSB and send NAK
 I2C1_Stop();
يمكنك ملاحظة أنه عند قراءة البايت الأخير فإن PIC18F2550 ليس بحاجة لإرسال نبضة "تسلم" acknowledge.

الروتينات التالية سوف تؤدى عمليات قراءة وكتابة بايت مع شرائح الذاكرة EEPROMs .

كود:
//--------------- Reads data from 24LC512 EEPROM - single location
unsigned short EEPROM_ReadByte(unsigned short EEPROM_Select, unsigned short rAddress) {
 unsigned short rAddrH, rAddrL, result;
 rAddrH = 0;
 rAddrL = rAddress;
 I2C1_Start();             // issue I2C1 start signal
 I2C1_Wr(EEPROM_Select);    // send byte via I2C1  (device address + W)
 I2C1_Wr(rAddrH);           // send Higher address byte
 I2C1_Wr(rAddrL);           // send Lower address byte
 I2C1_Repeated_Start();    // issue I2C1 signal repeated start
 I2C1_Wr(EEPROM_Select+1);   // send byte (device address + R)
 result = I2C1_Rd(0u);     // Read the data (NO acknowledge)
 while (!I2C1_Is_Idle())
 asm nop;                // Wait for the read cycle to finish
 I2C1_Stop();
 return result;
}
//--------------- Writes data to 24LC512 EEPROM - single location
void EEPROM_WriteByte(unsigned DeviceSelect, unsigned short wAddress, unsigned short wData) {
 unsigned short wAddrH, wAddrL;
 wAddrH = 0;
 wAddrL = wAddress;
 I2C1_Start();        // issue I2C1 start signal
 I2C1_Wr(DeviceSelect);   // send control byte
 I2C1_Wr(wAddrH);     // send higher address byte
 I2C1_Wr(wAddrL);     // send lower address byte
 I2C1_Wr(wData);      // send data to be written
 I2C1_Stop();
}

كود البرنامج :
كود:
 
/*
  Project: Multiple I2C devices on a common bus
  MCU: PIC18F2550 * 48.0 MHz (StartUSB for PIC board)
  Copyright * Rajendra Bhatt
  May 6, 2011
*/

// Define LCD module connections.
 sbit LCD_RS at RC6_bit;
 sbit LCD_EN at RC7_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 TRISC6_bit;
 sbit LCD_EN_Direction at TRISC7_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 connection definition


void Delay2s(){
 Delay_ms(2000);
}

void check_device(unsigned short dev_address){
 I2C1_Start();
 if (I2C1_Wr(dev_address)){ 
  Lcd_Out(2,1,"Device not found");
 }
 else Lcd_Out(2,1,"Device is OK");
 I2C1_Stop();
}

//--------------- Writes data to 24LC512 EEPROM - single location
void EEPROM_WriteByte(unsigned DeviceSelect, unsigned short wAddress, unsigned short wData) {
    unsigned short wAddrH, wAddrL;
    wAddrH = 0;
    wAddrL = wAddress;
    I2C1_Start();        // issue I2C1 start signal
    I2C1_Wr(DeviceSelect);   // send control byte
    I2C1_Wr(wAddrH);     // send higher address byte
    I2C1_Wr(wAddrL);     // send lower address byte
    I2C1_Wr(wData);      // send data (data to be written)
    I2C1_Stop();
}
//--------------- Reads data from 24LC512 EEPROM - single location
unsigned short EEPROM_ReadByte(unsigned short EEPROM_Select, unsigned short rAddress) {
    unsigned short rAddrH, rAddrL, result;
    rAddrH = 0;
    rAddrL = rAddress;
    I2C1_Start();             // issue I2C1 start signal
    I2C1_Wr(EEPROM_Select);   // send byte via I2C1  (device address + W)
    I2C1_Wr(rAddrH);          // send Higher address byte
    I2C1_Wr(rAddrL);          // send Lower address byte
    I2C1_Repeated_Start();    // issue I2C1 signal repeated start
    I2C1_Wr(EEPROM_Select+1);            // send byte (device address + R)
    result = I2C1_Rd(0u);     // Read the data (NO acknowledge)
    while (!I2C1_Is_Idle())
      asm nop;                // Wait for the read cycle to finish
    I2C1_Stop();
    return result;
}

char message1[] = "I2C Devices ";
char message2[] = "with PIC18F2550" ;
char Sample[] = "Sample 0";
char temp[] = "00.0000 C";

unsigned int address, Fraction_Temp;
unsigned short i,MS_Byte, LS_Byte, Whole_Temp;
const int EEPROM1 = 0xA0, EEPROM2 = 0xA2, DS1631 = 0x90;
void main() {
  CMCON = 0x07;   // Disable comparators
  ADCON1 = 0x0F;  // Disable Analog functions
  TRISC = 0x00;
  TRISB = 0x00;
  Lcd_Init();        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);             // CLEAR display
  Lcd_Cmd(_LCD_CURSOR_OFF);        // Cursor off
  Lcd_Out(1,1,message1);   // Write message1 in 1st row
  Lcd_Out(2,1,message2);   // Write message1 in 1st row
  Delay2s();

  I2C1_Init(100000);   // Initiate I2C

  // Check EEPROM1
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"EEPROM1");
  check_device(EEPROM1);
  Delay2s();
  
  // Check EEPROM2
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"EEPROM2");
  check_device(EEPROM2);
  Delay2s();
  
  // Check Sensor
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"DS1631");
  check_device(DS1631);
  Delay2s();

  for (i=0; i<5; i++) {
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1,1,"Reading Temp.");
    // Read temperature
    I2C1_Start();
    I2C1_Wr(DS1631);               // Send device address
    I2C1_Wr(0x51);                 // Start Convert Temp command
    I2C1_Stop();
    Delay_ms(750);
    I2C1_Start();
    I2C1_Wr(DS1631);               // DS1631 Address again
    I2C1_Wr(0xAA);                 // Read Temperature command
    I2C1_Repeated_Start();
    I2C1_Wr(DS1631+1);              // Address with Read
    MS_Byte = I2C1_Rd(1);           // Read MSB and send ACK
    LS_Byte = I2C1_Rd(0);            // Read LSB and send NAK
    I2C1_Stop();
    Delay2s();

    // Write the MS Byte to EEPROM1
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1,1,"Writing MS Byte");
    EEPROM_WriteByte(EEPROM1, i, MS_Byte);
    Delay2s();

    // Write the LS Byte to EEPROM2
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1,1,"Writing LS Byte");
    EEPROM_WriteByte(EEPROM2, i, MS_Byte);
    Delay2s();
  }
    // Reading stored temperature samples
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1,1,"Reading EEPROMs");
    Delay2s();

    for (i=0; i<5; i++){
     Lcd_Cmd(_LCD_CLEAR);
     Sample[7] = i+49; //"Sample 1","Sample 2",……,"Sample 5"
     Lcd_Out(1,1,Sample);
     Whole_Temp = EEPROM_ReadByte(EEPROM1, i);
     Fraction_Temp = EEPROM_ReadByte(EEPROM2, i);
     Fraction_Temp = Fraction_Temp >>4;
     Fraction_Temp = 625*Fraction_Temp; // 12 bit resolution is 0.0625C
     temp[0] = Whole_Temp/10+48;
     temp[1] = Whole_Temp%10+48;
     temp[3] = Fraction_Temp/1000+48;
     temp[4] = (Fraction_Temp/100)%10+48;
     temp[5] = (Fraction_Temp/10)%10+48;
     temp[6] = Fraction_Temp%10+48;
     Lcd_Out(2,5,temp);
     Delay2s();
    }

  }

احصائية الشكر والاعجاب - 1 شكراً, 0 عدم اعجاب, 1 اعجاب
شكراً سعيد قادر ( شكر العضو على هذه المشاركة )
اعجاب سعيد قادر ( أعجبته المشاركة )

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 09-07-2017, 07:45 PM المشاركة 4   
افتراضي


الناقل 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();
}
}




الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 09-07-2017, 07:47 PM المشاركة 5   
افتراضي


ساعة التوقيت الحقيقى DS1307 وربطها مع الميكروكونترولر PIC بغرض إنشاء ساعة رقمية  :
العديد من الميكروكونترولر PIC يمتلك ضمن بنائه الداخلى ناقل IC (Inter-Integrated Circuit) . هذا الناقل هو ناقل اتصال تسلسلى متزامن يعمل بواسطة  2- سلك(خط) .
بعض الأجهزة ، مثل الحساسات ، تتصل بالميكروكونترولر باستخدام هذا الناقل التسلسلى . العديد من الأجهزة ، حتى وإن كانت من أنواع مختلفة ، يمكن ربطها على نفس خطى الناقل 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 .


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 09-07-2017, 07:48 PM المشاركة 6   
افتراضي


المشروع التمهيدى لساعة التوقيت الحقيقى 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);

}
}

شرح أجزاء البرنامج :


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 09-07-2017, 07:51 PM المشاركة 7   
افتراضي


شرح أجزاء البرنامج :
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

2- إنشاء دالة قراءة بيانات التوقيت time والتاريخ date من سجلات DS1303 ، كل ما سوف نحتاجه تحيد عنوان address السجل المطلوب الحصول على بياناته ، ويتم حفظ بيانات السجل فى المتغير  read_data :



كود:
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_Start(); بغرض إيقاظ جميع الأجهزة المرتبطة بالناقل I2C مع الميكروكونترولر .
• الدالة التالية مباشرة هى دالة كتابة (أرسال) بايت عبر الناقل وهى 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' أو العدد 48 لتحويل الرقم إلى حرف من حروف كود أسكى القابل للكتابة والعرض على وحدة LCD
بعد حل مشكلة اختلاف نوع البيانات نعود للعمل الاعتيادى :
• من المفضل وضع جميع الإعدادات فى شكل دالة كما يلى :



كود:
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



كود:
      Lcd_out(1, 6, time);
      Lcd_out(2, 6, date);
      Delay_ms(100);

}
}


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 09-07-2017, 07:52 PM المشاركة 8   
افتراضي


ملفات البرنامج والمحاكاة ببرنامج بروتيس على الرابط :

http://www.mediafire.com/download/85...ic-project.zip

النتيجة :



احصائية الشكر والاعجاب - 1 شكراً, 0 عدم اعجاب, 1 اعجاب
شكراً سعيد قادر ( شكر العضو على هذه المشاركة )
اعجاب سعيد قادر ( أعجبته المشاركة )
إضافة رد

العلامات المرجعية

«     الموضوع السابق       الموضوع التالي    »
أدوات الموضوع

الانتقال السريع إلى


الساعة معتمدة بتوقيت جرينتش +3 الساعة الآن: 02:06 AM
موقع القرية الالكترونية غير مسؤول عن أي اتفاق تجاري أو تعاوني بين الأعضاء
فعلى كل شخص تحمل مسئولية نفسه إتجاه مايقوم به من بيع وشراء وإتفاق وأعطاء معلومات موقعه
التعليقات المنشورة لا تعبر عن رأي موقع القرية الالكترونية ولايتحمل الموقع أي مسؤولية قانونية حيال ذلك (ويتحمل كاتبها مسؤولية النشر)

Powered by vBulletin® Version 3.8.6, Copyright ©2000 - 2025