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

   

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



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


البرنامج مزد بالتعليقات اللازمة لشرح طريقة العمل :



كود:
//DS1307 RTC Interfacing with PIC16F877A

// LCD module connections
sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
/////////////////////
///// global variables////
unsigned short sec;
unsigned short minute;
unsigned short hour;
unsigned short day;
unsigned short date;
unsigned short month;
unsigned short year;
unsigned short temp;
char time[9];
char ddate[11];
//////functions ////////

//////////
unsigned short read_ds1307(unsigned short address)// address byte
{
I2C1_Start();//Determines if I²C bus is free and issues START signal.
I2C1_Wr(0xd0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
I2C1_Wr(address);//address of ds1307 to be read 
I2C1_Repeated_Start();//to change from write condition to read condition
I2C1_Wr(0xd1); //0x68 followed by 1 --> 0xD1
temp=I2C1_Rd(0);//Reads one byte from the slave, and sends not acknowledge signal 
I2C1_Stop();//Issues STOP signal
return(temp);//BCD byte
}
/////////
void write_ds1307(unsigned short address,unsigned short w_data)//address and w_data bytes
{
I2C1_Start(); // issue I2C start signal
//address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
I2C1_Wr(0xD0); // send byte via I2C (device address + W)
I2C1_Wr(address); // send byte (address of DS1307 location)
I2C1_Wr(w_data); // send data (data to be written)
I2C1_Stop(); // issue I2C stop signal
}
/////////////////////////
unsigned char BCD2UpperCh(unsigned char bcd)
{
return ((bcd >> 4) + '0');//get ASCII character
}
////////
unsigned char BCD2LowerCh(unsigned char bcd)
{
return ((bcd & 0x0F) + '0');
}
///////
void init(){
I2C1_Init(100000); //DS1307 I2C is running at 100KHz
PORTB = 0;
TRISB = 0; // Configure PORTB as output
TRISC = 0xFF;

Lcd_Init();                // Initialize LCD
Lcd_Cmd(_LCD_CLEAR);       // Clear LCD display
Lcd_Cmd(_LCD_CURSOR_OFF);  // Turn cursor off

Lcd_Out(1, 1, "TIME:");
Lcd_Out(2, 1, "DATE:");

//Set Time
write_ds1307(0,0x80); //address 0 , data 10000000 :Reset second to 0 sec. and stop Oscillator  ,DS1307 TIMEKEEPER REGISTERS Figure 3
write_ds1307(1,0x06); //write min 06
write_ds1307(2,0x12); //write hour 12
write_ds1307(3,0x07); //write day of week 7:satarday
write_ds1307(4,0x16); // write date 16
write_ds1307(5,0x04); // write month 04
write_ds1307(6,0x16); // write year 16 --> 2016
write_ds1307(7,0x10); //SQWE output at 1 Hz , control address 0x07 , enable bit bit4
write_ds1307(0,0x00); //Reset second to 0 sec. and start Oscillator
}
///////main function////////////
void main(){
init();

while(1)
{
sec=read_ds1307(0); // read second
minute=read_ds1307(1); // read minute
hour=read_ds1307(2); // read hour
day=read_ds1307(3); // read day
date=read_ds1307(4); // read date
month=read_ds1307(5); // read month
year=read_ds1307(6); // read year

time[0] = BCD2UpperCh(hour);
time[1] = BCD2LowerCh(hour);
time[2] = ':';
time[3] = BCD2UpperCh(minute);
time[4] = BCD2LowerCh(minute);
time[5] = ':';
time[6] = BCD2UpperCh(sec);
time[7] = BCD2LowerCh(sec);
time[8] = '\0';

ddate[0] = BCD2UpperCh(date);
ddate[1] = BCD2LowerCh(date);
ddate[2] ='/';
ddate[3] = BCD2UpperCh(month);
ddate[4] = BCD2LowerCh(month);
ddate[5] ='/';
ddate[6] = '2';
ddate[7] = '0';
ddate[8] = BCD2UpperCh(year);
ddate[9] = BCD2LowerCh(year);
ddate[10] = '\0';

Lcd_Out(1,6,time);
Lcd_Out(2,6,ddate);
Delay_ms(50);
}
}

اعلانات

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


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

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

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


مشروع ساعة رقمية قابلة لضبط التوقيت والتاريخ  باستخدام 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 ]
قوة السمعة:
قديم 09-07-2017, 11:00 PM المشاركة 124   
افتراضي


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

