الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

استعرض الموضوع السابق استعرض الموضوع التالي اذهب الى الأسفل

الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

مُساهمة من طرف Admin في الجمعة أبريل 15, 2016 2:16 pm

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



Admin
Admin

عدد المساهمات : 935
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

مُساهمة من طرف Admin في الجمعة أبريل 15, 2016 5:45 pm

ساعة التوقيت الحقيقى DS1307 وربطها مع الميكروكونترولر PIC بغرض إنشاء ساعة رقمية :
العديد من الميكروكونترولر PIC يمتلك ضمن بنائه الداخلى ناقل I²C (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 .

Admin
Admin

عدد المساهمات : 935
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

مُساهمة من طرف Admin في الجمعة أبريل 15, 2016 9:22 pm

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

}
}


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

Admin
Admin

عدد المساهمات : 935
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

مُساهمة من طرف Admin في الجمعة أبريل 15, 2016 9:52 pm

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

}
}


عدل سابقا من قبل Admin في السبت أبريل 16, 2016 6:12 am عدل 1 مرات

Admin
Admin

عدد المساهمات : 935
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

مُساهمة من طرف Admin في الجمعة أبريل 15, 2016 11:03 pm

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

http://www.mediafire.com/download/855cr7rm351k828/MIKROC-I2C-ds1307-basic-project.zip

النتيجة :



Admin
Admin

عدد المساهمات : 935
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

مُساهمة من طرف Admin في السبت أبريل 16, 2016 11:02 am

المشروع الأول : ساعة بسيطة باستخدام 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);
}
}



Admin
Admin

عدد المساهمات : 935
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

مُساهمة من طرف Admin في الأحد أبريل 17, 2016 2:41 pm

تحويل عدد من رقمين من 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)
ملحوظة :
تستخدم الأقواس ( ) فى تجميع التعبيرات ، وفصل تعبيرات الشرط ، وفى استدعاء الدوال، وفى احتواء بارامترات الدوال .

Admin
Admin

عدد المساهمات : 935
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

مُساهمة من طرف Admin في الإثنين أبريل 18, 2016 2:00 pm

مشروع ساعة رقمية قابلة لضبط التوقيت والتاريخ باستخدام DS1307 والميكروكونترولر 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;
// End LCD module connections
unsigned short read_ds1307(unsigned short address)
{
  unsigned short r_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
  r_data=I2C1_Rd(0);
  I2C1_Stop();
  return(r_data);
}
//////////////////////////////////////////
void write_ds1307(unsigned short address,unsigned short w_data)
{
  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');
}

unsigned char BCD2LowerCh(unsigned char bcd)
{
  return ((bcd & 0x0F) + '0');
}

//////global variables//////////////////
unsigned short  second;
unsigned short  minute;
unsigned short  hour;
unsigned short  hr;
unsigned short  day;
unsigned short  dday;
unsigned short  month;
unsigned short  year;
unsigned short  ap;

unsigned short set_count = 0;
short set;

