Jump to content
Sign in to follow this  
indian engineer

Timer 0 Problem In Pic16f84a

Recommended Posts

Hi there,

Is there any problem in the following code?

#include <system.h>

//Target PIC16F84 configuration word
#pragma DATA _CONFIG, _PWRTE_OFF & _WDT_OFF & _HS_OSC & _CP_OFF

//Set clock frequency
#pragma CLOCK_FREQ	4000000
int ar[3][3];

//======================Timer 0 handler=============================
static void display( void )
{
int i;

for(i=0;i<3;i++)
 {
  portb.6=portb.7=porta.0=0;
  if(i==1){portb.7=1;portb.6=porta.0=0;}
  else if(i==2){porta.0=1;portb.6=portb.7=0;}
  else {portb.6=1;portb.7=porta.0=0;}

  if(ar[i][0]==1)
{
 portb.0=1;portb.1=0;
}
  else if(ar[i][0]==2)
{
 portb.1=1;portb.0=0;
}
  else
{
 portb.0=portb.1=0;
}

//---------
  if(ar[i][1]==1)
{
 portb.2=1;portb.3=0;
}
  else if(ar[i][1]==2)
{
 portb.3=1;portb.2=0;
}
  else
{
 portb.2=portb.3=0;
}
//-----------
if(ar[i][2]==1)
{
 portb.4=1;portb.5=0;
}
  else if(ar[i][2]==2)
{
 portb.5=1;portb.4=0;
}
  else
{
 portb.4=portb.5=0;
}
  //---------
  delay_ms(50);
 }
}
//=====================Interrupt====================================
void interrupt( void )
{

//Handle timer0 interrupt
if( (intcon & (1<<T0IF))!=0 )
{
	display(); //call timer 0 handler

	clear_bit( intcon, T0IF ); //clear timer 0 interrupt bit
}

}
//==========================Main====================================
void main( void )
{
//Configure port A
trisa = 0x14;
//Configure port B
trisb = 0x00;

//Initialize port A
porta = 0x00;
//Initialize port B
portb = 0x00;
//Set Timer0 mode
clear_bit( option_reg, T0CS ); //configure timer0 as a timer
//Set prescaler assignment
clear_bit( option_reg, PSA ); //prescaler is assigned to timer0
//Set prescaler rate
set_bit( option_reg, PS2 ); //prescaler rate 1:256
clear_bit( option_reg, PS1 );
set_bit( option_reg, PS0 );
//Set timer0 source edge selection
//set_bit( option_reg, T0SE ); //increment on high-to-low transition on RA4/T0CKI pin
//Enable interrupts (Timer0)
intcon = 0xA0;

  int i,j;
  for(i=0;i<3;i++)
  {
for(j=0;j<3;j++)
 { ar[i][j]=0; }
  }
  while(1)
{ 
for(i=0;i<3;i++)
 {
  for(j=0;j<3;j++)
   {
	ar[i][j]=1;
	delay_s(2);
	ar[i][j]=2;
	delay_s(2);
	ar[i][j]=0;
   }
  } 
} 
}
//========================End of Main===========================

 

The problem is that when simulating in sourceboost IDE the interrupt function once executed, the control will not terminate from interrupt function (Here display function). I mean, the control is looping around display() and not return to main(). I didn't understan what is the problem. Help me please. I have the external circuit also. If necessary I will attach it.

 

Thanks in advance

Share this post


Link to post
Share on other sites

I think the interrupt routine is longer than the timer overflow which causes the interrupt.

 

Within the interrupt service routine a delay of 50 ms is called 3 times, yet timer0 overflows (fosc/4*256*256) 65ms. So the ISR is being interrupted by itself before it finishes.

Share this post


Link to post
Share on other sites

Yes. A way to overcome this would be to make a global flag and on the TMR0 interrupt event set that flag true. Within the infinite loop in main check the status of this flag. If it's 1, first set it to zero and then call the display function, i.e.:

//... 

bool trm_0_overflowed = false;

// ... 

void interrupt() {
 if ( intcon & T0IF  ) {
trm_0_overflowed = true;
clear_bit( intcon, T0IF );
 }
}

// ...

void main() {
 //...

 while( true ) {
if ( trm_0_overflowed ) {
  trm_0_overflowed = false;
  display();
}

// ...
 }
}

Share this post


Link to post
Share on other sites

Thanks for response. But I am a very beginner in this field. So Please explain and if there are any articles specifically saying this type of problems please post their link.

I understood that the timer0 overflows before display() function finishes. But didn't go the idea to troubleshoot

Thanks

Share this post


Link to post
Share on other sites
Thanks for response. But I am a very beginner in this field. So Please explain and if there are any articles specifically saying this type of problems please post their link.

I understood that the timer0 overflows before display() function finishes. But didn't go the idea to troubleshoot

Thanks

 

Microchip has lots of excellent documentation. Every production chip has a data sheet associated with it and it's always a good idea to look that over, as well as current errata sheets (or the one that pertains to the stepping of your silicon). They also have application projects, tips, etc.

 

I'm perusing Mike Predko's books and they mention general rules for interrupt routines. Recently, and an older version was selling on Amazon at a discount and most of the information is still applicable today.

 

www.piclist.com has a ton of code examples, projects and ideas. A lot of it is in assembly, but the ideas are often transferable to C.

 

If you google "pic interupt tutorial" you'll probably get lots of hits.

 

I'd start with the data sheet first.

 

google has many pic books with sample pages, and Amazon does this also (sample pages).

Share this post


Link to post
Share on other sites
Hi there,

Is there any problem in the following code?

( ... )

The problem is that ...

Thanks in advance

 

I had a similar problem in that I was writing to a MAX7219 which was driving some LED displays.

The problem for me was that I had delays in my interrupt routine to give the MAX7219 time to digest the data.

 

My fix was to move all the display driver code into main and communicate from the interrupt routine using a global variable.

 

eg here's some of my thermometer code (using RC curve measured by timer1) ...

 

unsigned int rawtemp; // global raw temperature value
void interrupt( void )
{
if (pir1.CMIF) // Comparator interrupt (either)
{
	BYTE comval;
	comval=cmcon;	// clear change condition
	if (!comval.7) // comparator 2 low->high (from RA2)
	{
		t1con = 00000000b;	// stop Timer1
		trisa.2=0;	// discharge the C (RA2 val doesn't matter)
var set =>			rawtemp=tmr1h<<8 | tmr1l; // form rawtemp  out of timer1 value
	}
	clear_bit( pir1, CMIF );  // clear interrupt
}
}

void main()
{
( lots of missing initialisation code )
while ( 1 )
{
	delay_ms(50);
	if (rawtemp > 0)
	{
		// wrong value (nonlinear, uncalibrated etc)
		unsigned int tv;
used =>			tv=380-(rawtemp>>6);

		LEDnext[0x01]=tv/100; // digit 1
		LEDnext[0x02]=((tv-(tv/100)*100)/10)|0x80; // digit 2 (inc dp)
		LEDnext[0x03]=tv%10; // digit 3
		LEDnext[0x04]=00001101b;	// digit 4 : 'c'
takes ages ===>		LEDupdate();
	}

}
}

 

Hope this helps.

I'm using a 16F628A BTW (cheaper and has a comparator) but codewise its the same as the old 16F84A.

 

Ginger Lee.

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...