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

   

الصورة الرمزية assed
assed
:: عضو فضي ::
تاريخ التسجيل: Jul 2014
الدولة: العراق - بغداد
المشاركات: 1,034
نشاط [ assed ]
قوة السمعة:
قديم 06-06-2017, 12:05 AM المشاركة 65   
افتراضي



السلام عليكم
أستاذنا العزيز لقد كتبت هذا الكود للجزء الاول من البرنامج ولاكنه لم يفلح في العمل فقط ليد الاول يعمل. طبعاً يجب ان تتحملني شوي انا متلخبص بين البيسك والسي
كود:
void main(void)
{
   unsigned int c;
c=0;
TRISB = 0;
PORTB = 0;

while(c<10)break;
{
portb = 1;
delay_ms (1000);
portb = portb >>1;

++c;

  
  
 }
 }
فأين المشكلة بالموضوع... قمت بمراجعة الموضوع بالكامل
اعتقد راح تتعب معي . او أعود الى برنامجي المفضل protonBasic

اعلانات

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


مشكلة الارتداد فى المفاتيح SWITCHES والمفاتيح الضاغطة PUSH-BUTTONS وطرق علاجها
المشكلة :
ربما تكون المفاتيح والمفاتيح الضاغطة هى أبسط الأجهزة والتى توفر أبسط طريقة للكشف عن مظهر الجهد على طرف مدخل الميكروكونترولر . ومع ذلك فإنها ليست بسيطة كما تبدو... السبب في ذلك هوالارتداد bounce الذى يحدث فى تلامساتها .




إرتداد التلامس مشكلة مشتركة مع المفاتيح الميكانيكية. عندما تتصادم التلامسات بعضها ببعض فإن خواصها الميكانيكية ( كمية الحركة momentum والمرونة elasticity ) تعمل معا وتسبب ظاهرة الارتداد bounce . وتكون النتيجة تولد نبضات سريعة من التيار الكهربائى بدلا من الانتقال النظيف المثالى (الخالى من تلك النبضات) من الصفر إلى التيار الكامل . وغالبا ما يحدث ذلك بسبب الاهتزازات vibrations والبقع الخشنة الصغيرة والأوساخ بين التلامسات . هذا التأثير غير ملحوظ عادة عند استخدام هذه المكونات في الحياة اليومية لأن الارتداد يحدث بسرعة كبيرة تؤثر على معظم المعدات. ومع ذلك ، فإنه يسبب مشاكل في بعض الدوائر التناظرية والمنطقية والتى تستجيب بسرعة كافية فتفسر نبضات التوصيل والفصل on/off على أنها بيانات متدفقة . على أي حال فالعملية برمتها لا تدوم طويلا ( قليل من الميكرو أو الملى ثوانى )ولكنها طويلة بما يكفي ليتم تسجيلها بواسطة الميكروكونترولر . عندما لا يستخدم سوى المفتاح الضاغط كمصدر لعداد counter إشارة تحدث أخطاء فى ما يقرب من 100 ٪ من الحالات!

الحل :
يمكن حل هذه المشكلة بسهولة من خلال ربط دائرة RC بسيطة لإخماد التغييرات السريعة فى الجهد. وحيث أن فترة الارتداد غير معروفة فإن قيم المكونات غير محددة بدقة . في معظم الحالات من المستحسن استخدام القيم كما هو مبين في الشكل أدناه :





إذا كانت هناك حاجة للاستقرار التام complete stability ينبغي اتخاذ تدابير جذرية. الخرج من الدائرة التالية ( قلاب RS flip-flop ) سوف يغير حالته المنطقية فقط بعد الكشف عن أول نبضة منطلقة من إرتداد التلامس .هذا الحل هو أكثر تكلفة بسبب المفتاح (SPDT قطب واحد ودائرتين ) والدائرة المتكاملة ولكن بالتأكيد هو حل للمشكلة.



