[SOLVED] PIC18F2221 CCP compare mode CCP1IF don't trigger

Status
Not open for further replies.

kekecjan

Newbie level 4
Joined
Jun 29, 2020
Messages
7
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
91
Hello guys !
I began learning programming PIC uC in MPLABX 5.4 , in few days i learned a lot but now i would really need some help about CCP compare mode, i am using PIC18F2221 external crystal oscillator 8MHz. I have done a lot of research on internet about CCP and timers but still i am struggling with CCP1IF to become 1, i know it's simple because i used timer0 to blink LED exactly one ms. Sooo what i want to do is this comparing register CCPR1 and Timer1 register TMR1. the result has to be CCP1IF=1 (i am not using interrupts) but unfortunately this CCP1IF is alway 0 , but when i make simple if statement like this: if(TMR1 == CCPR1) {LATC4=~LATCH4;} then LED on PORTC4 will blink but CCP1IF should not be 0 if values of registers are the same. I hope anyone has a clue what could be wrong.

BTW : #include "UART.h" is made by me and #include "XC8.h" cuse includes some configurations and _XTAL_FREQ.

C:
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 8000000
#endif

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "XC8.h"
#include "UART.h"


//#include <MojConfig.h> //include _xtal_freqs
// PIC18F2221 Configuration Bit Settings

// 'C' source line config statements


// CONFIG1H
#pragma config OSC = XT     // Oscillator (Internal oscillator block, port function on RA6 and RA7)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = ON         // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 2         // Brown-out Reset Voltage bits ()

// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = RC1     // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ANA     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config BBSIZ = BB256    // Boot Block Size Select bits ( 256 Word)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bitProtect Boot (Boot block not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block not protected from table reads executed in other blocks)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.


volatile char count=0;

/* delata oba :void __interrupt(high_priority) myIsr(void)  in void interrupt low_priority TMR_ISR(void) */

/*void interrupt TMR_ISR(void){
    UART_Print("ISR \n");
    if(CCP1IE && CCP1IF){  // preverim ce je verflow Interrupt Enable bit in Overflow Interrupt Flag bit
    PIR1bits.CCP1IF=0;
    UART_Print("CCPISR \n");//NUJNO ga postavim na 0  (must be cleared in software)
    //count++;
    LATCbits.LATC4 = ~LATCbits.LATC4;count=0;
    //if(count==125){LATCbits.LATC4 = ~LATCbits.LATC4;count=0;}  
   
    }

}  */

void Timer3_Init(void){

    T3CONbits.RD16=1;
    T3CONbits.T3CCP2=0;
    T3CONbits.T3CCP1=1;
    T3CONbits.T3CKPS1=0;
    T3CONbits.T3CKPS0=1;
    T3CONbits.TMR3ON=0;
    T3CONbits.TMR3CS=0;

    TMR3=0;

}

void Timer1_Init(void){
    T1CONbits.RD16=1;
    T1CONbits.T1RUN=0;
    T1CONbits.T1CKPS1=1;
    T1CONbits.T1CKPS0=1;
    T1CONbits.T1OSCEN=1;
    T1CONbits.TMR1ON=1;
    TMR1=0;
}

//const char message[] = "PIC18F2221 TIMER0 \n " ;

char text[16];

void main(void)
{  TRISC4=0;  //PORTC4 output
   TRISC2=0;
   
    CCP1CON= 0x00001010; //Compare mode: generate software interrupt on compare match (CCPxIF bit is set,CCP pin reflects I/O state)
    //CCPR2H=(unsigned char) 1000>>8;
  //  CCPR2L=(unsigned char) 1000;
    CCPR1=1000;
   

    UART_Init(9600);
   
    Timer1_Init();
    Timer3_Init();
   
  while(1)
  {    
       
      if(TMR1==CCPR1){LATC4=~LATC4;sprintf(text,"TMR %u CCP %u  %d %d \n", TMR1, CCPR1 , CCP1IF, TMR1IF);UART_Print(text);TMR1IF=0;}


  }

}
 

