i'm trying to control four separate lighting arrays using a timer overflow interrupt to control four pulse width modulations. at the same time i want to be able to control the pwm frequencies using serial communication. i'm using a version of pic lite for my compiling and can compile my code with either interrupt but not with both of them together. below is the full code (simplified) that i'm trying to use.

/*-----------------------------------------------------
contol 4 leds through pwm and serial
-------------------------------------------------------*/
#include "mxapi.h"

__CONFIG(0X7E61);  //Sets Interrupt Configuration for PIC

char counter;
char led_1;
char led_2;
char led_3;
char led_4;
char id;

/*---------------------------------------------------------------\
|  The following section defines a special "interrupt function"  |
| called "lights()" that will execute every time an interrupt is  |
| triggered. (In this case, that's every time Timer0 overflows.) |
================================================================*/

void interrupt lights(void) {
 if  (T0IF == 1)      //check if Timer0 "Interrupt Flag" is set -when it
  {                  //times out ("overflows" at 255) it's set to 1.)
    T0IF = 0;        //reset Timer0 flag
    counter ++;      //increase counter by 1
    if (counter==38) //check if interrupt has triggered 39 times
      {
        RB3=1;       //start pulse for led 1
        RB4=1;       //start pulse for led 2
        RB5=1;       //start pulse for led 3
        RB6=1;       //start pulse for led 4
        counter=0;   //reset counter
      }
    if (counter==led_1)  //check if time to end pulse for led 1
        RB3=0;
    if (counter==led_2)  //check if time to end pulse for led 2
        RB4=0;
    if (counter==led_3)  //check if time to end pulse for led 3
        RB5=0;
    if (counter==led_4)  //check if time to end pulse for led 4
        RB6=0;
   }             //end if(T0IF==1)
}                 //end servo() definition

//====================================================\\
//-----------------------START PROGRAM-------------------------\\
//====================================================\\

void main() {
    GIE=1;       //enable global interrupts
    PEIE = 1;    // enable peripheral interrups
    RCIE = 1;    // enable receive interrupt pin
    usart_init(30000);

    T0IE=1;      //enable Timer0 interrupts
    T0CS=0;      //set Timer0 to use internal instruction clock
    PSA=0;       //assign prescaler to Timer0
    //---- The next three lines set a "pre-scale value" for frequency of interrupts on the
    //---- PIC. "000" sets a pre-scale value of 2, meaning interrupts happen 1/2 as often.
    PS2=0;    //set first digit of pre-scaler value
    PS1=0;    //set second digit of pre-scaler value
    PS0=0;    //set third digit of pre-scaler value

    TRISB3=0;    //set B3 as output (for led 1)
    TRISB4=0;    //set B4 as output (for led 2)
    TRISB5=0;    //set B5 as output (for led 2)
    TRISB6=0;    //set B6 as output (for led 2)

     while (1==1) {
        led_1=id;        //set pulse rates to leds
        led_2=10;       //set pulse rates to leds
        led_3=20;       //set pulse rates to leds
        led_4=30;       //set pulse rates to leds
    }
}

void interrupt usart_test(){    //interrupt that loads new serial_in from the serial port
    if(RCIF){        // if data is ready on USART
        id = RCREG;
        RCIF = 0;
    }
}

Recommended Answers

All 6 Replies

What are T0IF and RCIF ?

Imagine an interrupt control register, with flags for various kinds of interrupts.

+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+
                          ^   ^
               USART   ---+   |
               TIMER   -------+

Setting both to 0 may be fine, if there is only ever one of them at once.

But to clear RCIF say properly, it would need to be RCIF &= ~0x02; Where ~2 evaluates to 11111101 (in binary), and the & has the effect of preserving all the other bits, and setting the required bit back to zero.

i've been learning c through a website: machinescience.org they have their own compiler (i believe based off pic lite) and their own libraries. so i think some of the commands have been simplified/altered through their interface. so TOIF references the timer overflow interrupt and RCIF referneces the recieve interrupt.

i tried changing the RCIF=0; to RCIF&=~0x02; but had no luck. the RCIF=0; works in this compiler without the timer overflow interrupt. so that must be another one of machine sciennce's alterations.

have you ever used these two interrupts in the same code before?

when you say "Setting both to 0 may be fine, if there is only ever one of them at once." does that mean that the interrupts will cancel each others flags?

