+ Post New Thread
Results 1 to 5 of 5
  1. #1
    Member level 5
    Points: 673, Level: 5

    Join Date
    Aug 2018
    Posts
    81
    Helped
    0 / 0
    Points
    673
    Level
    5

    Displaying the time parameter using Timer interrupt

    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];    
    
        }
    
     }

    •   AltAdvertisement

        
       

  2. #2
    Super Moderator
    Points: 83,850, Level: 70
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    13,796
    Helped
    4578 / 4578
    Points
    83,850
    Level
    70

    Re: Displaying the time parameter using Timer interrupt

    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.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.



    •   AltAdvertisement

        
       

  3. #3
    Member level 5
    Points: 673, Level: 5

    Join Date
    Aug 2018
    Posts
    81
    Helped
    0 / 0
    Points
    673
    Level
    5

    Re: Displaying the time parameter using Timer interrupt

    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();
    	}
    
    }



    •   AltAdvertisement

        
       

  4. #4
    Advanced Member level 4
    Points: 7,888, Level: 21
    Achievements:
    7 years registered

    Join Date
    Jul 2010
    Location
    Sweden
    Posts
    1,059
    Helped
    403 / 403
    Points
    7,888
    Level
    21

    Re: Displaying the time parameter using Timer interrupt

    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) {



  5. #5
    Super Moderator
    Points: 83,850, Level: 70
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    13,796
    Helped
    4578 / 4578
    Points
    83,850
    Level
    70

    Re: Displaying the time parameter using Timer interrupt

    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)
    {
      [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.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.



--[[ ]]--