Home › Forums › Microcontrollers › PIC Microcontroller › Using Capture and Compare mode together – PIC 12F1840
- This topic has 4 replies, 2 voices, and was last updated 7 years, 10 months ago by GITANJALI.
-
AuthorPosts
-
February 2, 2017 at 4:07 pm #13455GITANJALIParticipant
Hello,
I am working on PIC 12F1840 and MPLABX IDE 3.35 . I have written a code for reading PWM pulse width at one pin and writing that value to another PWM pin. But, at the time of simulation in logic analyzer output PWM pulse is not continuous. Is it a correct way to use capture mode and compare mode in one code ? Please check following code and guide me.
/* * File: general.c * Author: Murumkar * * Created on 25 January, 2017, 9:27 AM * * * read input (freq 400Hz) RA2 pulse width and write to RA5 (PWM with freq 18Kz) * * */ #include <stdio.h> #include <stdlib.h> #include <xc.h> #pragma config FOSC =INTOSC, PLLEN =OFF, WDTE =OFF, MCLRE =ON, #pragma config CLKOUTEN =OFF, IESO =OFF, FCMEN =OFF,CP =OFF, CPD =OFF,BOREN=OFF #pragma config WRT=OFF,STVREN=ON,BORV=LO,LVP=OFF unsigned char counter=0;//Overflow counter int count = 0; unsigned char timer1_value1 @ 0x2020; unsigned char timer1_value2 @ 0x2040; unsigned int timer1_value @ 0x2060; unsigned int Pulse @ 0x2080; unsigned int PulseWidth @ 0x20A0; delay() { int i; for(i=0;i<30;i++) { ; } } void pwm_start() { TRISAbits.TRISA2 = 1; APFCONbits.CCP1SEL = 0; CCP1CONbits.CCP1M = 0x05; // capture mode with each rising edge TRISAbits.TRISA2 = 0; TRISAbits.TRISA2 = 1; // RA2 as input ANSELAbits.ANSA2 = 0; // RA2 as Digital } void init_interrupt() { INTCONbits.GIE = 1; // enable global interrupt INTCONbits.PEIE = 1; // enable peripheral interrupt PIE1bits.TMR1IE = 1; // enable timer 1 PIE1bits.CCP1IE = 1; // enable capture mode interrupt } void pwm_again_start() { TRISAbits.TRISA5 = 1; // RA5 APFCONbits.CCP1SEL = 1; // CCP1 function on RA5 CCP1CONbits.CCP1M = 0x0C; // PWM mode: P1A active-high; P1B active-high CCP1CONbits.P1M = 0x00; // Single output; P1A modulated; P1B assigned as port pins PR2 = 0xDD; // CCPR1L = 0x00; // UPDATE PWM TON=0 CCP1CONbits.DC1B = 0x00; // the two LSbs of the PWM duty CYCLE PIR1bits.TMR2IF = 0; // TIMER2 FLAG CLEAR T2CONbits.T2CKPS = 0x00; // PRESCALER 1 T2CONbits.TMR2ON = 1; // TIMER 1 TRISAbits.TRISA5 = 0; // } void SetPWMDutyCyle(unsigned int duty_cycle_value) { CCP1CONbits.DC1B = duty_cycle_value & 0x03; // two LSbs of the PWM duty cycle. CCPR1L = (duty_cycle_value >> 2); // MSB VALUES while(PIR1bits.TMR2IF==1) { PIR1bits.TMR2IF =0; } T2CONbits.TMR2ON = 1; // TIMER 1*/ delay(); } void interrupt ISR() { if(PIE1bits.CCP1IE && PIR1bits.CCP1IF) { count++; if(count==1) { T1CONbits.TMR1ON = 1; // start timer 1 PORTAbits.RA1 = ~PORTAbits.RA1; counter = 0; PIR1bits.CCP1IF = 0; CCP1CONbits.CCP1M = 0x04; // capture mode with each falling edge timer1_value1 = TMR1L; timer1_value2 = TMR1H; timer1_value = timer1_value1 + (((int)TMR1H) << 8); } else if(count==2) { count = 0; PORTAbits.RA1 = ~PORTAbits.RA1; INTCONbits.GIE = 0; // disable global interrupt INTCONbits.PEIE = 0; // disable peripheral interrupt PIE1bits.TMR1IE = 0; // disable timer 1 PIE1bits.CCP1IE = 0; // disable capture mode interrupt counter = 0; PIR1bits.CCP1IF = 0; CCP1CONbits.CCP1M = 0x05; // capture mode with each rising edge timer1_value1 = TMR1L; timer1_value2 = TMR1H; Pulse = timer1_value1 + (((int)TMR1H) << 8); PulseWidth = Pulse - timer1_value; pwm_again_start(); SetPWMDutyCyle(PulseWidth); pwm_start(); init_interrupt(); } } } void micro_init() { OSCCONbits.SPLLEN = 0; // PLL DISABLE OSCCONbits.IRCF = 0x0F; // 16 MHZ INTERNAL FREQ OSCCONbits.SCS = 0x02; // INTERNAL OSCILLATR BLOCK } void main() { micro_init(); pwm_start(); TRISAbits.TRISA1 = 0; // RA1 as output ANSELAbits.ANSA1 = 0; // RA1 as digital TRISAbits.TRISA2 = 1; // RA2 as input ANSELAbits.ANSA2 = 0; // RA2 as Digital TRISAbits.TRISA5 = 0; // RA5 as output init_interrupt(); while (1) { ; } }
thanking you ,
Gitanjali
February 2, 2017 at 6:15 pm #13460Ligo GeorgeKeymasterCan you please explain in details ?
You can use a CCP module in Capture OR Compare OR PWM mode. It will work only in one mode at a time. You may use PIC microcontrollers with multiple CCP modules to use Capture and Compare mode together.
February 3, 2017 at 9:53 am #13462GITANJALIParticipantHi,
I’m using PIC 12F1840 (single CCP module) and internal oscillator 16MHz. I want to read Pulse width of input signal at RA2 (input PWM frequency 400Hz). Generate new PWM out (output PWM frequency 18KHz) at RA5 with same pulse width reading at input PWM at RA2.
steps i followed :
1) Capture Mode: detected rising edge (interrupt detection) -> detected falling using capture mode (interrupt detection) at RA2, got pulse width (falling edge – rising edge)
2) Compare Mode : write pulse width to RA5 using compare mode
Now, my problem is when controller is in compare mode at the same time my new rising or falling edge get detected system is not able to find new pulse width.
thanking you,
Gitanjali
February 3, 2017 at 12:54 pm #13464Ligo GeorgeKeymasterAs I told above, a single CCP will work only in one mode at a time. I think you should do like this.
- You can use a normal input interrupt or on-change interrupt to detect rise and fall.
- Start a timer when rise is detected and stop it when fall happens.
- So you will get the time period from the timer count.
- Use that CCP module only in PWM mode.
- Just change the duty cycle based on the timer value.
February 3, 2017 at 1:56 pm #13470GITANJALIParticipantok , thanks for your reply . 🙂
-
AuthorPosts
- You must be logged in to reply to this topic.