char time[] = "00:00:00 PM";
char date[] = "00-00-00";
/////////////////////////
bit oldstate;                                    // Old state flag
////////////////////
void main()
{
  I2C1_Init(100000); //DS1307 I2C is running at 100KHz

  CMCON = 0x07;  // To turn off comparators
  ADCON1 = 0x06;  // To turn off analog to digital converters

  TRISA = 0x07;
  PORTA = 0x00;

  Lcd_Init();                        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);              // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  Lcd_out(1,1,"Time:");
  Lcd_out(2,1,"Date:");

  while(1)
  {
                set = 0;
        /////////
                if (Button(&PORTA, 0, 10, 0)) {              // Detect logical one
                        oldstate = 1;                              // Update flag
                        }

                if (oldstate && Button(&PORTA, 0, 10, 1)) {  // Detect one-to-zero transition
                        oldstate = 0;                              // Update flag
                        set_count++;
                                if(set_count >= 7)
                                {
                set_count = 0;
                                }

                }

        /////////////////////
    if(set_count)
    {
        //////////////////////////
                if (Button(&PORTA, 1, 10, 0)) {              // Detect logical one
                        oldstate = 1;                              // Update flag
                        }
                        /////
                if (oldstate && Button(&PORTA, 0, 10, 1)) {  // Detect one-to-zero transition
                        oldstate = 0;                              // Update flag
                        set = 1;
                }
          /////////////////////
 
                if (Button(&PORTA, 2, 10, 0)) {              // Detect logical one
                        oldstate = 1;                              // Update flag
                        }
                if (oldstate && Button(&PORTA, 0, 10, 1)) {  // Detect one-to-zero transition
                        oldstate = 0;                              // Update flag
                        set = -1;
                        }
          /////////////////////////
        if(set_count && set)
        {
          switch(set_count)
          {
            case 1:
                    hour=Bcd2Dec(hour);
                                        hour = hour + set;
                    hour=Dec2Bcd(hour);
                                        if((hour & 0x1F) >= 0x13)
                    {
                      hour = hour & 0b11100001;
                      hour = hour ^ 0x20;
                    }
                    else if((hour & 0x1F) <= 0x00)
                    {
                      hour = hour | 0b00010010;
                      hour = hour ^ 0x20;
                    }
                    write_ds1307(2, hour); //write hour
                                                 
                   
                    break;
            case 2:
                    minute = Bcd2Dec(minute);
                                        minute = minute + set;
                    if(minute >= 60)
                        minute = 0;
                    if(minute < 0)
                        minute = 59;
                    minute = Dec2Bcd(minute);
                                        write_ds1307(1, minute); //write min
                    break;
            case 3:
                    if(abs(set))
                      write_ds1307(0,0x00); //Reset second to 0 sec. and start Oscillator
                    break;
            case 4:
                    day = Bcd2Dec(day);
                                        day = day + set;
                    day = Dec2Bcd(day);
                                        if(day >= 0x32)
                        day = 1;
                    if(day <= 0)
                        day = 0x31;
                    write_ds1307(4, day); // write date 17
                    break;
            case 5:
                    month = Bcd2Dec(month);
                                        month = month + set;
                    month = Dec2Bcd(month);
                                        if(month > 0x12)
                      month = 1;
                    if(month <= 0)
                      month = 0x12;
                    write_ds1307(5,month); // write month 6 June
                    break;
            case 6:
                    year = Bcd2Dec(year);
                                        year = year + set;
                    year = Dec2Bcd(year);
                                        if(year <= -1)
                      year = 0x99;
                    if(year >= 0x50)
                      year = 0;
                    write_ds1307(6, year); // write year
                    break;
          }
        }
    }

      second = read_ds1307(0);
      minute = read_ds1307(1);
      hour = read_ds1307(2);
      hr = hour & 0b00011111;
      ap = hour & 0b00100000;
      dday = read_ds1307(3);
      day = read_ds1307(4);
      month = read_ds1307(5);
      year = read_ds1307(6);

//////////////////////////
      time[0] = BCD2UpperCh(hr);
      time[1] = BCD2LowerCh(hr);
      time[3] = BCD2UpperCh(minute);
      time[4] = BCD2LowerCh(minute);
      time[6] = BCD2UpperCh(second);
      time[7] = BCD2LowerCh(second);

      date[0] = BCD2UpperCh(day);
      date[1] = BCD2LowerCh(day);
      date[3] = BCD2UpperCh(month);
      date[4] = BCD2LowerCh(month);
      date[6] = BCD2UpperCh(year);
      date[7] = BCD2LowerCh(year);
      ///////
      if(ap)
      {
        time[9] = 'P';
        time[10] = 'M';
      }
      else
      {
        time[9] = 'A';
        time[10] = 'M';
      }
////////////////////////////

      Lcd_out(1, 6, time);
      Lcd_out(2, 6, date);
      Delay_ms(100);


  }
}


Admin
Admin

عدد المساهمات : 935
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

مُساهمة من طرف Admin في الإثنين أبريل 18, 2016 2:06 pm

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

الرابط :

http://www.mediafire.com/download/gc46bvmk7d868x3/Mikroc_DS1307_PIC16F877A_Setable_Digital_Clock.zip


Admin
Admin

عدد المساهمات : 935
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :

مُساهمة من طرف Admin في الثلاثاء أبريل 19, 2016 10:52 am

الدروس المستفادة من ربط DS1307 مع PIC16F877A خلال I2C ومع المترجم ميكروسى برو :
1- تمهيد :
الجهاز DS1307 يتعامل مع البيانات من نوع BCD فقط فى حين أن المترجم ميكروسى لا يتعامل مع هذا النوع من البيانات تعاملا مباشرا فكيف نوفق بينهما ؟
• نحن نتعامل ونتفاهم مع المترجم ميكروسى برو بأنظمة الأعداد المختلفة ( السداسى عشر بالبادئة 0x ، والثنائى بالبادئة 0b والعشرى بدون بادئة ) وفى جميع الأحول وفى نهاية المطاف يقوم المترجم بترجمة البرنامج إلى إلى ملف سداسى عشرى .
• الميكروكونترولر لا يفهم إلا لغة الآلة فقط ، والمكونة من آحاد وأصفار فقط ولا تحتوى على بادئات أو لاحقات ، عندما يتم تحميل الملف السداسى عشرى إلى ذاكرة الميكروكونترولر بواسطة جهاز البرمجة والبرمجيات الخاصة به يجب أن يحمل فى شكل لغة الآلة .
• عند الكتابة :يرسل الميكروكونترولر بايت إلى DS1307 يكون فى شكل آحاد وأصفار 8-bit . عندما يصل هذا البايت إلى DS1307 فلن يسبب مشكلة لأنه سوف يترجم الأربع بتات الأولى رقم أحاد BCD والأربع بتات الأخيرة رقم عشرات BCD .
• عند القراءة يرسل DS1307 بيانات بايت فى شكل 8 بتات مشكلة BCD وعندما يستقبلها الميكروكونترولر يستقبلها أيضا فى شكل 8 بتات وهنا تأتى المشكلة ، فكيف يتعامل معها لكى تعبر تعبيرا صحيحا عن البيانات الأصلية ؟ الإجابة : يجب علية أولا وقبل كل شىء تحويل هذه البيانات BCD إلى أى شكل من الأشكال التى يتعرف عليها المترجم حتى يمكنه لاحقا من معالجتها بأى شكل من الأشكال .

2- إمكانيات المترجم ميكروسى برو فى التعامل مع الناقل I2C :

Admin
Admin

عدد المساهمات : 935
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

استعرض الموضوع السابق استعرض الموضوع التالي الرجوع الى أعلى الصفحة


 
صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى