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.

Glow LED on specified counter values 0-500 in 89c52 uC

Status
Not open for further replies.
How to use state machine handling delays with flags?

By using state machine you would always return to an Idle state instead of being blocked within execution of a Delay function, in addition to the obvious advantage of having a better structured program. As you did, it is not any issue at all if blink two leds is the only thing you have to do but if you need to read for example a key pressed within 1s would not work, so it is time to you get introduced to better practices in coding; make a search on the Web for the keyword FSM ("finite state machice") and you will have insights to apply this approach on your programs.
 

Try this.

Code:
volatile unsigned int Counter = 0;
volaile unsigned int oldCounter = 0;

void ext0_isr(void) interrupt 0
{ 
	Counter++;	
}

main()
{ 
if((Counter >= 10) && ((Counter % 15) == 10))LED1 = 1;
elseif((Counter >= 15) && ((Counter % 10) == 0))LED2 = 1;
delay(1000);
LED1 = 0;
LED2 = 0;
}

Still this is a blocking code. If you want non-blocking code then put this piece of code in a 1 second timer interrupt without the delay(1000) code that is just the code which is in while(1) loop into timer interrupt code.
 

By using state machine you would always return to an Idle state instead of being blocked within execution of a Delay function, in addition to the obvious advantage of having a better structured program. As you did, it is not any issue at all if blink two leds is the only thing you have to do but if you need to read for example a key pressed within 1s would not work, so it is time to you get introduced to better practices in coding; make a search on the Web for the keyword FSM ("finite state machice") and you will have insights to apply this approach on your programs.

I am thankful to you and inspired by you for giving good solutions.


I did not use in code util/delay.h but wrote my own timer0 mode 1 code for approx 100usec.

Code:
unsigned int i,x;

void delay(i)          //100usec delay
	{
	for(x=0 ; x<=i ; x++){
	TMOD = 0x01;    // Timer0 mode1
	TH0 = 0xFF; 	 //initial value for 100usec
	TL0 = 0xA2;
	TR0 = 1;      // timer start
	while(TF0==0);  // check overflow condition
	TR0 = 0;     // Stop Timer
	TF0 = 0;    // Clear flag
	}
	}

- - - Updated - - -

Try this.

Code:
volatile unsigned int Counter = 0;
volaile unsigned int oldCounter = 0;

void ext0_isr(void) interrupt 0
{ 
	Counter++;	
}

main()
{ 
if((Counter >= 10) && ((Counter % 15) == 10))LED1 = 1;
elseif((Counter >= 15) && ((Counter % 10) == 0))LED2 = 1;
delay(1000);
LED1 = 0;
LED2 = 0;
}

Still this is a blocking code. If you want non-blocking code then put this piece of code in a 1 second timer interrupt without the delay(1000) code that is just the code which is in while(1) loop into timer interrupt code.



Ok I will do it.
 

Hi,

if((Counter >= 10) && ((Counter % 15) == 10))LED1 = 1;

Is the same as
if ( (Counter % 15) == 10) LED1 = 1;

Klaus
 

If you want non-blocking code then put this piece of code in a 1 second timer interrupt

Not a good recommendation to insert pieces of code inside interrupt vectors. As far as possible, the only service to be performed there is the triggering of a flag to be handled in the main() function, which in your provided code misses the enclosing while(1) sentence.
 
Oops... Yes, forgot to wrap in while(1) loop

Code:
volatile unsigned int Counter = 0;
volaile unsigned int oldCounter = 0;

void ext0_isr(void) interrupt 0
{ 
	Counter++;	
}

main()
{ 

while(1) {
if((Counter % 15) == 10)LED1 = 1;
elseif((Counter >= 15) && ((Counter % 10) == 0))LED2 = 1;
delay(1000);
LED1 = 0;
LED2 = 0;
}
}
 

Code:
void ext0_isr(void) interrupt 0
{ 
	Counter++;	
}

Again, a well-written code ideally do not perform any task in handling interrupts other than triggering flags. In the above case, if during the execution of the program, the interruption changes the value of the Counter variable (which is evaluated several times during the program), the result could be unexpected. Interrupts, particularly external ones, are assynchonous with the code, it can happen at any time, not sure that will be at the beginning of the routine.

The correct action could be something like:


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void ext0_isr (void) interrupt 0 {
      bExtTimer0Interrupt = true;
      }
 
main ()
{
while (1) {
      if (bExtTimer0Interrupt) {
            Counter ++;
            bExtTimer0Interrupt = false;
            }
      ...
      ...
      }



We are obviously not talking about a critical life support application, just a led blinker; but if you are going to recommend a code, please do it by adopting good practices.
 
Last edited:

By using state machine you would always return to an Idle state instead of being blocked within execution of a Delay function, in addition to the obvious advantage of having a better structured program. As you did, it is not any issue at all if blink two leds is the only thing you have to do but if you need to read for example a key pressed within 1s would not work, so it is time to you get introduced to better practices in coding; make a search on the Web for the keyword FSM ("finite state machice") and you will have insights to apply this approach on your programs.

I wrote a code using Interrupt of Timer 1 mode 2 generating output of 25us and some state machine look but please let me know how add delay between LED toggling, i.e 1 second delay.

Code:
#include <reg52.h>
volatile unsigned int counter = 0;
bit flag = 0;
sbit LED = P2^0;
unsigned char STATE;


void timer1_isr() interrupt 3
{	
	flag = 1;			
}

void main()
{
    TMOD = 0x20;       //Timer1 mode 2  //  Generating 25us pulse Total time period is 50us
    TH1 = 0XE9;        //Load the timer value
    TR1 = 1;           //turn ON Timer zero
    ET1 = 1;           //Enable TImer1 Interrupt
    EA = 1;            //Enable Global Interrupt bit
    STATE = 0;
    while(1)
    {
			if(flag)
				{
			switch(STATE)
			{
			
                        case 0:
			LED = 1;
			STATE = 1;
		        break;
				
			case 1:
			LED = 0;
			STATE = 0;
		        break;
			
                        default:
			STATE = 0; 
			break;			
			}
	     	              }
			
			
    }
}
 

This is an incomplete code, you are not reseting the variable flag anywhere, as well as you are no more incrementing Counter variable which should be used in additioin to other variables, when turn on and off the LED. Draw a flowchart prior to coding, or at least review the code before asking for help.
 
Post your circuit and also your Keil complete project files.

Also, mention what is your Crystal frequency, 12MHz, 11.0592MHz,...?
 
This is complete working code thanks for andre_teprom for recommending Finite State Machine Algorithm.

And also thanks for all thread members.

The only thing in this code is Timer Interrupt delay I calculated for 25us but microsecond value should be 40000 for (25us x 40000) = 1 sec delay.
But it was not, it was work with microsecond = 11000. But why :thinker:

I am working with 11.0592Mhz Crystal.

11.0592/12 clock cycles = 921.6~ 922kHz. --->>> 1/922kHz = 1.085us.

for example: for 25us delay --> 25us/1.085us = 23 -->> 256-23=233 convert to hex --> 0xE9 Timer 1 mode 2 (Auto-Reload).

Code:
#include <reg52.h>
volatile unsigned int counter = 0;
bit flag = 0;
sbit LED = P2^0;
#define LED_OFF 0
#define LED_ON_WAIT 1
#define LED_ON 2
#define LED_OFF_WAIT 3
#define microseconds 11000
unsigned char STATE = LED_OFF;

void timer1_isr() interrupt 3
{	
	flag = 1;			
}

void main()
{
    TMOD = 0x20;       //Timer1 mode 2  //  Generating 25us pulse Total time period is 50us
    TH1 = 0xE9;        //Load the timer value
    TR1 = 1;           //turn ON Timer zero
    ET1 = 1;           //Enable TImer1 Interrupt
    EA = 1;            //Enable Global Interrupt bit
	  STATE = 0;
    while(1)
    {		
			switch(STATE)
			{
				case LED_OFF:
					LED = 0;				  
				  STATE = LED_ON_WAIT;				
				break;
					
				
				case LED_ON_WAIT:
				if(counter >= microseconds)
					{					
				  STATE = LED_ON;
					counter = 0;
				  }		  
				break;
					
				case LED_ON:
				LED = 1;				  
				STATE = LED_OFF_WAIT;	
				break;
				
				case LED_OFF_WAIT:
				if(counter >= microseconds)
					{					
				  STATE = LED_OFF;
					counter = 0;
				  }	
				break;
				
				default:					
				break;			
			}	
			
						if(flag == 1)
							{					
						if(counter < 65535)  
							{
							 counter++;
							}
							flag = 0;
							}
	  }			
}

- - - Updated - - -

Please find circuit and project file.
 

Attachments

  • Circuit.png
    Circuit.png
    88.7 KB · Views: 142
  • FSM Project.rar
    12.1 KB · Views: 102
Last edited:

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top