PWM değerlerini okuma hakkında..

Başlatan muhittin_kaplan, 15 Şubat 2011, 21:29:26

muhittin_kaplan

4 Kanaldan gelen PWM sinyalin herbirinin duty sini ölçmem gerekiyor. Hızlı Yoldan Nasıl yapabilirim ?
Önerileriniz ve Çözülerimlerinize açığım.



Duty 1ms ile 2ms arasında değişiyor.

serdararikan

1-   4 girişli CCP kanalı olan bir mcu ile
2-   PIC deki PORTB nin son dört pininin değişme kesmesi ile

iyildirim

Eğer senkron sinyali de varsa sadece 2 giriş kullanılarak da yapılabilir.

Kullanılacak işlemci ve derleyici nedir bilmiyorum ancak çok kanal okumaya örnek olması açısından 128MC710 için

struct radioType{
	signed int riseCount;
	signed int fallCount;
	signed int IC_Period;
	signed int IC_time;
	double IC_Val;
	unsigned int portSignal;
	int stat1;
	int stat2;
	const int *ICBufPtr;
	const int *ICPort;
	}; 


#define NUM_RADIO_CHANNEL 8

#define IC_CHANNEL1	PORTDbits.RD8
#define IC_CHANNEL2	PORTDbits.RD9
#define IC_CHANNEL3	PORTDbits.RD10
#define IC_CHANNEL4	PORTDbits.RD11
#define IC_CHANNEL5	PORTDbits.RD12
#define IC_CHANNEL6	PORTDbits.RD13
#define IC_CHANNEL7	PORTDbits.RD14
#define IC_CHANNEL8	PORTDbits.RD15

#define IC_CHANNEL1_TRIS TRISDbits.RD8
#define IC_CHANNEL2_TRIS TRISDbits.RD9
#define IC_CHANNEL3_TRIS TRISDbits.RD10
#define IC_CHANNEL4_TRIS TRISDbits.RD11
#define IC_CHANNEL5_TRIS TRISDbits.RD12
#define IC_CHANNEL6_TRIS TRISDbits.RD13
#define IC_CHANNEL7_TRIS TRISDbits.RD14
#define IC_CHANNEL8_TRIS TRISDbits.RD15


struct radioType radioBuf[NUM_RADIO_CHANNEL];

void Init_RadioIC()
{



	T3CONbits.TCS = 0;
	T3CONbits.TCKPS = TIMER3_PRESCALER;		//0b10;// 
	TMR3 = 0x00; // Clear timer register
	PR3 = 30000;//TIMER3_PERIOD; // Load the period value   30000->40MHZ ICIN 


	
	TRISD = 0b1111111100000000;	 //PORT D8-13 IC Input D0-7 OC SERVO OUTPUT
			  
{//bit 2-0 ICM<2:0>: Input Capture x Mode Select bits
//	111 = Input capture functions as interrupt pin only when device is in Sleep or Idle mode (rising edge detect only, all other control bits are not applicable)
//	110 = Unused (Input Capture module disabled)
//	101 = Capture mode, every 16th rising edge
//	100 = Capture mode, every 4th rising edge
//	011 = Capture mode, every rising edge
//	010 = Capture mode, every falling edge
//	001 = Capture mode, every edge – rising and falling (ICI<1:0> bits do not control interrupt generation for this mode)
//	000 = Input Capture module turned off 
}


/*	IC1CONbits.ICM=0b00; // Disable Input Capture 1 module
	IC1CONbits.ICTMR= 1; // Select Timer2 as the IC1 Time base
	IC1CONbits.ICI= 0b00; // Interrupt on every capture event
	IC1CONbits.ICM= 0b001; // Generate capture event on every Rising edge  */

	radioBuf[1].ICBufPtr = (int *)&IC1BUF;
	radioBuf[2].ICBufPtr = (int *)&IC2BUF;
	radioBuf[3].ICBufPtr = (int *)&IC3BUF;
	radioBuf[4].ICBufPtr = (int *)&IC4BUF;
	radioBuf[5].ICBufPtr = (int *)&IC5BUF;
	radioBuf[6].ICBufPtr = (int *)&IC6BUF;
	radioBuf[7].ICBufPtr = (int *)&IC7BUF;
	radioBuf[8].ICBufPtr = (int *)&IC8BUF;


	IC1CON = IC2CON = IC3CON = IC4CON = IC5CON = IC6CON = IC7CON = IC8CON = 0b0000000000000001; 
//  	                                                          x        TIMER3
//															       xx      ICI ınterrupt on every capture 
//          	       											       xxx ICM capture every edge 
	IPC0bits.IC1IP = IPC1bits.IC2IP = IPC9bits.IC3IP = IPC9bits.IC4IP = IPC9bits.IC5IP = IPC10bits.IC6IP = IPC5bits.IC7IP = IPC5bits.IC8IP = 1; // Setup IC1 interrupt priority level
	IFS0bits.IC1IF = IFS0bits.IC2IF = IFS2bits.IC3IF = IFS2bits.IC4IF = IFS2bits.IC5IF = IFS2bits.IC6IF = IFS1bits.IC7IF = IFS1bits.IC8IF = 0;	// Clear IC Interrupt Status Flag
	IEC0bits.IC1IE = IEC0bits.IC2IE = IEC2bits.IC3IE = IEC2bits.IC4IE = IEC2bits.IC5IE = IEC2bits.IC6IE = IEC1bits.IC7IE = IEC1bits.IC8IE = 1;	// Enable IC interrupt Routine
	T3CONbits.TON = 1; // Enable Timer
	

}

