الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
منتديات الهندسة الكهربية والإلكترونية والميكاترونكس والكومبيوتر :: الميكروكونترولر PIC والبرجة بلغة السى والمترجم مسكروسى برو :: الميكروكونترولر PIC والبرمجة بلغة السى والمترجم ميكروسى برو
صفحة 1 من اصل 1
الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
الناقل 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 .
أليست سهلة ؟
يمكن تنفيذ ذلك بلغة السى والمترجم ميكروسى برو كما يلى :
مثال على القراءة من الساعة 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)
تنفيذ الكود السابق فى شكل برنامج :
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();
}
}
رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
ساعة التوقيت الحقيقى 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 :
شرح هذا الكود :
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 .
العديد من الميكروكونترولر 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 .
رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
المشروع التمهيدى لساعة التوقيت الحقيقى DS1307 :
الغرض استعراض :
• كيفية التعامل مع دوال مكتبة المترجم ميكروسى .
• كيفية قراءة سجلات التوقيت والتقويم من DS1307 عن طريق الميكروكونترولر .
• كيفية تحويل القراءة من BCD إلى أحرف يمكن عرضه على وحدة LCD .
الدائرة الكهربية :
البرنامج :
شرح أجزاء البرنامج :
الغرض استعراض :
• كيفية التعامل مع دوال مكتبة المترجم ميكروسى .
• كيفية قراءة سجلات التوقيت والتقويم من 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);
}
}
شرح أجزاء البرنامج :
رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
شرح أجزاء البرنامج :
1- أعدادات توصيل وحدة العرض LCD :
2- إنشاء دالة قراءة بيانات التوقيت time والتاريخ date من سجلات DS1303 ، كل ما سوف نحتاجه تحيد عنوان address السجل المطلوب الحصول على بياناته ، ويتم حفظ بيانات السجل فى المتغير 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 كما يلى :
يتم تحويل النبل الأعلى إلى أحرف بزحزحة بيانات البايت جهة اليمين بأربع للتخلص من النبل الأدنى ووضع النبل الأعلى فى بداية بايت العائد ، ثم إضافة حرف الصفر '0' أو العدد 48 لتحويل الرقم إلى حرف من حروف كود أسكى القابل للكتابة والعرض على وحدة LCD .
ويتم تحويل النبل الأدنى إلى أحرف بإجراء عملية AND باستخدام المعامل & بين بيانات البايت والقيمة 0X0F بغرض التخلص النبل العلوى مع الحفاظ على النبل السفلى فى بداية بايت العائد ، ثم إضافة حرف الصفر '0' أو العدد 48 لتحويل الرقم إلى حرف من حروف كود أسكى القابل للكتابة والعرض على وحدة LCD
بعد حل مشكلة اختلاف نوع البيانات نعود للعمل الاعتيادى :
• من المفضل وضع جميع الإعدادات فى شكل دالة كما يلى :
بعد ذلك يتم إعلان المتغيرات كما يلى :
////////////////////////////////
وأخيرا نصل إلى الدالة الرئيسية :
نبدأ باستدعاء دالة الإعدادات Init(); ثم ننشىء حلقة غير منتهية
وفيها يتم :
• قراءة بيانات جميع سجلات التوقيت والتاريخ من 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 إلى أحرف كما يلى :
////////////////////////////////////
وأخيرا يتم عرض التوقيت والتاريخ على وحدة العرض LCD
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 مرات
رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
ملفات البرنامج والمحاكاة ببرنامج بروتيس على الرابط :
http://www.mediafire.com/download/855cr7rm351k828/MIKROC-I2C-ds1307-basic-project.zip
النتيجة :
http://www.mediafire.com/download/855cr7rm351k828/MIKROC-I2C-ds1307-basic-project.zip
النتيجة :
رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
المشروع الأول : ساعة بسيطة باستخدام DS1307 و PIC16F877A و LCD :
لكى يعمل المشروع بشكل صحيح فى الواقع أو فى المحاكاة ينبغى وضع بعض القيم فى DS13-7 (ضبط الساعة) قبل القراءة منها وعرض النتائج على وحدة العرض LCD أى مجرد ضبط الساعة قبل عملية القراءة .
فى هذا المشروع لن نستخدم أزرار للضبط بغرض تسهيل معرفة مبادىء العمل ، وسوف نستخدم لاحقا فى المشاريع أزرار الضبط للوصول إلى ساعة عملية . علاوة على ذلك يتم توضيح فكرة استخدام طرف الخرج SOUT لتوليد موجة مربعة بتردد 1Hz .
الدائرة الكهربية :
الدائرة الكهربية للساعة بسيطة جدا وهى مبينة بالشكل التالى :
البرنامج مزد بالتعليقات اللازمة لشرح طريقة العمل :
لكى يعمل المشروع بشكل صحيح فى الواقع أو فى المحاكاة ينبغى وضع بعض القيم فى 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);
}
}
رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
تحويل عدد من رقمين من BCD إلى عشرى والعكس :
لعمل ساعة رقمية بجميع الميزات سوف يتم استخدام DS1307 . فى هذه الحالة سوف نستخدم العديد من التحويلات من BCD إلى العشرى والعكس من أجل قراءة وضبط توقيت ساعة التوقيت الحقيقى DS1307 . يوفر مترجم الميكرو سى دوال مدمجة به من أجل مثل هذه التحويلات ولكن الدوال تستهلك معظم كمية حيز ذاكرة الميكروكونترولر ، لذلك يمكن إنشاء دوال بسيطة والتى تستهلك ذاكرة أقل للقيام بتحويل عدد BCD مكون من رقمين إلى عشرى والعكس .
1- دالة تحويل عدد BCD مكون من رقمين 2-digit BCD إلى عدد عشرى Decimal:
الشرح :
• العدد 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 :
الشرح :
• نحصل على رقم الخانة العلوية بقسمة بايت العدد العشرى على 10 ونزحزح النتيجة 4 مواقع جهة اليمين (dec/10)<<4) ، ونحصل على رقم الخانة السفليى بإيجاد باقى خارج قسمة العدد العشرى على عشرة (dec%10) ، ثم نضع الجزئين بجوار بعضهما بالترتيب المناسب (dec/10)<<4)(dec%10)
ملحوظة :
تستخدم الأقواس ( ) فى تجميع التعبيرات ، وفصل تعبيرات الشرط ، وفى استدعاء الدوال، وفى احتواء بارامترات الدوال .
لعمل ساعة رقمية بجميع الميزات سوف يتم استخدام 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)
ملحوظة :
تستخدم الأقواس ( ) فى تجميع التعبيرات ، وفصل تعبيرات الشرط ، وفى استدعاء الدوال، وفى احتواء بارامترات الدوال .
رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
مشروع ساعة رقمية قابلة لضبط التوقيت والتاريخ باستخدام 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);
}
}
رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
ملفات المشروع والمحاكاة ببرنامج بروتيس :
الرابط :
الرابط :
رد: الناقل 2IC وساعة التوقيت الحقيقى DS1307 ومشاريع الساعات الرقمية :
الدروس المستفادة من ربط DS1307 مع PIC16F877A خلال I2C ومع المترجم ميكروسى برو :
1- تمهيد :
الجهاز DS1307 يتعامل مع البيانات من نوع BCD فقط فى حين أن المترجم ميكروسى لا يتعامل مع هذا النوع من البيانات تعاملا مباشرا فكيف نوفق بينهما ؟
• نحن نتعامل ونتفاهم مع المترجم ميكروسى برو بأنظمة الأعداد المختلفة ( السداسى عشر بالبادئة 0x ، والثنائى بالبادئة 0b والعشرى بدون بادئة ) وفى جميع الأحول وفى نهاية المطاف يقوم المترجم بترجمة البرنامج إلى إلى ملف سداسى عشرى .
• الميكروكونترولر لا يفهم إلا لغة الآلة فقط ، والمكونة من آحاد وأصفار فقط ولا تحتوى على بادئات أو لاحقات ، عندما يتم تحميل الملف السداسى عشرى إلى ذاكرة الميكروكونترولر بواسطة جهاز البرمجة والبرمجيات الخاصة به يجب أن يحمل فى شكل لغة الآلة .
• عند الكتابة :يرسل الميكروكونترولر بايت إلى DS1307 يكون فى شكل آحاد وأصفار 8-bit . عندما يصل هذا البايت إلى DS1307 فلن يسبب مشكلة لأنه سوف يترجم الأربع بتات الأولى رقم أحاد BCD والأربع بتات الأخيرة رقم عشرات BCD .
• عند القراءة يرسل DS1307 بيانات بايت فى شكل 8 بتات مشكلة BCD وعندما يستقبلها الميكروكونترولر يستقبلها أيضا فى شكل 8 بتات وهنا تأتى المشكلة ، فكيف يتعامل معها لكى تعبر تعبيرا صحيحا عن البيانات الأصلية ؟ الإجابة : يجب علية أولا وقبل كل شىء تحويل هذه البيانات BCD إلى أى شكل من الأشكال التى يتعرف عليها المترجم حتى يمكنه لاحقا من معالجتها بأى شكل من الأشكال .
2- إمكانيات المترجم ميكروسى برو فى التعامل مع الناقل I2C :
1- تمهيد :
الجهاز DS1307 يتعامل مع البيانات من نوع BCD فقط فى حين أن المترجم ميكروسى لا يتعامل مع هذا النوع من البيانات تعاملا مباشرا فكيف نوفق بينهما ؟
• نحن نتعامل ونتفاهم مع المترجم ميكروسى برو بأنظمة الأعداد المختلفة ( السداسى عشر بالبادئة 0x ، والثنائى بالبادئة 0b والعشرى بدون بادئة ) وفى جميع الأحول وفى نهاية المطاف يقوم المترجم بترجمة البرنامج إلى إلى ملف سداسى عشرى .
• الميكروكونترولر لا يفهم إلا لغة الآلة فقط ، والمكونة من آحاد وأصفار فقط ولا تحتوى على بادئات أو لاحقات ، عندما يتم تحميل الملف السداسى عشرى إلى ذاكرة الميكروكونترولر بواسطة جهاز البرمجة والبرمجيات الخاصة به يجب أن يحمل فى شكل لغة الآلة .
• عند الكتابة :يرسل الميكروكونترولر بايت إلى DS1307 يكون فى شكل آحاد وأصفار 8-bit . عندما يصل هذا البايت إلى DS1307 فلن يسبب مشكلة لأنه سوف يترجم الأربع بتات الأولى رقم أحاد BCD والأربع بتات الأخيرة رقم عشرات BCD .
• عند القراءة يرسل DS1307 بيانات بايت فى شكل 8 بتات مشكلة BCD وعندما يستقبلها الميكروكونترولر يستقبلها أيضا فى شكل 8 بتات وهنا تأتى المشكلة ، فكيف يتعامل معها لكى تعبر تعبيرا صحيحا عن البيانات الأصلية ؟ الإجابة : يجب علية أولا وقبل كل شىء تحويل هذه البيانات BCD إلى أى شكل من الأشكال التى يتعرف عليها المترجم حتى يمكنه لاحقا من معالجتها بأى شكل من الأشكال .
2- إمكانيات المترجم ميكروسى برو فى التعامل مع الناقل I2C :
مواضيع مماثلة
» تدريبات ومشاريع الأردوينو Arduino Tutorials and Projects
» الميكروكونترولر PIC والبرمجة بلغة C ومشاريع متقدمة مع المترجم مبكروسى برو
» شرح ساعة وقت وتاريخ تستخدم PIC16F877A و DS1307 و السفن سيجمنت مع المقاطعة
» ساعة وبيان درجة الحرارة وتقنية برمجة DS1307-DS18B20-LCD-PIC16F876
» مشاريع الميكروكونترولر المتقدمة بلغة السى نظام تشغيل الزمن الفعلى (الحقيقى) RTOS والمترجم CCS C :
» الميكروكونترولر PIC والبرمجة بلغة C ومشاريع متقدمة مع المترجم مبكروسى برو
» شرح ساعة وقت وتاريخ تستخدم PIC16F877A و DS1307 و السفن سيجمنت مع المقاطعة
» ساعة وبيان درجة الحرارة وتقنية برمجة DS1307-DS18B20-LCD-PIC16F876
» مشاريع الميكروكونترولر المتقدمة بلغة السى نظام تشغيل الزمن الفعلى (الحقيقى) RTOS والمترجم CCS C :
منتديات الهندسة الكهربية والإلكترونية والميكاترونكس والكومبيوتر :: الميكروكونترولر PIC والبرجة بلغة السى والمترجم مسكروسى برو :: الميكروكونترولر PIC والبرمجة بلغة السى والمترجم ميكروسى برو
صفحة 1 من اصل 1
صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى