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.

Displaying the time parameter using Timer interrupt

Status
Not open for further replies.

nayakajit87

Member level 5
Joined
Aug 13, 2018
Messages
84
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
1,065
I have PIC16F886 4mhz crystal 1ms timer interrupt.I have code working as below. Now currently facing updating ms and Sec parameter.
the min and sec parameter will update properly but not in msec and sec


Code:
void interrupt isr(void) {

    asm("clrwdt"); 

    if (TMR1IF) {
        TMR1IF = 0;
    //  TMR1H = 0x3C;
      //  TMR1L = 0xB0;100ms

       TMR1H = 0xFE;                                
       TMR1L = 0x0C;// timer interrupt for 1ms
     if(Top_Display>Bottom_Value)
        {
        if(LED_SS==0)
        {
        Bottom_Value=(Sec*100)+MSec;
        }else
        if(LED_MS==0)
        {
        Bottom_Value=(Min*100)+Sec;
        }else
        if(LED_HM==0)
        {
        Bottom_Value=(Hour*100)+Min;
        }

        }else if(Top_Display==Bottom_Value)
            {

            } 

MSec++;
if(MSec>1000)
    {
    MSec=0;
    Sec++; 
      if(Sec>=59) {
            Sec=0;
            Min=Min+1;
            if(Min>=59) {
                Min=0;
            Hour=Hour+1;
                if(Hour>99) {
                    Hour=0;
                }
            }
        }
 }    
    Display();
    }

}

void Process_RUN_MODE()
{
//Display_Faults(12,18,27,26,18,11,24,26);

if(EEPROM_Read_Flag==1)
{
READ_EPROM();EEPROM_Read_Flag=0;
}
Top_Display=1234;
LED_MS=0;
Key_CHK_RESET();


if(LED_MS==0)
{
Dissect(Top_Display);
Float_Value=SplitFloat(Top_Display);
InG_value=SplitInt(Top_Display);   

Dissect_2(Bottom_Value);
}

} 
Void main()
 {

  while(1)
   {
Process_RUN_MODE();
  }

}

void Dissect_2(unsigned int Value)              // Spliting of process value in digits form
 {
    unsigned char a,Temp;
    for(a = 4;a >= 1 ; a--)
    {

     Temp = Value%10;
     Value = Value/10;
     LEDBuffer_1[a-1] = DISPTABLE[Temp];    

    }

 }

void Dissect(unsigned int Value)            // Spliting of process value in digits form
 {
    unsigned char a,Temp;

    for(a = 8;a >= 5 ; a--)
    {
     Temp = Value%10;
     Value = Value/10;
     LEDBuffer_1[a-1] = DISPTABLE[Temp];    

    }

 }
 

I couldn't read code so badly formatted and commented. Please stick to one style to make it easier to read.
I think I managed to unscramble it as:
Code:
void interrupt isr(void) 
{
    asm("clrwdt"); 

    if (TMR1IF) 
    {
        TMR1IF = 0;
    //  TMR1H = 0x3C;
    //  TMR1L = 0xB0;100ms

        TMR1H = 0xFE;                                
        TMR1L = 0x0C;// timer interrupt for 1ms
        if(Top_Display>Bottom_Value)
        {
            if(LED_SS==0)
            {
                Bottom_Value=(Sec*100)+MSec;
            }
            else
            if(LED_MS==0)
            {
                Bottom_Value=(Min*100)+Sec;
            }
            else
            if(LED_HM==0)
            {
                Bottom_Value=(Hour*100)+Min;
            }
        }
        else if(Top_Display==Bottom_Value)
        {

        } 

        MSec++;
        if(MSec>1000)
        {
            MSec=0;
            Sec++; 
            if(Sec>=59) 
            {
                Sec=0;
                Min=Min+1;
                if(Min>=59) 
                {
                    Min=0;
                    Hour=Hour+1;
                    if(Hour>99) 
                    {
                        Hour=0;
                    }
                }
            }
        }    
        Display();
    }
}

void Process_RUN_MODE()
{
//Display_Faults(12,18,27,26,18,11,24,26);

    if(EEPROM_Read_Flag==1)
    {
        READ_EPROM();
        EEPROM_Read_Flag=0;
    }
    Top_Display=1234;
    LED_MS=0;
    Key_CHK_RESET();


    if(LED_MS==0)
    {
        Dissect(Top_Display);
        Float_Value=SplitFloat(Top_Display);
        InG_value=SplitInt(Top_Display);   

        Dissect_2(Bottom_Value);
    }

}

