Using Capture and Compare mode together – PIC 12F1840 – electroSome https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/feed/ Sat, 18 Mar 2023 04:53:27 +0000 https://bbpress.org/?v=2.6.9 en-US https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/#post-13455 <![CDATA[Using Capture and Compare mode together – PIC 12F1840]]> https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/#post-13455 Thu, 02 Feb 2017 10:37:04 +0000 GITANJALI 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

]]>
https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/#post-13460 <![CDATA[Reply To: Using Capture and Compare mode together – PIC 12F1840]]> https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/#post-13460 Thu, 02 Feb 2017 12:45:25 +0000 Ligo George Can 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.

]]>
https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/#post-13462 <![CDATA[Reply To: Using Capture and Compare mode together – PIC 12F1840]]> https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/#post-13462 Fri, 03 Feb 2017 04:23:33 +0000 GITANJALI Hi,

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

 

 

]]>
https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/#post-13464 <![CDATA[Reply To: Using Capture and Compare mode together – PIC 12F1840]]> https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/#post-13464 Fri, 03 Feb 2017 07:24:06 +0000 Ligo George As 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.
]]>
https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/#post-13470 <![CDATA[Reply To: Using Capture and Compare mode together – PIC 12F1840]]> https://electrosome.com/topic/capture-compare-pwm-pic-12f1840/#post-13470 Fri, 03 Feb 2017 08:26:04 +0000 GITANJALI ok , thanks for your reply . 🙂

 

]]>