منتدى الإلكترونيات قسم الالكترونكس لمناقشة الافكار والمعلومات المتعلقة بالهندسة الالكترونية للمبتدئين والهواة والفنيين - Electronics

   

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 18-04-2016, 05:20 PM المشاركة 9   
افتراضي



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


   }
}

اعلانات

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 18-04-2016, 05:20 PM المشاركة 10   
افتراضي


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

http://www.mediafire.com/download/gc...ital_Clock.zip


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

الصورة الرمزية حيدر علاج حسن
حيدر علاج حسن
:: مشرف منتدى الهندسة الكهربائية ::
تاريخ التسجيل: Mar 2005
الدولة: IRAQ
المشاركات: 9,848
نشاط [ حيدر علاج حسن ]
قوة السمعة:
قديم 19-04-2016, 12:24 AM المشاركة 11   
افتراضي


تحويل عدد من رقمين من 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)
ملحوظة :
تستخدم الأقواس ( ) فى تجميع التعبيرات ، وفصل تعبيرات الشرط ، وفى استدعاء الدوال، وفى احتواء بارامترات الدوال .
استاذ فتح الله من فضلك ارجو ان تعيد النظر في الفقرة 2 من الشرح و التي تخص دالة تحويل عدد عشرى مكون من رقمين 2-digit Decimal إلى عدد BCD :
حيث انك ذكرت ان نزحزح الرقم جهة اليمين ولكن ارى في الكود الاتجاه الى اليسار
مع جزيل الشكر


التعديل الأخير تم بواسطة : حيدر علاج حسن بتاريخ 19-04-2016 الساعة 12:33 AM

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 19-04-2016, 12:43 AM المشاركة 12   
افتراضي


استاذ فتح الله من فضلك ارجو ان تعيد النظر في الفقرة 2 من الشرح و التي تخص دالة تحويل عدد عشرى مكون من رقمين 2-digit Decimal إلى عدد BCD :
حيث انك ذكرت ان نزحزح الرقم جهة اليمين ولكن ارى في الكود الاتجاه الى اليسار
مع جزيل الشكر

حيث انك ذكرت ان نزحزح الرقم جهة اليمين ولكن ارى في الكود الاتجاه الى اليسار
شكرا للمتابعة والتدقيق ، فعلا خطأ سهوا منى أثناء الأنهماك فى الشرح ، اعذرنى فأنت مجرب وعارف مشقة البحث والإعداد والكتابة وتحميل الصور بهذه الكيفية ، المهم أن البرنامج صواب 100 % .
فى انتظار المزيد من إثراء الموضوع

مع تمنياتى بدوام التوفيق شكرا لك


الصورة الرمزية حيدر علاج حسن
حيدر علاج حسن
:: مشرف منتدى الهندسة الكهربائية ::
تاريخ التسجيل: Mar 2005
الدولة: IRAQ
المشاركات: 9,848
نشاط [ حيدر علاج حسن ]
قوة السمعة:
قديم 19-04-2016, 01:07 AM المشاركة 13   
افتراضي


اشكرك جزيل الشكر استاذي العزيز ...
سوف تكون لدينا مشاركة جميله في موضوعك هذا و كله بفضل شرحك المستفيض ...
وفقك الله


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 19-04-2016, 01:53 PM المشاركة 14   
افتراضي


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

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


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 19-04-2016, 08:29 PM المشاركة 15   
افتراضي تنويه


استاذ فتح الله من فضلك ارجو ان تعيد النظر في الفقرة 2 من الشرح و التي تخص دالة تحويل عدد عشرى مكون من رقمين 2-digit Decimal إلى عدد BCD :
حيث انك ذكرت ان نزحزح الرقم جهة اليمين ولكن ارى في الكود الاتجاه الى اليسار
مع جزيل الشكر
السلام عليكم :
تنويه :
1- فى الشرح كلمة يمين فقط تصحح إلى كلمة يسار بينما الكود سليم . وشكر للمهندس حيدر على المتابعة .
2- المشاركة المشار إليها هى مشاركة اعتراضية ولا دخل لها على الإطلاق فى البرنامج السابق لها حيث أننى استخدمت دالتى التحويل من BCD إلى عشرى وبالعكس والمدمجتان ضمن مترجم الميكروسى ولم استخدم هذه الدوال المعرفة يمعرفة المستخدم ، ولكننى أردت بها لفت النظر إلى أنه يمكن إنشاء دوال خاصة بك لهذا الغرض وخاصة أن استخدام الدوال المدمجة فى المترجم تستهلك (تستنفذ) ذاكرة كبيرة لكن فى حالتنا الذاكرة وفيرة والحمد لله .

مع تمنياتى بدوام التوفيق


التعديل الأخير تم بواسطة : F.Abdelaziz بتاريخ 19-04-2016 الساعة 08:32 PM


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