بالإضافة إلى هذا الحل الذى يعتمد على الأجهزة hardware هناك أيضا حل برمجى بسيط.
عندما يقوم البرنامج باختبار الحالة المنطقية لطرف المدخل وكشف التغير , ينبغي أن يتم التحقق مرة أخرى بعد تأخير زمنى معين . إذا أكد البرنامج التغيير ، فهذا يعني أن المفتاح أو المفتاح الضاغط قد غير من وضعه . مزايا مثل هذا الحل واضحة : فهو مجانى ، ويتم التخلص من آثار إرتداد التلامس علاوة على إمكانية تطبيقه على التلامسات ذات الجودة الأقل .

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

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


السلام عليكم
أستاذنا العزيز لقد كتبت هذا الكود للجزء الاول من البرنامج ولاكنه لم يفلح في العمل فقط ليد الاول يعمل. طبعاً يجب ان تتحملني شوي انا متلخبص بين البيسك والسي
كود:
void main(void)
{
   unsigned int c;
c=0;
TRISB = 0;
PORTB = 0;

while(c<10)break;
{
portb = 1;
delay_ms (1000);
portb = portb >>1;

++c;

  
  
 }
 }
فأين المشكلة بالموضوع... قمت بمراجعة الموضوع بالكامل
اعتقد راح تتعب معي . او أعود الى برنامجي المفضل protonBasic
كل عام وأنت بخير

هل تقصد مثل هذا الشكل :

كود:
void main(void)
{
   unsigned int c;
   c=0;
   TRISB = 0;
   PORTB = 1;


           while(c<80)
           {

           delay_ms (1000);
           portb = portb <<1;
           if(portb==0) portb=1 ;

           ++c;

           }

 }
1- كتابة portb=1 داخل حلقة التكرار تجعل فى كل تكرر نفس الشىء ولذا يجب وضعها خارج الحلقة .
2- وجود break بعد عبارة while مباشرة يعطل عملها وكأنها غير موجودة .
3- الإزاحة يجب أن تكون جهة اليسار لإن portb=1 تعنى وضع واحد فى أول بت جهة اليمين ويتم تحركها إلى جهة اليسار .
4- البرنامج أعلاه لا يعطى النتيجة المرجوة تماما .

ملحوظة :
عبارة التكرار while تأخذ شكلين :
تكرار عبارة واحدة :

كود:
while (expression) statement ;
وهو الشكل الذى استخدمته ، ولكن مع عبارة break وبالتالى أصبحت العبارات الموجودة داخل الأقواس "خارج حلقة التكرار" وتعتبر عبارات مستقلة .

أو تكرار عبارات :

كود:
while (expression) {

statements

}
فيما يلى شكل البرنامج المستقل

كود:
void main(void)
{

   TRISB = 0;
   PORTB = 1;


           while(1)
           {

           delay_ms (1000);
           portb = portb <<1;
           if(portb==0) portb=1 ;

           }

 }

أو :

كود:
void main()
{
	unsigned char J = 1;
	TRISB= 0;
	
	for(;;) // Endless loop
	{
		PORTB = J; 			// Send J to PORTB
		Delay_ms(1000); 	// Delay 1 second
		J = J << 1; 		// Shift left J
		if(J == 0) J = 1; 	// If last LED, move to first LED
}
}

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


التعديل الأخير تم بواسطة : F.Abdelaziz بتاريخ 06-06-2017 الساعة 12:39 PM

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


طريقة توصيل وبرمجة المفتاح مع الميكروكونترولر :
المفتاح ، ببساطة ، "يغلق" closes أو "يفتح" opens دائرة . لكن الميكروكونترولر هو جهاز رقمى والذى يفهم فقط الصفر “0”(0V) أو الواحد “1”(5V) . لذلك نحن بحاجة لدائرة تبين حالة المفتاح بدلالة “0” أو “1” .
الشكل التالى يبين طريقتى توصيل المفتاح مع الميكروكونترولر .



