Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

PIC18F4550 problem with TIMER interupt

Status
Not open for further replies.

mikimtb

Newbie level 1
Newbie level 1
Joined
Dec 16, 2010
Messages
1
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Visit site
Activity points
1,296
Hi everybody, my name is Miroslav and I'm from Serbia.
I'm trying to write a code for controlling four RC servo motors with PIC18F4550. Till now I finished all things about USB HID and UART communication, and it's working perfectly.

Today I try to write a code for timer0 configuration. Because I have four motors to control, I need timer0 interrupts on every ~5ms. I configured timer0 as 16bit timer/counter, increment on internal clock, with prescaler of 1:2. After that I configured interrupt priority low for timer0 and enable timer0 interrupt. With timer0 prescaler 1:2 I have to write offset of 35398 into TMR0H:TMR0L and timer will overflow on every 5ms (30137*0.083us * 2 = 5002us).
Firstly, I tested this in main loop and its work perfectly. Code for my test is below:

Code:
void TIMER0Init(void)
{
	T0CONbits.TMR0ON = 0;	// Disable TMR0
	T0CONbits.T08BIT = 0;	// Timer0 is 16bit timer/counter
	T0CONbits.T0CS = 0;		// Internal clock source	
	T0CONbits.PSA = 0;		// Prescaler enabled
	T0CONbits.T0PS2 = 0;	// 1:2 Prescaler ratio	
	T0CONbits.T0PS1 = 0;
	T0CONbits.T0PS0 = 0;
	
	/* Make Timer0 interrupt low priority */
	INTCON2bits.TMR0IP = 0;
	/* Enalbe TMR0 interrupt*/
	INTCONbits.TMR0IE = 0;
	/* Enable all low priority interrupts */
	INTCONbits.GIEL = 0;
	/*Clear TMR0 interrupt flag*/
	INTCONbits.TMR0IF = 0;
	
	/* Write Timer0 offset for ~5ms interrupt */
	TMR0H = 0;
	TMR0L = 0;
	
	T0CONbits.TMR0ON = 1; // Start the timer
.
.
.
// infinite loop inside main function
while(1)
    {
        #if defined(USB_POLLING)
			// If we are in polling mode the USB device tasks must be processed here
			// (otherwise the interrupt is performing this task)
	        USBDeviceTasks();
        #endif
    	
    	// Process USB Commands
        processUsbCommands();  
        
        // Process UART Commands
        processUartCommand();
        
        // timer0 test
        timerValuePtr = (unsigned char*)&timerValue;
	*timerValuePtr = TMR0L;
	timerValuePtr++;
	*timerValuePtr = TMR0H;

	if(timerValue >= 30137) 
	{ 
		PORTBbits.RB0 ^= 1;
		
		timerValue = 0;
		TMR0H = 0;
		TMR0L = 0;
	}
        // timer0 test end
}

After proofing this with oscilloscope, I changed the code to do the same thing with interrupt. The code is below:
Code:
void TIMER0Init(void)
{
	T0CONbits.TMR0ON = 0;	// Disable TMR0
	T0CONbits.T08BIT = 0;	// Timer0 is 16bit timer/counter
	T0CONbits.T0CS = 0;		// Internal clock source	
	T0CONbits.PSA = 0;		// Prescaler enabled
	T0CONbits.T0PS2 = 0;	// 1:2 Prescaler ratio	
	T0CONbits.T0PS1 = 0;
	T0CONbits.T0PS0 = 0;
	
	/* Make Timer0 interrupt low priority */
	INTCON2bits.TMR0IP = 0;
	/* Enalbe TMR0 interrupt*/
	INTCONbits.TMR0IE = 1;
	/* Enable all low priority interrupts */
	INTCONbits.GIEL = 1;
	/*Clear TMR0 interrupt flag*/
	INTCONbits.TMR0IF = 0;
	
	/* Write Timer0 offset for ~5ms interrupt */
	TMR0H = 138;
	TMR0L = 70;
	
	T0CONbits.TMR0ON = 1; // Start the timer
}


// Low-priority ISR handling function
#pragma interruptlow lowPriorityISRCode
void lowPriorityISRCode()
{
	// Application specific low-priority ISR code goes here
	
	// TMR0 interrupt
	if(INTCONbits.TMR0IF)
	{
		TMR0H = 138;							// Write offset for 5ms overflow
		TMR0L = 70;						
		PORTBbits.RB0 ^= 1; 					// Toggle PORTB.0
		INTCONbits.TMR0IF;						// Clear interrupt flag
	}
}

Again I had PWM signal on RB0 pin but the frequency wasn't 200Hz. Instead that frequency is 193kHz. I try to change prescaler value, or offset value but the frequency is constant 193kHz. In code above I didn't copy RCONbits.IPEN = 1; for interrupt priority enables. This configuration is in picInit function.

Does somebody had problem like this? I mentioned that I had uart and usb communication, does that can be a problem? I'm using PIC C18 compiler.

- - - Updated - - -

I found the error,
INCONBits.TMR0IF; has to be INCONBits.TMR0IF = 0;
I was blind almost four hour, wtf.
 
Last edited:

check this code its working its for 4520 but hopefully will work also for 4550
Code:
#include <p18f4520.h>
#include <usart.h>
#include <timers.h>
#pragma config OSC = HS
#pragma config PWRT = OFF
#pragma config MCLRE = ON
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config DEBUG = ON
#pragma config PBADEN = OFF
#define SERVO_PULSE_HIGH LATCbits.LATC0 =1
#define SERVO_PULSE_LOW LATCbits.LATC0 =0
#define CONVERT_mS_PULSE 10000.0 
void chk_handler (void);
void chk_handler_low (void);
unsigned char val1=0,val2=0,int1=0,int2=0,servo=0,dc=0,state=0,state1=0;
unsigned int timer0=0,t1=0,timer1=0;
unsigned long s=0,d=0;
float t=0,dt=0;
////high priority interrupt
#pragma code interrupt = 0x8
void _interrupt (void)
{
  _asm goto chk_handler _endasm
}
///LOW priority interrupt
#pragma code interruptlow = 0x18
void interruptlow (void)
{
  _asm goto chk_handler_low _endasm
}

#pragma code
#pragma interruptlow chk_handler_low
void chk_handler_low (void)
{
unsigned char c=0;
/* as timer is included in low priority interrupt so when its interrupt come*/ 
if (INTCONbits.TMR0IF)
{ 
///we r deviding the 20ms as///////
//0----->servo on time(ms) for state 0///
//and       off time=20-servo on time for state 1----->19//// 
if(state==0)
{
////for state zero on the on servo///
PORTCbits.RC0=1;
///time devision if less then 50 pressed the its move right but with deviosion will be of 8us/////
if(servo<=50)
{
t=servo*.008+.960;///0-50 the devision will be 8us
}
///if greater than 50 its moves let but devision of 8.68us////   
else
{
t=servo*.00868+.960;
}
}
/////servo of for 20-ontime////
else if(state==1)
{
PORTCbits.RC0=0;
////time interrupt will come after 2ms-ontime for making calculation easy for next 18ms
t=2.0-t;
}
else if(state>1&&state<19)
{
PORTCbits.RC0=0;
////1ms timer interrupt
t=1.0;
}
///////put value to timero variable/////
timer0=(unsigned int)(65536-(t*CONVERT_mS_PULSE));//(t*CONVERT_mS_PULSE));
INTCONbits.TMR0IF=0;
T0CONbits.TMR0ON = 1;
////write timer0
WriteTimer0(timer0);
state++;
//////after 20ms state value should be zero for next pulse
if(state>19)
state=0;
}
if (PIR1bits.TMR1IF)
{  
if(state1==0)
{
////for state1 zero on the on DC///
PORTCbits.RC1=1;
///time devision if less then 150 pressed the its move right but with deviosion will be of 8us/////
dt=dt*.010;///the devision will be 10us
}
else if(state1==1)
{
PORTCbits.RC1=0;
////time interrupt will come after ontime for making calculation easy for next
dt=1.0-dt;
}
///////put value to timero variable/////
timer1=(unsigned int)(65536-(dt*CONVERT_mS_PULSE));
PIR1bits.TMR1IF=0;
T1CONbits.TMR1ON = 1;
////write timer0
WriteTimer1(timer1);
state1++;
//////after 20ms state value should be zero for next pulse
if(state1>1)
state1=0;
} 
if(PIR1bits.RCIF==1)
{
  c = ReadUSART();
  WriteUSART(c);
////if value is in between then get as data////
  if (c >= '0' && c <= '9')
   {
///ascii o 0 is 48 and 1 is 48 and so on////
////so subsrtat 48 or getting actual value///// 
   c=c-48;
    val1=val1*10+c;
   // PORTD=val1;
    }
///////////////enter/////////////
////if enetr pressed then get value///
    else if(c==13)
   {
    val2=val1;
  //  PORTD=val2;
///is this for servo////
if(val2<100&&val2>=0)
{
servo=val2;
}
////or for dc///
if(val2>=100&&val2<200)
{
////if for dc subtratc from 100 as user is enterring off by 100 for dc///
dc=val2-100;
}
//PORTD=servo;
     val1=0;
    }
////////back space//////////////
  else if(c==8)
   {
    val1=(val1-(val1%10))/10;
     PORTD=val1;
    }
c=0;
   // PORTD=c;
PIR1bits.RCIF = 0;
}
}
#pragma code
#pragma interrupt chk_handler
void chk_handler (void)
{
if(INTCONbits.INT0IF)////if from portb 1st pin(servo robot)
{
if(servo==0)
{
int1++;
INTCONbits.INT0IF = 0;
INTCONbits.INT0IE = 1;
if(int1==1)//////rising edge
{
PORTCbits.RC0 = 1;
INTCON2bits.INTEDG0 = 0;///set interrupt on falling edge
}
if(int1==2)////falling edge
{

PORTCbits.RC0 = 0;
INTCON2bits.INTEDG0 = 1;///set interrupt on rising edge edge
int1=0;
}
}
else
{
INTCONbits.INT0IF = 0;
INTCONbits.INT0IE = 1;
}
}
if(INTCON3bits.INT1IF)////if from portb 1st pin(servo robot)
{
if(dc==0)
{
int2++;
INTCON3bits.INT1IF = 0;
INTCON3bits.INT1IE = 1;
if(int2==1)//////rising edge 
{
PORTCbits.RC1 = 1;
INTCON2bits.INTEDG1 = 0;///set interrupt on falling edge
}
if(int2==2)////falling edge
{
PORTCbits.RC1 = 0;
INTCON2bits.INTEDG1 = 1;///set interrupt on rising edge edge
int2=0;
} 
}
else
{
INTCON3bits.INT1IF = 0;
INTCON3bits.INT1IE = 1;
}
}
}

void main (void)
{
INTCONbits.INT0IF = 0;///interrupt0 interrupt flag set to 0
INTCONbits.INT0IE = 1;///interrupt0 enable
INTCON2bits.INTEDG0 = 1;//interrupt on rising edge
TRISCbits.TRISC0 = 0;/////////////////O/p for servo
TRISCbits.TRISC1 = 0;/////////////////O/p for servo
TRISBbits.TRISB0 = 1;/////interrupt i/p
TRISBbits.TRISB1 = 1;/////interrupt i/p
INTCON3bits.INT1IE=1;///EXTERNAL INTERRUPT 1
INTCON3bits.INT1IF=1;///EXTERNAL INTERRUPT FLAG CLEARED
//INTCON3bits.INT2IP=0;
//INTCON3bits.INT1IP=0;
PORTC = 0x00;/////no movement
TRISD = 0;////CHECKING WHETHER IT IS GETTING DATA FROM SERIAL
PORTD=0;
  /* 4800 baud for 4 mhz crystal by adjusting value to 64, */
  OpenUSART (USART_TX_INT_OFF &
             USART_RX_INT_ON &
             USART_ASYNCH_MODE &
             USART_EIGHT_BIT &
             USART_CONT_RX &
             USART_BRGH_LOW, 64);

  /* Display a prompt to the USART */
  putrsUSART ((const far rom char *)"\n\rEnter a digit 0-99 for servo and 100-199 for dc motor!\n\r");

  /* Enable interrupt priority */
  RCONbits.IPEN = 1;
/* Clear the peripheral interrupt flags */
   PIR1 = 0;
//////TIMER0///////////
t=1.0;
dt=0;
OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_1);

/*timer0 interrupt priority low*/
INTCON2bits.TMR0IP=0;
////timer interrupt calculation ///
timer0=(unsigned int)(65536-(t*CONVERT_mS_PULSE));//(t*CONVERT_mS_PULSE));
WriteTimer0(timer0);
///TIMER1/////////
///interrupt priority low//
IPR1bits.TMR1IP=0;
OpenTimer1(TIMER_INT_ON & T1_16BIT_RW & T1_SOURCE_INT & T1_PS_1_1 & T1_OSC1EN_OFF);
T1CONbits.TMR1CS = 0; //Timer 1Clock internal source
timer1=(unsigned int)(65536-(dt*CONVERT_mS_PULSE));//(t*CONVERT_mS_PULSE));
WriteTimer1(timer1);
  /* Make receive interrupt high priority */
  IPR1bits.RCIP = 0;

  /* Enable all high priority interrupts */
  INTCONbits.GIEH = 1;
/* Enable all low priority interrupts */
  INTCONbits.GIEL = 1;
  /* Loop forever */
while (1)
{
if(servo>0)/////ON
{
//PORTDbits.RD3=~PORTDbits.RD3;
T0CONbits.TMR0ON = 1;
}
else//////////OFF
{     
T0CONbits.TMR0ON = 0;
}
if(dc>0)
{
T1CONbits.TMR1ON = 1;
}
else
{
T1CONbits.TMR1ON = 0;
}
       
}
}
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top