Void main()
{
    while(1)
    {
        Process_RUN_MODE(); 
    }

}

void Dissect_2(unsigned int Value)              // Spliting of process value in digits form
{
    unsigned char a,Temp;
    for(a = 4;a >= 1 ; a--)
    {
        Temp = Value%10;
        Value = Value/10;
        LEDBuffer_1[a-1] = DISPTABLE[Temp];    
    }
}

void Dissect(unsigned int Value)            // Spliting of process value in digits form
{
    unsigned char a,Temp;

    for(a = 8;a >= 5 ; a--)
    {
        Temp = Value%10;
        Value = Value/10;
        LEDBuffer_1[a-1] = DISPTABLE[Temp];    
    }
}
If I got it right, your problem is almost certainly because the time taken inside your ISR is longer than the time between intervals between interrupts. As this is a timer of some kind, it would make more sense to ensure it kept time accurately by making the ISR much shorter. i suggest all you do inside the ISR is:
1. clear the interrupt flag
2. reload TMR1 read for the next interrupt
3. set a flag to say 100mS has elapsed
4. exit the ISR

Then in your main loop, poll the flag, do the timing routine and reset the flag.

Brian.
 

I have actually 2 issue in code.

1) variable declaration. I have declare variable
unsigned int Top_Display=0;
if assign Top_Display=0123 display shows 0083
if assign Top_Display=123 display shows 0123
Some of the variable it take properly and some are not. if i assign value Top_Display=0129 it gives error digit is out of range.


2)i have created 1ms timer interrupt . every 1ms i am increment msec . i am getting wrong calculation for displaying Msec to sec. other paramter it showing well. somewhere the conversion is affected

1S=1000ms
60S=1Min
60M=1H


Code:
void Process_RUN_MODE() {

	Top_Display=0123;

	LED_MS=0;

	Key_CHK_RESET();

	if(LED_MS==0) {
		LED_SS=1;
		LED_HM=1;
		Dissect(Top_Display);
		Dissect_2(Bottom_Value);

	} else if(LED_HM==0) {
		LED_MS=1;
		LED_SS=1;
		Dissect(Top_Display);
		Dissect_2(Bottom_Value);
	} else if(LED_SS==0) {
		LED_MS=1;
		LED_HM=1;
		Dissect(Top_Display);
		Dissect_2(Bottom_Value);
	}

}

void interrupt isr(void) {

	asm("clrwdt");

	if (TMR1IF) {
		TMR1IF = 0;
		//	TMR1H = 0x3C;
		//  TMR1L = 0xB0;100ms

		TMR1H = 0xFE;
		TMR1L = 0x0C;// timer interrupt for 1ms
		if(Top_Display>Bottom_Value) {
			if(LED_SS==0) {
				Bottom_Value=(Sec*100)+MSec;
			} else if(LED_MS==0) {
				Bottom_Value=(Min*100)+Sec;
			} else if(LED_HM==0) {
				Bottom_Value=(Hour*100)+Min;
			}

		} else if(Top_Display==Bottom_Value) {

		}

		MSec++;
		if(MSec>1000) {
			MSec=0;
			Sec=Sec+1;
		}
		if(Sec>=59) {
			Sec=0;
			Min=Min+1;
		}
		if(Min>=59) {
			Min=0;
			Hour=Hour+1;
		}
		if(Hour>99) {
			Hour=0;
		}



		Display();
	}

}
 

In C code, a number beginning with "0" is an octal number. Octal 0123 = Binary 1010011 = Hex 53 = Decimal 83

0129 is illegal because there is no digit '9' in octal base.


Wrong:
Code:
if(MSec>1000)
if(Sec>=59) {
if(Min>=59) {

Correct:
Code:
if(MSec >= 1000)
if(Sec >= 60) {
if(Min >= 60) {
 

Additionally, please do what I suggested in the ISR. Reduce it to:
Code:
void interrupt isr(void)
{
  if (TMR1IF) 
  {
    TMR1IF = 0;
    TMR1H = 0xFE;
    TMR1L = 0x0C;// timer interrupt for 1ms
    Elapsed100mS = 1;
  }
}

then in your main code:
Code:
if(Elapsed100mS)
{
  <your routine="" goes="" here="">[clear the WDT]
  [run your routine]
Elapsed100mS = 0;
}

Doing it like that avoids your ISR overrunning and you losing time. This is particularly important if your mysterious 'Display()' routine is lengthy or has any delays in it.

Clearing the WDT inside an ISR is not a good idea, the program can still crash but leave the WDT being cleared so a reset wont occur.

Brian.</your>
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top