• إذا كان توصيل المفتاح وهو "مفتوح" يطبق “0” على طرف الدخل ، وهو "مغلق" يطبق “1” على طرف الدخل ، يقال أن المفتاح "فعال فى الحالة المرتفعة" active high .
• وإذا كان توصيل المفتاح وهو "مفتوح" يطبق “1” على طرف الدخل ، وهو "مغلق" يطبق “0” على طرف الدخل ، يقال أن المفتاح "فعال وهو فى الحالة المنخفضة" active low .
ومن ثم ، إذا تم توصيل المفتاح بحيث يذهب إلى “0” عند الضغط عليه ، فهو فعال فى الحالة المنخفضة ، وإذا تم توصيله بحيث يذهب إلى “1” عند الضغط عليه ، فإنه يكون فعال فى الحالة المرتفعة .
الشكل التالى يبين توصيل مفتاح فعال فى الحالة المرتفعة (A) ، ومفتاح فعال فى الحالة المنخفضة (B) . المقاومة تحافظ على الدخل فى الحالة "الغير فعالة" حتى يتم غلق المفتاح ، عند هذه النقطة يتم سحب الدخل إلى "الحالة الفعالة" . يمكنك التفكير فى ذلك كمقسم جهد ، مقاومة المفتاح تكون مرتفعة جدا وهو مفتوح وتكون صفر وهو مغلق .
مقاومةالسحب لأعلى pullup ( موصلة بين طرف الدخل والجهد الموجب )أو مقاومة السحب لأسفل pulldown (موصلة بين طرف الدخل والأرضى) ، والتى قد تكون مدمجة فى بناء الميكروكونترولر أو قد تكون عنصر خارجى ، تكون فى المدى من 10 إلى 100 كيلو أوم .





الصورة الرمزية assed
assed
:: عضو فضي ::
تاريخ التسجيل: Jul 2014
الدولة: العراق - بغداد
المشاركات: 1,034
نشاط [ assed ]
قوة السمعة:
قديم 07-06-2017, 02:09 AM المشاركة 69   
افتراضي




كل عام وأنت بخير

هل تقصد مثل هذا الشكل :

كود:
void main(void)
{
   unsigned int c;
   c=0;
   TRISB = 0;
   PORTB = 1;


           while(c<80)
           {

           delay_ms (1000);
           portb = portb <<1;
           if(portb==0) portb=1 ;

           ++c;

           }

 }
1- كتابة portb=1 داخل حلقة التكرار تجعل فى كل تكرر نفس الشىء ولذا يجب وضعها خارج الحلقة .
2- وجود break بعد عبارة while مباشرة يعطل عملها وكأنها غير موجودة .
3- الإزاحة يجب أن تكون جهة اليسار لإن portb=1 تعنى وضع واحد فى أول بت جهة اليمين ويتم تحركها إلى جهة اليسار .
4- البرنامج أعلاه لا يعطى النتيجة المرجوة تماما .

ملحوظة :
عبارة التكرار while تأخذ شكلين :
تكرار عبارة واحدة :

كود:
while (expression) statement ;
وهو الشكل الذى استخدمته ، ولكن مع عبارة break وبالتالى أصبحت العبارات الموجودة داخل الأقواس "خارج حلقة التكرار" وتعتبر عبارات مستقلة .

أو تكرار عبارات :

كود:
while (expression) {

statements

}
فيما يلى شكل البرنامج المستقل

كود:
void main(void)
{

   TRISB = 0;
   PORTB = 1;


           while(1)
           {

           delay_ms (1000);
           portb = portb <<1;
           if(portb==0) portb=1 ;

           }

 }

أو :

كود:
void main()
{
	unsigned char J = 1;
	TRISB= 0;
	
	for(;;) // Endless loop
	{
		PORTB = J; 			// Send J to PORTB
		Delay_ms(1000); 	// Delay 1 second
		J = J << 1; 		// Shift left J
		if(J == 0) J = 1; 	// If last LED, move to first LED
}
}

مع تمنياتى بدوام التوفيق
شكراً لك أستاذ فتح الله عبد العزيز الكود الاخير في هذه المشاركة أشتغل بشكل سليم .. while(c<80) من اين اتت 80 هل هي حركة البرنامج بالكامل ؟
ولي سؤال اخر دالة function هل تقابلها دالة GoSub في البروتون بيسك ؟
مع جزيل الشكر والتقدير.


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