Perhaps they've simplified it too much.
Though this question would be better asked on their forum, since they'll know a hell of a lot more about all the details.

sadly they have no forum. i too think i've reached the limits of their capabilities but am reluctant to shift myself off of their interface. the thing that confuses me most is bootloading. all of my pics have their bootloader on them. to load my code now all i do is communicate through serial. do i need to buy a bootloader and rebootload all my pics in order to use another compiler? once that is done do i still load new code via serial?

i'm dieing to use the new 8 pin atmegas so the time has come to change compilers i guess.

I still think it might work, if you can figure out a better way of clearing the interrupt other than through the = 0 method you have at the moment.

This is fine when you only have one interrupt, but if you have several, then the approach seems flawed to clear interrupts which haven't been processed.

Another point to remember is interrupt routines should do the least amount of work possible with the fewest resources possible.

ok so i figured it out! it was not the compiler after all. the pic 16 family only has one interrupt vector. so i merged both of my interrupt functions into one and it compiled and works perfectly. below is the new code if anyone is interested.

[code=c]

/*-----------------------------------------------------
contol 4 leds through pwm and serial
-------------------------------------------------------*/
#include "mxapi.h"

__CONFIG(0X7E61);  //Sets Interrupt Configuration for PIC

unsigned char counter;
unsigned char led_1;
unsigned char led_2;
unsigned char led_3;
unsigned char led_4;
unsigned char id;
unsigned char com;
unsigned char led_1_duration = 3;
unsigned char led_2_duration = 3;
unsigned char led_3_duration = 3;
unsigned char led_4_duration = 3;

void interrupt light_control(void){
	//timer overflow check
	if (T0IF){
		if(T0IF == 1){      //check if Timer0 "Interrupt Flag" is set -when it... times out ("overflows" at 255) it's set to 1.)
			T0IF = 0;        //reset Timer0 flag
			counter ++;      //increase counter by 1
			if(counter==38){
				RB3=1;       //start pulse for led 1
				RB4=1;       //start pulse for led 2
		                RB5=1;       //start pulse for led 3
				RB6=1;       //start pulse for led 4
				counter=0;   //reset counter
			}
			if(counter==led_1)
				RB3=0;
			if(counter==led_2)
				RB4=0;
			if(counter==led_3)
				RB5=0;
			if(counter==led_4)
				RB6=0;
		}  
	}

	//usart input check
	if(RCIF){        // if data is ready on USART
		id = RCREG;
		id = id>>5;	//set pic id
		
		com = RCREG;
		com = com<<3;	//set as data for communication
		com = com>>3;
		
		if (id==5){
			if (com <= 23){
				if (com <= 15){
					if (com <= 7){
						led_1_duration = com + 1;
					}
					else {
					led_2_duration = (com - 8) + 1;
					}
				}
				else{
					led_3_duration = (com - 16)*2 + 1;
				}
			}
			else {
				led_4_duration = (com - 24)*2 + 1;
			}
		}
		RCIF = 0;
	}
	
	//set interrupt flags back to 0
	T0IF = 0;
	RCIF = 0;
}

//====================================================\\
//-----------------------START PROGRAM-------------------------\\
//====================================================\\

void main() {
    GIE=1;       //enable global interrupts
    PEIE = 1;    // enable peripheral interrups
    RCIE = 1;    // enable receive interrupt pin
    usart_init(30000);

    T0IE=1;      //enable Timer0 interrupts
    T0CS=0;      //set Timer0 to use internal instruction clock
    PSA=0;       //assign prescaler to Timer0
    //---- The next three lines set a "pre-scale value" for freq.
    //---- of interrupts on the PIC. "000" sets a pre-scale value
    //---- of 2, meaning interrupts happen 1/2 as often.
    PS2=0;    //set first digit of pre-scaler value
    PS1=0;    //set second digit of pre-scaler value
    PS0=0;    //set third digit of pre-scaler value

    TRISB3=0;    //set B3 as output (for led 1)
    TRISB4=0;    //set B4 as output (for led 2)
    TRISB5=0;    //set B5 as output (for led 2)
    TRISB6=0;    //set B6 as output (for led 2)

     while (1==1) {
        led_1=led_1_duration;        //set pulse rates to leds
        led_2=led_2_duration;       //set pulse rates to leds
        led_3=led_3_duration;       //set pulse rates to leds
        led_4=led_4_duration;       //set pulse rates to leds
    }
}
commented: Good job! +22
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.