This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

pedestrian road crossing - c code

I am trying to program the 8051 for a "Pelican" type pedestrian road crossing. It should control the red, amber and green lights for the traffic, the red and green pedestrian lights, and the bleeper. I have written some code but unfortunately it does not work. Bits 0 to 5 of P1 are supposed to control the lights and the bleeper and bit 0 of P2 is supposed to control the pedestrian button. Any ideas where the problem is? Code size limit is 2K.
Thanks!
Marko

#include <reg51.h>

sbit red_traf=P1^0;
sbit amber_traf=P1^1;
sbit green_traf=P1^2;
sbit red_ped=P1^3;
sbit green_ped=P1^4;
sbit bleeper=P1^5;
sbit button=P2^0;
unsigned char count;

void delay_vshort()
                        {
                        unsigned int x;
                        for (x=0;x<65536;x++);
                        }

void delay_short()
                        {
                        unsigned int x;
                        for (x=0;x<131072;x++);
                        }

void delay_long()
                        {
                        unsigned int x;
                        for (x=0;x<1048576;x++);
                        }


main()
        {
        P2 = 0xff;
        s0:
        green_traf=1;
        red_ped=1;
        if (button==1) goto s1;
        else goto s0;

        s1:
        amber_traf=1;
        red_ped=1;
        delay_short();
        goto s2;

        s2:
        red_traf=1;
        green_ped=1;
        bleeper=1;
        delay_long();
        goto s3;

        s3:
        for (count=0;count<5;count++)
                {
                amber_traf = 1;
                green_ped = 1;
                delay_vshort();
                amber_traf = 0;
                green_ped = 0;
                delay_vshort();
                }
                goto s4;

        s4:
        amber_traf=1;
        red_ped=1;
        delay_short();
        goto s0;
        }