الرابط :



الصورة الرمزية burai nuraldaem
burai nuraldaem
:: عضو فضى ::
تاريخ التسجيل: Nov 2015
الدولة: السودان
المشاركات: 501
نشاط [ burai nuraldaem ]
قوة السمعة:
قديم 12-07-2017, 11:28 PM المشاركة 125   
افتراضي


قبل كتابة برنامجك الأول يجب أن تكون ملما بما يلى :
• أطراف الميكروكونترولر PIC تكون مقسمة إلى "منافذ" PORTS تحتوى على مجموعة من "أطراف الدخل/الخرج .
• فى الميكروكونترولر PIC16F ، يوجد 2 سجل register ، كل سجل مكون من بايت أى 8 بت ، مرتبطة بكل منفذ ، السجل TRIS والسجل PORT ، على سبيل المثال : TRISB, PORTB و TRISC, PORTC وهكذا .
• الكلمة TRIS تعنى "حالات ثلاثة" Tri-State، والسجل TRIS هو المعنى بتحديد اتجاه كل طرف من أطراف الدخل/الخرج . وجود المنطق “1” فى بت محددة من بتات السجل TRIS يجعل الطرف المناظر "مدخل" Input ، ووجود المنطق “0” فى بت محددة من بتات السجل TRIS يجعل الطرف المناظر "مخرج" Output .
• السجلات PORT تستخدم لقراءة البيانات من أو كتابة البيانات إلى أطراف الدخل /الخرج . كتابة المنطق “1” فى بت معينة من بتات السجل PORT تجعل الطرف المناظر عند "المنطق المرتفع" (VDD) ، وكتابة المنطق “0” فى بت من بتات السجل PORT تجعل الطرف المناظر عند "المنطق المنخفض" (VSS) ، وذلك إذا كان هذا الطرف "مخرج" Output ( البت المناظرة من السجل TRIS بصفر “0” ) .
• السجل PORT يمكن أن يستخدم لقراءة البيانات الرقمية من طرف "مدخل". المنطق “1” عند طرف المدخل يشير إلى أن هذا الطرف عند الحالة المنطقية المرتفعة (VDD) Logic High ، والمنطق “0” عند طرف المدخل يشير إلى أن هذا الطرف عند الحالة المنطقية المنخفضة (VSS) Logic Low .



• يمكنك الكتابة إلى السجل PORT والسجل TRIS ككل (كبايت 8-bit ) أو ألى كل بت بشكل منفصل (بت ببت bit by bit ) :
مثال على طريقة الكتابة إلى البتات (بت ببت) :

كود:
 
