السلام عليكم
اريد عمل مشروع لقياس المسافة يعتمد على pic16f877a و hc-sr04
المهم أريد اخراج جهد 5 من البيك وبعد دلك اريد اطلاق مؤقت لحساب الوقت بين خروج الاشارة واستقبال اشارة في احد الاطراف ب الميكروا ثانية وهدا ما لم أفهمه المرجو مساعدتي في دلك
هدا كود وجدته لنفس الغرض
كود:
/*
* Project name:
Test du HC-SR04
* Test configuration:
MCU: PIC16F877A
Oscillator: HS, 12.0000 MHz
Ext. Modules: Character LCD 2x16
HC-SR04
SW: mikroC PRO for PIC
*/
// LCD connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB6_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB6_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD connections
char txt1[] = "Test du capteur";
char txt2[] = "HC-SR04";
char txt3[] = "Distance :";
char txt4[7];
unsigned long Cumul;
unsigned tWord,tOld, tNew;
char th,tl;
char edge = 0;
char capture = 0;
float temps = 0;
float distance = 0;
float distance2 = 0;
void interrupt() {
if(PIR1.CCP1IF){ //Si PIR1.CCP1IF égal à 1
if(!edge){ //Si edge égal à 0
CCP1CON = 0x04; // Mode de capture a chaque front descendant
tOld = 256*CCPR1H + CCPR1L; //garde la valeur de départ
edge = 1; //edge prend la valeur 1
}else{
tNew =256*CCPR1H + CCPR1L; //garde la valeur de fin
capture = 1; //indicateur capture términée
edge = 0; //edge prend la valeur 0
}
PIR1.CCP1IF = 0; //remise à 0 du flag (PIR1.CCP1IF)
}
}
void main() {
char i;
TRISB = 0; // PORTB en sortie
PORTB = 0; // Initialisation du PORTB
TRISA = 0; // PortA en sortie
PORTA = 0x00; // Initialisation du PORTA
TRISC = 0; // PortC en sortie
CCP1CON = 0x05; // Mode de capture a chaque front montant
TRISC.F2 = 1; // RC2 en entré
T1CON = 0x21; // timer1 ON, internal clock Fosc/4, prescaler 1:4
INTCON.GIE = 1;
INTCON.PEIE =1;
PIE1.CCP1IE = 1; // active la capture par interruption
PIR1.CCP1IF = 0; //remise à 0 du flag (PIR1.CCP1IF)
Lcd_Init(); // Initialisation du LCD
Lcd_Cmd(_LCD_CLEAR); // Effacer le LCD
Lcd_Cmd(_LCD_CURSOR_OFF); // Desactivation du curseur
Lcd_Out(1,2,txt1); // Ecrire text 1
Lcd_Out(2,6,txt2); // Ecrire text 2
Delay_ms(2000);
Lcd_Cmd(_LCD_CLEAR); // Effacer le LCD
PORTA = 0x01; // Envoi une impulsion
Delay_us(10); // de 10 microsecondes
PORTA = 0x00; // dans la broche RA1
while(1)
{
if(capture){
PIE1.CCP1IE = 0; //desactive la capture par interruption
capture = 0; // Capture prend la valeur 0
tWord = ~tOld + tNew+1; //Calculer la longueur de l'impulsion de front montant à front montant
CCP1CON = 0x05; // Mode de capture a chaque front montant
// tword contiennent longueur d'impulsion en micro seconde
temps =((float)tWord*4)/3;
distance = ((float)temps*17)/1000; //calcul de la distance en cm
floatToStr(distance,txt4);
Delay_ms(70);
PIR1.CCP1IF = 0; //remise à 0 du flag (PIR1.CCP1IF)
PIE1.CCP1IE = 1; // enable interrupt
if(distance !=distance2){
Lcd_Cmd(_LCD_CLEAR); // Effacer le LCD
Lcd_Cmd(_LCD_CURSOR_OFF); // Desactivation du curseur
Lcd_Out(1,1,txt3); // Ecrire text 3
Lcd_Out(2,8,txt4); // Afficher distance
}
distance2 = distance;
PORTA = 0x01; // Envoi une impulsion
Delay_us(10); // de 10 microsecondes
PORTA = 0x00; // dans la broche RA1
}
}
}
|
اخى العزيز البرنامج يستخدم موديول الالتقاط الموجود بالبك و فكرة هذا الموديول هو ان تقوم بضبط احد التايمرات الخاصه بالبك و فى الاغلب يكون تايمر1 بالعمل تبعا لنظام محدد و تنتظر قدوم الاشارة و عند قدوم الاشارة على الطرف ccp1 او ccp2 عندئذ يقوم موديول الالتقاط بتسجيل قيمه تايمر(1 الذى يعمل فى خلفيه البرنامج ) فى السجل ccpr1 و لحساب المدة الزمنيه بين قدوم اشارتين سيقوم الموديول بتسجيل قيمه تايمر1 فى الاشارة الاولى ويحفظها فى متغير ( فلنسميه old) ثم ينتظر لقدوم اشارة اخرى ويسجل قيمه تايمر1 فى متغير اخر ( فلنسميه new) وعند طرح قيمتى المتغيرين نحصل على عدد مرات تايمر1 و لكن ما الاستفادة الحقيقيه من معرفه عدد عدات تايمر1 بين حدثين ( الاشارتين ) ؟
عندما يعمل تايمر1 كمؤقت و ليس عداد عندئذ كل زيادة فى قيمه تايمر1 تمثل زمن تنفيذ تعليمه واحدة , اذن اذا علمنا زمن تنفيذ تعليمه البك سنتمكن من معرفه الزمن بين الحدثين.
زمن تنفيذ التعليمه يحسب كالاتى
زمن تنفيذ التعليمه (الناتج بالثانيه)= ( 4 * prescaler of TMR )/ تردد الكريستاله المستخدمه بالهرتز
من القانون السابق يتضح لك ان زمن تنفيذ التعليمه الواحدة لبك يعمل بكريستاله 4 ميجا هو واحد مايكرو ثانيه(اذا كانت قيمه prescaler 1:1) و بالتالي اذا اتضح ان فرق العدد بين تايمر1 فى الاشارة الاولى عن الاشارة الثانيه فلنفترض مثلا 1000 اذن يكون الزمن بين الاشارتين هو 1000 مايكرو ثانيه اى واحد ملى ثانيه .
ارجو ان اكون اوضحت الفكرة بشكل عام و ان اردت معرفه تقنيات استخدام موديول الالتقاط اخبرني و سأحاول مساعدتك بقدر معرفتى لأنى قمت من قبل بعمل ريموت كنترول يعمل بتلك الخاصيه و لكنى لم اعرف كيفيه وضع الشرح كالاخوه الكرام فى المنتدى و بالتالي لم يلاقي شرحي القبول.