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

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

اذهب الى الأسفل

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

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

الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
1- مقدمة عن الناقل 2IC :
الناقل I2C (اختصار Inter-Integrated Circuit ) هو ناقل شائع الاستخدام ، وهو ناقل اتصال متزامن ( أى يوجد نبضات ساعة تزامن) يستخدم خطين (سلكين) :
• الخط SDA (اختصار Serial Data Line ) : هو خط بيانات ثنائى الاتجاه .
• الخط SCL (اختصار Serial Clock Line ) : هو خط ساعة التزامن ثنائى الاتجاه .

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

يتم التحكم فى الناقل 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  (راجع الداتا شيت ) . الشكل التالى يوضح ذلك .

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

لضبط تاريخ اليوم من الشهر ليكون يوم 27 ، يجب عليك كتابة البيانات 0x27 ( شفرة ثنائية مكودة عشرى BCD ) فى السجل الذى عنوانه 0x04 بالساعة DS1307 .
الناقل I2C يستخدم البروتوكول التالى :  

الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية : 311
 
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



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

مثال على القراءة من الساعة DS1307 :
فى هذه الحالة يكون المرسل هو التابع والمستقبل هو الماستر .
السجلات ذات العناوين من 0x00 إلى 0x06 بالساعة تحتوى على الترتيب على بيانات : الثوانى ، والدقائق ، والساعات ، والأيام (يوم الأسبوع) ، والتواريخ (يوم الشهر) ، والأشهر ، والسنين (راجع الداتا شيت) .
هنا سوف نتعرف على كيفية قراءة محتويات العناوين من 0x00 إلى 0x06 للساعة DS1307 ، ودفعة واحدة :
 
الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية : 511

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();
}
}
 


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

Admin
Admin

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

https://fathallaabdelaziz.forumarabia.com

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

الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية : Empty رد: الناقل 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 :
الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية : 711

يتم توصيل الطرف 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 بشكل مناسب .

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

عملية إرسال أو كتابة البيانات للساعة 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 لها ثمانى أطراف كما يلى :

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


وصف الأطراف :
• الطرف SQW/OUT : طرف الموجة المربعة / وتشغيل الخرج .
• الطرف SCL : طرف الساعة التسلسلية المستخدمة من أجل الاتصال IC2 .
• الطرف SDA : طرف البيانات التسلسلية من أجل الاتصال التسلسلى I2C .
• الطرف GND : طرف أرضى مصدر القدرة .
• الطرف VBAT : طرف توصيل البطارية الاحتياطية 3V ، وتستخدم فى حالة انهيار القدرة الرئيسية .
• الأطراف X1 , X2 : أطراف توصيل الكريستال 32.768 .
• الطرف Vcc : طرف توصيل موجب مصدر القدرة الرئيسى .

ربط الساعة الرقمية DS1307 مع الميكروكونترولر :
الشكل التالى يبين المخطط الصندوقى العام لربط الساعة الرقمية مع الميكروكونترولر:

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

في الاتصال التسلسلي I2C ، يعمل أحد الأجهزة باعتبار تابع slave ويعمل الجهاز الأخر باعتبارة السيد master . الجهاز التابع يستجيب فقط لتعليمات الجهاز السيد . الجهاز التابع لا يمكنه أن يعطي تعليمات للجهاز السيد . الساعة الرقمية DS1307 تعمل باعتبارها تابع slave وتستجيب لتعليمات الميكروكونترولر . السجلات المبنية ضمن الساعة الرقمية DS1307 تستخدم للاستجابة (الرد على ) لتعليمات الميكروكونترولر . كما هو مبين في المخطط أعلاه ، يتم توصيل الطرف SCL بالساعة DS1307 إلى الطرف SCL بالميكروكونترولر. يستخدم هذا الطرف (طرف الساعة التسلسلية) لمزامنة البيانات التسلسلية على الخط التسلسلي . كلمة SCL تعنى مدخل الساعة التسلسلية . فى حين أن الكلمة SDA تعنى طرف مدخل/مخرج البيانات التسلسلية . يتم توصيل الطرف SDA بالساعة DS1307 مع الطرف SDA بالميكروكونترولر. يستخدم الطرف SDA كمدخل للبيانات التسلسلية أو كمخرج من أجل الاتصال التسلسلى بخطين . الأطراف SDA و SCL بالساعة DS1307 هى أطراف مصب مفتوح وهذا هو سبب الاحتياج لمقاومة رفع خارجية كما هو مبين بالشكل أعلاه . يستخدم كريستال عيارى32.876KHz مع ساعة الوقت الحقيقى DS1307 .

Admin
Admin

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

https://fathallaabdelaziz.forumarabia.com

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

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

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

المشروع التمهيدى لساعة التوقيت الحقيقى DS1307 :
الغرض استعراض :
• كيفية التعامل مع دوال مكتبة المترجم ميكروسى  .
• كيفية قراءة سجلات التوقيت والتقويم من DS1307 عن طريق الميكروكونترولر .
• كيفية تحويل القراءة من BCD إلى أحرف يمكن عرضه على وحدة LCD .
الدائرة الكهربية :

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

البرنامج :


الكود:

/*
* 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

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

https://fathallaabdelaziz.forumarabia.com

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

الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية : Empty رد: الناقل 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

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

https://fathallaabdelaziz.forumarabia.com

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

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

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

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

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

النتيجة :

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

Admin
Admin

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

https://fathallaabdelaziz.forumarabia.com

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

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

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

المشروع الأول : ساعة بسيطة باستخدام DS1307 و PIC16F877A و LCD :
لكى يعمل المشروع بشكل صحيح فى الواقع أو فى المحاكاة ينبغى وضع بعض القيم فى DS13-7 (ضبط الساعة) قبل القراءة منها وعرض النتائج على وحدة العرض LCD أى مجرد ضبط الساعة قبل عملية القراءة .
فى هذا المشروع لن نستخدم أزرار للضبط بغرض تسهيل معرفة مبادىء العمل ، وسوف نستخدم لاحقا فى المشاريع أزرار الضبط للوصول إلى ساعة عملية . علاوة على ذلك يتم توضيح فكرة استخدام طرف الخرج SOUT لتوليد موجة مربعة بتردد 1Hz .
الدائرة الكهربية :
الدائرة الكهربية للساعة بسيطة جدا وهى مبينة بالشكل التالى :

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


الكود:

//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

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

https://fathallaabdelaziz.forumarabia.com

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

الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية : Empty رد: الناقل 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

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

https://fathallaabdelaziz.forumarabia.com

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

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

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

مشروع ساعة رقمية قابلة لضبط التوقيت والتاريخ باستخدام DS1307 والميكروكونترولر PIC16F877A والمترجم ميكروسى برو :

الدائرة الكهربية :

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

البرنامج :

الكود:

// 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

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

https://fathallaabdelaziz.forumarabia.com

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

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

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

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

الرابط :

Admin
Admin

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

https://fathallaabdelaziz.forumarabia.com

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

الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية : Empty رد: الناقل 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

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

https://fathallaabdelaziz.forumarabia.com

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

الرجوع الى أعلى الصفحة

- مواضيع مماثلة

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