TRISC.F0 = 1; //Makes 0th bit of PORTC Input TRISC.F5 = 0; //Makes 5th bit of PORTC Output PORTB.F3 = 1; //Makes 3ed bit of PORTB at Logic High PORTB.F7 = 0; //Makes 7th bit of PORTB at Logic Low
ملاحظات :
• لعلك لاحظت وجود "فاصلة منقوطة" ( عند نهاية كل تعليمة (أمر) . هذه الفاصلة المنقوطة مهمة فى لغة السى حيث يتعرف عليها المترجم فيعلم مكان انتهاء التعليمة ويبدأ فى ترجمتها وينتقل إلى [/code] التعليمة التالية وهكذا .
• للإشارة إلى البت المحددة بالسجل يمكن استخدام الصيغة TRISC.F0 أو الصيغة TRISC.B0 .
• علامة التساوى (=) هنا تسمى علامة "تخصيص" ، بمعنى كتابة أو إرسال “1” إلى البت TRISC.F0 ، على سبيل المثال .
وللكتابة إلى السجل ككل (بايت) :
يجب أن تكون ملما بالمفاهيم التالية عند البرمجة بلغة السى :
• العدد الثنائى binary يشار إليه بالبادئة “0b” .
• العدد الثمانى octal يشار إليه بالبادئة “0” .
• العدد السداسى عشر hexadecimal يشار إليه بالبادئة “0x”.
• العدد العشرى decimal يكون بدون بادئة .
إليك بعض الأمثلة :

كود:
 
PORTB = 0xFF; //Makes all pins of PORTB Logic High TRISC = 0x00; //Makes all pins of TRISC Output PORTD = 128; //Makes 7th bit of PORTD Logic High
برنامجك الأول :
البرنامج التالى يقوم بعمل وميض ليد Led Blink بتأخير زمنى قيمته واحد ثانية :

كود:
 
void main() { TRISB.F0 = 0; //Makes PORTB0 or RB0 Output Pin PORTB=0; //LED OFF while(1) //Infinite Loop { PORTB.F0 = 1; //LED ON Delay_ms(1000); //1 Second Delay PORTB.F0 = 0; //LED OFF Delay_ms(1000); //1 Second Delay } }
ملحوظة : الدالة Delay_ms هى دالة ضمن مكتبة المترجم ميكروسى برو والتى توفر تأخير بالملى ثانية .
• أدخل البرنامج السابق بنافذة المحرر للمترجم ميكروسى برو .



• احفظ المشروع .
• قم بترجمة المشروع من خلال النقر على Build >> Build (or Ctrl+F9) .
• سوف يتم توليد الملف التنفيذى بالامتداد hex فى مجلد المشروع . أنت بحاجة إلى تحميل (كتابة) هذا الملف إلى الميكروكونترولر باستخدام جهاز برمجة أو تحميله فى برنامج ISIS بغرض المحاكاة .
الدائرة الكهربية :



الطرف VDD والطرف VSS للميكروكونترولر PIC تكون متصلة بكل من +5V و GND على الترتيب لتوفير القدرة اللازمة لعمل الميكروكونترولر . الكريستال 4MHz تستخدم لتوفير الساعة اللازمة للميكروكونترولر . المكثفات 22Pf تقوم بعمل تنظيم (تثبيت) لذبذبات الكريستال . يتم توصيل الليد LED بالبت bit0 للمنفذ PORTB (تسمى RB0) ويتم توصيل مقاومة 330 أوم على التوالى مع الليد للحد من التيار المار خلال الليد .
يمكنك محاكاة العمل باستخدام برنامج Proteus . لا تنسى إعداد تردد الساعة وأن تضيف ملف hex الموجود فى مجلد المشروع وذلك عن طريق تحرير خصائص الميكروكونترولر وذلك بالنقر المزدوج على الميكروكونترولر فتظهر لك نافذة كما هو مبين بالشكل التالى :



هذا البرنامج يقوم بتوصيل on لليد المتصل بالطرف RB0 من المنفذ PORTB للميكروكونترولر PIC16F877A . وبعد تأخير 1000 ملى ثانية (واحد ثانية) يتم فصل off الليد ، ثم التأخير واحد ثانية مرة أخرى ويتكرر العمل السابق بشكل غير منتهى بفعل الدالة while(1) .

لا تقلق إذا كنت لا تفهم عمل هذا البرنامج فى هذه المرحلة ، حيث أن كل شىء سوف يكون واضحا كلما تقدمنا.
السلام عليكم استاذ فتح الله
جازاك الله خير عن كل ما تقوم به
بدات متابعه هذه الدوره اليوم بعد ان نصحني بها الاستاذ القدير ماجد عباس محمد
لي استفسار صغير
اقتبست كل المشاركه وما اود السؤال عنه مميز باللون الاخضر
انت قلت ان الوسم يحدد ببادئه وان العشري لا بادئه له
انت وضعت قيمه 128 وهي حقا تناظر 7
انا الان كتبت هذا السطر
كود:
 void main()
{ 
      trisb=288;

}
الكومبايلر نفذ مع السطر ولم يعطي رساله خطا
وفي نفس الوقت لم احصل علي ملف hex
السؤال كيف ذلك ولا يمكن ان يتعدي البايت القيمه 256
وايضا التسلسل هو 2 4 8 16 32 ...



الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 13-07-2017, 01:56 AM المشاركة 126   
افتراضي


السلام عليكم استاذ فتح الله
جازاك الله خير عن كل ما تقوم به
بدات متابعه هذه الدوره اليوم بعد ان نصحني بها الاستاذ القدير ماجد عباس محمد
لي استفسار صغير
اقتبست كل المشاركه وما اود السؤال عنه مميز باللون الاخضر
انت قلت ان الوسم يحدد ببادئه وان العشري لا بادئه له
انت وضعت قيمه 128 وهي حقا تناظر 7
انا الان كتبت هذا السطر
كود:
 void main()
{ 
      trisb=288;

}
الكومبايلر نفذ مع السطر ولم يعطي رساله خطا
وفي نفس الوقت لم احصل علي ملف hex
السؤال كيف ذلك ولا يمكن ان يتعدي البايت القيمه 256
وايضا التسلسل هو 2 4 8 16 32 ...

وعليكم السلام ورحمة الله وبركاته
أخى الكريم شكرا جزيلا لك
أهلا ومرحبا بك ، وشكرا للاستاذ ماجد على الثقة

1- المترجم يكتشف الأخطاء اللغوية الخاصة بلغة السى والأخطاء المتعلقة بالميكروكونترولر المستهدف ، كأن تكتب منفذ غير موجود ، ولا يكتشف الأخطاء البرمجية .


2- القيمة 288 تعادل الرقم الثنائى

كود:
00000001 00100000
وبالتالى سوف يتم أخذ الثمانى بتات الأولى فقط ونسخها إلى المنفذ TRISB وهو ما يكافىء مايلى :

كود:
 TRISB=0b00100000;
وبالتالى فى البداية من المفضل استخدام الأعداد الثنائية عند تهيئة المنافذ حيث تكون واضحة وسهلة فى التعرف عليها .

3- قمت بتنفيذ البرنامج كما ذكرته ، وتم ترجمته وأعطى ملف HEX .

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


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


التحويل من تناظرى لرقمى ADC
مقدمة :
العديد من الإشارات الكهربائية من حولنا تكون ذات طبيعة تناظرية Analog (تتغير قيمتها بشكل مستمر) . محولات حساسات الكميات الطبيعية فى الغالب تحول الكمية الطبيعية إلى إشارة كهربائية ، هذا يعنى أن كمية تتغير مباشرة مع كمية أخرى . الكمية الأولى فى الغالب تكون الجهد voltage فى حين أن الكمية الثانية يمكن أن تكون أى كمية طبيعية مثل درجة الحرارة ، الضغط ، الضوء ، القوة ، العجلة ، .... إلخ . على سبيل المثال ، فى حساس درجة الحرارة LM35 ، جهد خرجه يتغير تبعا لدرجة الحرارة ، ومن ثم إذا امكننا قياس الجهد ، يمكنننا قياس درجة الحرارة .

ولكن معظم أجهزة الكمبيوتر (أو الميكروكنترولر) تكون ذات طبيعة رقمية. فهى يمكن أن تفرق فقط بين المستوى المرتفع HIGH أو المستوى المنخفض LOW على أطراف الدخل . على سبيل المثال ، إذا كان الدخل أكبر 2.5V سيتم قراءته باعتباره واحد (1) ، وإذا كان الدخل أقل من 2.5V سيتم قراءته باعتباره صفر (0) ( فى الأنظمة التى تعمل على 5V ) . لذلك لا يمكننا قياس الجهد مباشرة من الميكروكونترولر . لحل هذه المشكلة ، معظم الميكروكونترولر يمتلك وحدةتحويل من تناظرى إلى رقمى ADC . هذا المحول سوف يقوم بتحويل الجهد voltage إلى عدد number بحيث يمكن معالجته من قبل الأنظمة الرقمية مثل الميكروكونترولر . هذا المحول يتيح لنا ربط بسهولة كل أنوع الأجهزة التناظرية مع الميكروكونترولر .

دقة المحول من تناظرى لرقمى Resolution :
إن أهم مواصفات المحول من تناظرى لرقمى ADC هي "الدقة أو القدرة على التحليل " resolution ( هى أقل كمية يمكن قياسها ) . وهى تحدد مدى دقة قياس ADC لإشارات المدخلات التناظرية. نتيجة تحويل المحولات الشائعة تكون بسعة 8-bit أو 10-bit أو 12-bit . على سبيل المثال إذا كان جهد المرجع (سوف يتم شرحه لاحقا ) لمحول ADC هو من 0V إلى 5V ، فإن المحول 8-bit سوف يقسمه إلى 256 قسم ( من 0 إلى 255 ) ، لذلك يمكنه القياس بدقة ( تغيير نتيجة التحويل بمقدار واحد قسم ) تصل إلى 5/255 V =19.6mV تقريبا. في حين أن المحول 10-bit سوف يقسمه إلى 1024 قسم (أدنى نتيجة تحويل هى 0 ، وأقصى نتيجة تحويل هى 1023 ) ، عندئذ تكون دقة القياس
5/1023 V = 4.88 mV تقريبا . من ذلك يمكنك أن تدرك أن المحول 8-bit لا يمكنه التفرقة بين 1mV و 18mV .
المحول ADC المدمج فى الميكروكونترولر PIC من نوع 10-bit .



مصطلح الجهد المرجعى Reference Voltage :
الجهد المرجعى يحدد الحد الأدنى والحد الأقصى لمدى جهد الدخل التناظرى . فى الميكروكونترولر PIC يوجد جهدى مرجع ، إحداهما هو جهد المرجع السالب Vref- ، والآخر هو جهد المرجع الموجب Vref+ . جهد المرجع السالب Vref- يحدد الحد الأدنى لجهد الدخل التناظرى ، فى حين أن جهد المرجع الموجب يحدد الحد الأقصى لجهد الدخل التناظرى . على سبيل المثال ، إذا تم تطبيق إشارة قيمتها Vref- على قناة الدخل التناظرى ، عندئذ تكون نتيجة التحويل بصفر ، وإذا تم تطبيق إشارة قيمتها Vref+ على قناة الدخل التناظرى ، فإن النتيجة سوف تكون 1023 ( أقصى قيمة للمحول ADC ) .
• عندما يكون دخل ADC بقيمة Vref- ، فإن نتيجة التحويل تكون 0000000000 .
• وعندما يكون دخل ADC بقيمة Vref+ ، فإن نتيجة التحويل تكون 1111111111 .
• دقة ADC

كود:
 Resolution of ADC = (Vref+ – Vref-)/(210 – 1)
وهى أدنى جهد مطلوب لتغيير نتيجة تحويل ADC بواحد بت .
• فى الحالة العادية الافتراضية Resolution = (5 – 0)/(1024 – 1) = 5/1023 = 0.004887V .
• لذلك ، إذا كان الدخل 5V ، فإن نتيجة تحويل ADC تكون 5/0.004887 = 1023 = 11111111 (binary .
• وإذا كان الدخل 0.004887V ، فإن نتيجة تحويل ADC تكون 0.004887/0.004887 = 1 = 00000001 (binary) .
باختصار ، يمكن القول ، بأن قياس الجهد فى المحول يستند على مقارنة جهد الدخل مع المقياس الداخلى والذى له 1024 علامة (قسم) (2 أس عشرة) . أدنى علامة للمقياس تناظر جهد المرجع السالب Vref- ، فى حين أن أعلى علامة للمقياس تناظر جهد المرجع الموجب . الشكل التالى يبين جهدى المرجع القابلة للاختيار وقيمها الدنيا والقصوى أيضا .



معظم الميكروكونترولر PIC تمتلك ضمن بنائها موديول ADC . سوف نستعرض الميكروكونترولر PIC16F877A ، على سبيل المثال . الميكروكونترولر PIC16F877A يمتلك موديول 10-bit ADC .
جهد المرجع الموجب Vref+ وجهد المرجع السالب Vref- تكون قابلة للبرمجة ، فهى يمكن أن تكون VDD,VSS أو جهد ما على الأطراف RA2,RA3 .



موديول ADC يعمل مع أى من ثمانى قنوات متصلة بالأطراف الخارجية ، يتم الاختيار بين القنوات برمجيا عن طريق بتات اختيار القناة CHS0:CHS2 بالسجل ADCON0 (مترجم الميكروسى برو يقوم نيابة عنك بذلك )، كما هو مبين بالشكل .



السجل ADCON1 يتحكم فى تهيئة المنافذ لتكون تناظرية أو رقمية أو توليفة من الاثنين معا ، حيث يمكن تهيئة أى من الأطراف AN0-AN7 كمدخل تناظرى أو مدخل لجهد مرجع أو دخل / خرج رقمى ، وذلك عن طريق بتات تهيئة المنفذ PCFG0:PCFG3 ، كما هو موضح بالشكل .



الجدول التالى يبين الخيارات الممكنة :



ملاحظات :
1- فى الوضع الافتراضى البتات الأربعة تكون بأصفار وهذا يعنى أن جميع المداخل هى مداخل تناظرية وأن جهد المرجع الموجب يساوى VDD ، وجهد المرجع السالب هو VSS . يجب ألا تنسى تهيئة طرف المدخل التناظرى كطرف دخل عن طريق السجل TRIS (مع العلم بأن الوضع الافتراضى لتهيئة جميع المنافذ هو مداخل ) . الشكل أدناه يبين المخطط الصندوقى لموديول ADC .
2- اختيار ADCON=6 يعنى تهيئة جميع الأطراف باعتبارها مداخل / مخارج رقمية .



للتعامل مع المحول ADC ، فإن مترجم الميكروسى برو لديه مكتبة تعرف باسم ADC لإجراء التحويل . هذه المكتبة بها دالة وحيدة هى :

كود:
unsigned ADC_Read(unsigned short channel);
هذه الدالة تعود بنتيجة التحويل 10-bit للقناة المحددة بواسطة البارامتر channel .

مثال:
للتدريب على استخدام هذه المكتبة راقب وحلل المثال التالى :

كود:
 void main (void)
{
	// Declaration of variables.
	unsigned int ADC_result;  
	// Initialize ports.
	TRISB = 0;
	TRISC = 0;
	PORTB = 0;
	PORTC = 0;
	while (1) 				// infinite loop.
	{
		ADC_result = ADC_Read (0); 	// conversion is made on channel 0.
		//  Display 8 least significant bits from  port B.
		PORTB = ADC_result &0xFF;
		//Display  the most significant 2 bits from the port C.
		PORTC = (ADC_result >> 8) &0x03;
	}
}
لمحاكاة هذا البرنامج يجب جلب الأجهزة الآتية فى برنامج ISIS :
16F877A, RES, LEDRED,POT-HG
الشكل التالى يبين الدائرة الكهربية :



بعد تشغيل المحاكاة تعرض الليدات نتيجة قيمة التحويل فى شكل كود ثنائى binary code ، لفرق الجهد التناظرى المغذى بواسطة المقاومة المتغيرة .


الصورة الرمزية burai nuraldaem
burai nuraldaem
:: عضو فضى ::
تاريخ التسجيل: Nov 2015
الدولة: السودان
المشاركات: 501
نشاط [ burai nuraldaem ]
قوة السمعة:
قديم 14-07-2017, 01:03 AM المشاركة 128   
افتراضي




وعليكم السلام ورحمة الله وبركاته
أخى الكريم شكرا جزيلا لك
أهلا ومرحبا بك ، وشكرا للاستاذ ماجد على الثقة

1- المترجم يكتشف الأخطاء اللغوية الخاصة بلغة السى والأخطاء المتعلقة بالميكروكونترولر المستهدف ، كأن تكتب منفذ غير موجود ، ولا يكتشف الأخطاء البرمجية .


2- القيمة 288 تعادل الرقم الثنائى

كود:
00000001 00100000
وبالتالى سوف يتم أخذ الثمانى بتات الأولى فقط ونسخها إلى المنفذ TRISB وهو ما يكافىء مايلى :

كود:
 TRISB=0b00100000;
وبالتالى فى البداية من المفضل استخدام الأعداد الثنائية عند تهيئة المنافذ حيث تكون واضحة وسهلة فى التعرف عليها .

3- قمت بتنفيذ البرنامج كما ذكرته ، وتم ترجمته وأعطى ملف HEX .

مع تمنياتى بدوام التوفيق
كل الشكر والاحترام استاذ فتح الله
ذكرت لي ان المترجم لا يكتشف الاخطاء البرمجيه
لكن اليس هذا يعني اني يمكن ان اكتب كود طوييل يحوي كثير من الاخطاء وعند الترجمه ينتج ملف hex لكن عند العمل الفعلي تكون النتائج مختلفه ولو قليلا عن ما هو متوقع ان يكون

ثانيا استاذ ذكرت ان القيمه 288 لها مناظر ثنائي ويتم اخذ الثماني بتات الاولي فقط
لماذا
او قبل الاسئله من الذي اخذ الثماني بتات المترجم ام قواعد اللغه
السؤال هل السبب ان المايكرو من العائله f16 هو 8 بت فقط
واذا كان المايكرو 32 بت هل سياخذ اكثر من ذلك مع العلم ان كل بايت يتكون من 8 بتات
اخي الكريم شكرا سلفا
ومعذره ان كانت الاسئله غير منطقيه فانا مبتدئ
نقطه اخري هل اسئلتي تفسد تسلسل الشرح ؟؟



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