void getICValue(unsigned char ICChannel, unsigned char bitval)
{
	
	int lTmp = 0;
	
	if (bitval == 1){
		radioBuf[ICChannel].riseCount = (*radioBuf[ICChannel].ICBufPtr);
	}
	else{
		radioBuf[ICChannel].fallCount = (*radioBuf[ICChannel].ICBufPtr);

		if (radioBuf[ICChannel].fallCount >= radioBuf[ICChannel].riseCount)
			lTmp = radioBuf[ICChannel].fallCount - radioBuf[ICChannel].riseCount;
	
		else
			lTmp = (PR3 - radioBuf[ICChannel].riseCount) + radioBuf[ICChannel].fallCount;
		
			radioBuf[ICChannel].IC_Period = lTmp - TIMER3_1_5_MS;

			radioBuf[ICChannel].IC_Val = ((double)radioBuf[ICChannel].IC_Period / (double)TIMER3_0_5_MS);

	}

}	



void __attribute__((__interrupt__,__auto_psv__)) _IC1Interrupt(void)
{
	getICValue(1, PORTDbits.RD8);
	IFS0bits.IC1IF = 0;
}

void __attribute__((__interrupt__,__auto_psv__)) _IC2Interrupt(void)
{
	getICValue(2, PORTDbits.RD9);
	IFS0bits.IC2IF = 0;
}	

void __attribute__((__interrupt__,__auto_psv__)) _IC3Interrupt(void)
{
	getICValue(3, PORTDbits.RD10);
	IFS2bits.IC3IF = 0;
}	

void __attribute__((__interrupt__,__auto_psv__)) _IC4Interrupt(void)
{
	getICValue(4, PORTDbits.RD11);
	IFS2bits.IC4IF = 0;
}	

void __attribute__((__interrupt__,__auto_psv__)) _IC5Interrupt(void)
{
	getICValue(5, PORTDbits.RD12);
	IFS2bits.IC5IF = 0;
}	

void __attribute__((__interrupt__,__auto_psv__)) _IC6Interrupt(void)
{
	getICValue(6, PORTDbits.RD13);
	IFS2bits.IC6IF = 0;
}	

void __attribute__((__interrupt__,__auto_psv__)) _IC7Interrupt(void)
{
	getICValue(7, PORTDbits.RD14);
	IFS1bits.IC7IF = 0;
}	

void __attribute__((__interrupt__,__auto_psv__)) _IC8Interrupt(void)
{
	getICValue(8, PORTDbits.RD15);
	IFS1bits.IC8IF = 0;
}



muhittin_kaplan


muhittin_kaplan


iyildirim

#5
Evet hocam Input Capture kullanılıyor

MC710'da 8 IC (Input Capture) girişi var.

IC modülü timer3'e bağlı.  İşlemci yaklaşık 40MIPS de. timer3 prescale 1:8 ayarlı. Timer3 sayacı 6ms gibi bir değere ayarlı.

IC modülü hem düşen hemde yükselen kenar için capture ediyor.  8 kanal için de kesmeleri aktif ediyoruz.

getICValue içerisindeki kodları 8 kanal için tekrar tekrar yazmamak için, burada kullanmak için
radioBuf[1].ICBufPtr = (int *)&IC1BUF;

şeklinde her bir kanalın değerlerini okuduğumuz register adreslerini bir yapı içerisindeki pointer değişkene atıyoruz.

Kesme gerçekleştiğinde getICValue procedure'ünü ilgili kanala ait indis ve port değeri ile
getICValue(1, PORTDbits.RD8);

şeklinde çağırıyoruz.

Eğer port değeri 1 ise timer3 ün o andaki değerini risecount değişkenine atıyoruz. Port 0 yani düşen kenar ise  timer3 değeri fallcount'a atanıyor. Artık kenar düştüğüne göre period hesaplama zamanı gelmiş oluyor.
if (radioBuf[ICChannel].fallCount >= radioBuf[ICChannel].riseCount)
			lTmp = radioBuf[ICChannel].fallCount - radioBuf[ICChannel].riseCount;
	
		else
			lTmp = (PR3 - radioBuf[ICChannel].riseCount) + radioBuf[ICChannel].fallCount;
		
			radioBuf[ICChannel].IC_Period = lTmp - TIMER3_1_5_MS;

Kısmında kenar yükseldikten sonra timer3 resetlendi ise düşen kenara ait timer sayacı değerinin daha küçük olacağını da değerlendirip darbenin süresini hesaplayıp period değişkenine atıyoruz.