Parents
  • One way to increase your delay is to add NOPs (the asm code for No Operation Keil gives you a macro for it

    void delay(unsigned int msec)
    {
        unsigned int x;
    
        while (msec > 0)
        {
           // YOU Need to figure out the number of nops
           // and how big x needs to be
           // since x is an unsigned int it must be less than 65535
           for (x=0;x<9999;x++)
           {
              _nop_;
              _nop_;
              _nop_;
              _nop_;
              _nop_;
           }
           msec--;
       }
    
     }
    
     the time a nop uses is different  for different cpus
    The standard is 1/12 the crystal frequency.
    
    This will get you started.  You would move on to using the timer interupt later.
    the interupt also give you the benifit that your cpu is not doing nothing during the delays.  It can do something else during the delay time.
    
    
    

Reply
  • One way to increase your delay is to add NOPs (the asm code for No Operation Keil gives you a macro for it

    void delay(unsigned int msec)
    {
        unsigned int x;
    
        while (msec > 0)
        {
           // YOU Need to figure out the number of nops
           // and how big x needs to be
           // since x is an unsigned int it must be less than 65535
           for (x=0;x<9999;x++)
           {
              _nop_;
              _nop_;
              _nop_;
              _nop_;
              _nop_;
           }
           msec--;
       }
    
     }
    
     the time a nop uses is different  for different cpus
    The standard is 1/12 the crystal frequency.
    
    This will get you started.  You would move on to using the timer interupt later.
    the interupt also give you the benifit that your cpu is not doing nothing during the delays.  It can do something else during the delay time.
    
    
    

Children
  • 1."Goto" statement has been replaced with while.
    2.Delays are generated by using 8051's internal timer.
    3.The code is now hopefully properly commented.

    What I would like to do now is to extend the whole thing a bit by adding a sort of a lock-out function for the pedestrian button so that green pedestrian light cannot go green too quickly since the last time the button was pressed because that would hinder the flow of traffic.
    I do have a general idea of how to do that using a counter/timer, but implementation is a bit tricky for me because of my lack of skills.
    The code should probably look something like this:
    1.when a button is pressed a counter should be started
    2.if a button is pressed again the counter should be checked to see if it has reached a certain level
    3.if the level has been reached the program should continue
    4.if the level has not been reached the counter should continue counting till the level is reached
    6.when the level is reached stop the counter and continue with the program

    Would that be a good approach?
    Any comments regarding the code?

    Regards,
    Marko

    P.S.
    The code so far:

    #include <reg664.h>    //register map for 8051
    
    #define ON      1
    #define OFF     0
    
    sbit red_traf = P1^0;   //red traffic light is connected to bit 0 of P1
    sbit amber_traf = P1^1; //amber traffic light is connected to bit 1 of P1
    sbit green_traf = P1^2; //green traffic light is connected to bit 2 of P1
    sbit red_ped = P1^3;    //red pedestrian light is connected to bit 3 of P1
    sbit green_ped = P1^4;  //green pedestrian light is connected to bit 4 of P1
    sbit bleeper = P1^5;    //bleeper is connected to bit 5 of P1
    sbit button = P2^0;     //pedestrian button is connected to bit 0 of P2
    unsigned char count;
    
    void delay(int del)                     //delay procedure
            {
            int c=0;
            TMOD=0x01;                      //CT1 not used, CT0 as a timer, in mode 01
            TR0=0;
            TF0=0;
                    do
                    {
                    TH0=0;                  //Load CT0 with zero to get
                    TL0=0;                  //the longest possible time.
                    TR0=1;                  //start timer
                    while(!TF0);            //while Timer Flag is low, do nothing i.e.wait till it goes high
                    TR0=0;                  //stop timer
                    TF0=0;                  //make timer flag low again
                    c++;
                    }
            while (c<del);
            }
    
    main()
    {
            while (1)                       //infinite loop
    
            {
                P1 = 0x00;                 //reset all bits of P1
                P2 = 0xff;                 //Make all bits 1, so that port2 works as
                                           //an input port.
    
                /* Go traffic */
                // traffic:     G = ON,  A = OFF, R = OFF
    
                // pedestrians: G = OFF,          R = ON
    
                green_traf = ON;
                red_ped    = ON;
    
                while (button) {}         // wait for button
    
                // traffic:     G = OFF, A = ON,  R = OFF
    
                // pedestrians: G = OFF,          R = ON  - no change
    
                green_traf = OFF;
                amber_traf = ON;
    
                delay (30);              // short delay
    
    
                /* Go pedestrians */
                // traffic:     G = OFF, A = OFF, R = ON
    
                // pedestrians: G = ON,           R = OFF
    
                amber_traf = OFF;
                    red_traf  = ON;
                red_ped   = OFF;
                green_ped = ON;
    
                bleeper   = ON;     // turn bleeper on
    
                    delay (100);    // long delay
    
                // traffic:     G = OFF, A = ON, R = OFF
    
                // pedestrians: G = ON,          R = OFF
    
                bleeper = OFF;      //Turn off the bleeper
                red_traf=OFF;       //Switch off red traffic light
    
                for (count=0;count<7;count++)   //This will make amber traffic and green pedestrian light flash five times
                    {
                    amber_traf=ON;          //Switch amber traffic light on
                    green_ped=ON;           //Switch green pedestrian light on
                    delay(5);               //Wait for a very short time
                    amber_traf=OFF;         //Switch both previous lights off
                    green_ped=OFF;
                    delay(5);
                    }
            }               //infinite loop
    }                       //main
    
    

  • Neil Kurzman thanks for your comments. They were very useful.

    Regards,
    Marko

  • Think a bit more about your comments.

    Make sure that your functions and variables have names so that you never have to make comments about what you do.

    You seldom want to write comments that say _what_ you do - unless you have a very hairy algorithm. You normally want to write comments about _why_ you do things.

    Why use comment "turn off bleeper" for a line like:

    bleeper = OFF;
    

    Why comment delay(100) as "long delay"? How long is it? Why do you have a delay? If the delay function makes delays in ms - rename it as delay_ms(delay) and let the reader decide if it is a long delay or not.

  • Now you are programming. You need a plan.
    One way to do this is to have a periodic "Event" either in an interupt if it is short. Else, the interupt sets a flag and the event is handled from a function call in main.

    Lets assume you set a flag every 100ms in an interupt.

    when this flag is seen in the main loop you can decrement all your timers by 1 tick.

    Example
    if(tickFlag)
    {
       tickFlag = 0;              // clear tick flag
       if(Counter1 > 0)Counter1--;// dec counter down to 0
    }
    

    Then assuming Counter1 was you timer lock out. You would ignore the button if the counter is not 0;

    This is one posible way. There are may ways to do this task.