If you are using XC8 then you should only need to include "xc.h". Without showing us what you have in 'xc8.h' and 'uart.h' we can only guess and so we may be guessing incorrectly.
Also you probably don't need 'stdio.h', 'stdlib.h' and 'stdint.h'. While those can be 'standard' includes when programming on a PC, they are very rarely needed in an embedded app. I know you are using 'sprintf' and I'll get to that next.
You have declared 'text' to be 16 characters long which means you can write at most 15 characters into it (the sprintf will add in a trailing null character that you need to account for). However, even without working out how many characters the various formatting items expand to, you have 14 literal characters in the format string. That means you will certainly overflow the space allocated and there is no knowing what impact that will have.
Your setup for CCP1CON is wrong and also illustrates why "magic numbers' are a bad idea. You have specified a 32-bit constant that you are assigning to an8-bit register. (I know you meant to write '0b00001010' and not '0x00001010' but the compiler doesn't!). Therefore you have set the CCP1CONbits.CCP1M bits to 0 which disables the module. It is always much better to write to the specific individual bits when initialising a module - as you have done for Timer1 - as then any wrong values are limited to that part of the setup; it is also much easier for others (and ultimately, you) to "decode".
You should not be comparing TMR1 with CCPR1 - look at Figures 16-1 and 16-2 and you will see that the module has a whole lot of hardware to do that for you and set the CCP1F bit. Also that is the bit you should be clearing, not TMR1IF.
You have set up Timer1 to use the Fosc source but you have also enabled the hardware to use the external oscillator (T1OSCEN = 1) which, while not wrong, does waste power.
When you use Timer1 with the CCP module, the CCP module will clear TMR1 via hardware when a comparison is found. Therefore the timer will never overflow and so TMR1IF will not be set.
I suspect that things will work much better for you when you actually turn on the CPP module and get rid of a lot o your extraneous code.
Susan
 
Hi Susan, Thank you for a lot of explanations.

I was working with AVR at university, but i decided to learn new family of microcontrollers. In Atmel Studio to configure few bits you can just do it like this : REGISTER = (1<<NAME_REG1) | (1<< NAME_REG2); and for me that's much better looking then writting in HEX or BIN . Can in MPLABX also set up bits like i said ?

Well for comparing TMR1 with CCPR1 i just wanted too see if evrything works and if they compare.

Yah you are right i should turn off Timer1 oscillator ( T1OSCEN = 0 ) i read that on 13.3 .

Now i see that i have wrote ( 0x00001010 ) haha... yah it should be 0b00001010 and i only changed that in code and it worked as expected.
I appreciate your time to write. Thank you again.

Jan
 

....and yes, you can use the BIT names (1 <<NAME_BIT) but not register names as you wrote.

register = (1 << Bit name) will place a '1' in the named bit position with a zero in other bit positions.
register |= (1 << Bit name) sets the named bit in the register leaving other bits as they are.
register &= ~(1 << Bit name) resets the named bit in the register leaving other bits as they are.

Brian.
 

    kekecjan

    Points: 2
    Helpful Answer Positive Rating
COOL i will remember that , thanks Brian
 

Can in MPLABX also set up bits like i said ?
It certainly can - in fact you wrote the initialisation for Timer1 in the appropriate idiom: most registers have a name that refers to the whole register - T1CON for example - and also a name that refers to a structure that lets you access individual bits in the register - T1CONbits to continue the example. The structure is defined in such a way that the elements of the structure refer to the bits as defined in the data sheet for the register. It also means that for multi-bit fields - such as T1CONbits.T1CPKS - you can read and write all the bits at once.
Small point - MPLABx is the IDE and does not really get involved with things like naming conventions. It leaves that to the compiler - XC8 in this case. However it does 'try' to be helpful by invoking the compiler as you edit your file to try to provide name completion and error detection - which it does very badly.
Susan
 

Is there some better compilers to use instead of XC8, i did not found any for PIC microcontrollers ??
 

XC8 is extremely good, most of the complaints about it are because of bugs in the MPLABX IDE but you can use it from the command line if you like.
It s a bit dated but one of the best assembler/compiler/IDE packages for PIC12/16/PIC18 devices is "Wiz-C" from www.fored.co.uk

Brian.
 

Great, thanks.

Jan
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…