شكراً لك أستاذ فتح الله عبد العزيز الكود الاخير في هذه المشاركة أشتغل بشكل سليم .. while(c<80) من اين اتت 80 هل هي حركة البرنامج بالكامل ؟
ولي سؤال اخر دالة function هل تقابلها دالة GoSub في البروتون بيسك ؟
مع جزيل الشكر والتقدير.
عفوا أخى الكريم :
1- نعم هى حركة البرنامج بالكامل : فى كل دورة تكرار يتم الإزاحة لبت واحدة ، البايت أو سجل المنفذ 8 بتات بعد 8 دورات تصبح بتات السجل بأصفار ولنبدأ من جديد وضعنا الواحد مرة أخرى .
الإزاحة 8 مرات تصنع حركة واحدة من أقصى اليمين إلى أقصى اليسار ، تكرار 10 حركات تعنى 80 دورة تكرار .
2- نعم الدالة مثل البرنامج الفرعى .
مع تمنياتى بدوام التوفيق


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


برمجة المداخل الرقمية )المفتاح على سبيل المثال( :
الدائرة الكهربية :




• يتم توصيل المفتاح الضاغط إلى طرف البت الأولى بالمنفذ PORTD أى RD0 ، والذى يجب تهيئته كطرف دخل ، يتم توصيل المفتاح بحيث يكون فعال فى الحالة المنخفضة ، ولذلك يتم توصيل مقاومة سحب لأعلى (رفع) بين طرف الدخل RD0 والجهد الموجب (5V)VDD ، ويتم توصيل المفتاح بين هذا الطرف والأرضى . نتيجة لذلك تكون حالة طرف الدخل RD0 عند الحالة المنطقية المرتفعة High(5V)(1) "عندما يكون المفتاح غير مضغوط" (غير فعال) .
• عند الضغط على المفتاح (فعال) فإن طرف الدخل RD0 سوف يتصل بالأرضى وتتحول حالته إلى الحالة المنطقية المنخفضة Low(0V)(0) .
• الليد المتصل بطرف الخرج PORTB(RB0) ، خلال مقاومة تحديد التيار ، سوف يومض عند الضغط على المفتاح .
• يقوم الميكروكونترولر "تلقائيا" بالكشف (قراءة) على طرف الدخل وتسجيل حالته فى البت المناظرة وكل ما عليك هو اختبار حالة هذه البت بعبارات الشرط المعروفة ، كما فى البرنامج التالى .


تطبيق :
برنامج لتشغيل وتبطيل ليد (أو أى حمل) بمفتاح واحد .
• فى البداية يكون المفتاح فى الوضع المفتوح (غيرفعال) ، ويكون طرف الدخل RD0 فى الحالة المرتفعة ، وشرط العبارة if(PORTD.F0 == 1) يكون صواب true ، ومن ثم يتم تنفيذ العبارتين Delay_ms(10) (زمن تأخير لتلاشى الارتدادات ) ، و oldstate = 1 ( للإشارة إلى أن الدخل عند الحالة الابتدائية المرتفعة) .
• بعد ذلك يكون الميكروكونترولر فى انتظار الضغط على المفتاح ليكمل تنفيذ البرنامج .
• عندما يتم الضغط على المفتاح تتحول حالة طرف الدخل RD0 من الحالة المرتفعة (1) إلى الحالة المنخفضة (0) (الحالة الفعالة) ، ومن ثم يتحقق شرط العبارة if (oldstate && PORTD.F0 == 0) ، وهو شرط مركب من شرطين oldstate "و" && PORTD.F0 == 0 ، ويتم تنفيذ الثلاثة عبارات التابعة لها : Delay_ms(10) (زمن تأخير تلاشى الارتدادات ) ، وعبارة الفعل المطلوب وهى
PORTB.F0 = ~PORTB.F0 (عكس حالة الطرف RB0 ، فإن كان off(0) يصبح on(1) والعكس بالعكس ، و العبارة oldstate = 0 للعودة إلى الحالة الابتدائية انتظارا للضغطة التالية .
• نتيجة لذلك عند الضغطة الأولى يتم إضاءة الليد ، وعند الضغطة التالية يتم إطفاء الليد ، وتتكرر العملية . بعبارة أخرى ، فى كل مرة يتم فيها الضغط على المفتاح يتحول الليد بين التشغيل on والفصل off . بمجرد أن يتم الضغط على المفتاح فإن الميكروكونترولر سوف ينتظر تحرير الضغط للرجوع إلى الحالة الابتدائية وذلك قبل الكشف عن ضغطة أخرى .

كود:
bit oldstate;
void main()
{
oldstate=0;
TRISD.F0 = 1; 	//pin RD0 as input – it doesn’t matter if you are using F0 or B0
TRISB = 0x00; 	// PORTB as output
PORTB = 0x00; 	// PORTB pins are all “off”

while(1) 					// Endless loop
{
if(PORTD.F0 == 1) 			// Detect logical one , oldstate

{
Delay_ms(10); 			// “debouncing” mechanical contacts
oldstate = 1; 				// Update flag
}

if (oldstate && PORTD.F0 == 0)		 // Detect one-to-zero transition , pressed

{
Delay_ms(10); 			// “debouncing” mechanical contacts
PORTB.F0 = ~PORTB.F0; 		//Action >>> Invert PORTB.F0
oldstate = 0; 				// Update flag , Initial condition 
}
} 
}
النتائج :
















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


تدريب :

كود:
void main()
{
  TRISD.F0 = 1; 				//Configure 1st bit of PORTD as input
  TRISB.F0 = 0; 				//Configure 1st bit of PORTB as output
  PORTB.F0 = 0; 				//LED OFF
  while(1)
  {
    	if(PORTD.F0 == 0)   		//If the switch is pressed
    	{
       		Delay_ms(10);    		//Switch Debounce
       		if(PORTD.F0 == 0)		//If the switch is still pressed
       		{
         			PORTB.F0 = 1; 	//LED ON
         			Delay_ms(500); 	//0.5 Second Delay
         			PORTB.F0 = 0; 	//LED OFF
Delay_ms(500); 	//0.5 Second Delay
       		}
    	}
 }
}
فى هذا البرنامج :
• فى البداية ، وكالعادة، يتم تهيئة منافذ الدخل والخرج .
• بمجرد تشغيل البرنامج ، يتم قراءة حالة طرف الدخل RD0 ، وتكون فى الحالة المرتفعة (المفتاح غير مضغوط) ، وعند الدخول إلى الحلقة الغير منتهية نجد أن شرط العبارة if(PORTD.F0==0) غير متحقق false ولا يتم تنفيذ جسمها ، ويكون الليد مطفأ .
• عند الضغط على المفتاح تتحول حالة طرف الدخل RD0 إلى الحالة المنخفضة (0) ، ويتحقق true شرط عبارة if ويتم تنفيذ جسمها ، حيث التأخير 10 ملى ثانية ، ومرة أخرى نجد عبارة الشرط الثانية if(PORTD.F0==0) ، فإذا كان المفتاح مازال مضغوطا يكون شرطها متحقق true ويبد تنفيذ جسمها الذى يحتوى على وميض الليد المتصل بالطرف RB0 .
• عند رفع الضغط من على المفتاح تعود حالة الطرف إلى الحالة المرتفعة ونعود إلى الحالة الابتدائية ( الشروط أصبحت false).

لعلك لاحظت ما يلى :
• أنه يتم اختبار حالة المفتاح مرتين (باستخدام عبارة if ) ، بتأخير 10 ملى ثانية . هذا الزمن لازم لتجنب ظهور تأثير الارتدادات التى تحدث نتيجة غلق وفتح المفتاح debouncing .
• تأثير المفتاح (الوميض) يكون "أثناء الضغط علية" ، ويزول بعد تحرير المفتاح .




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