1

Please give a favor,

I am using MikroC compiler to write a program for 8051 microcontrollers, I am trying to find a way to execute and repeat the main program for 10 seconds, then stop for 2 seconds

Code below just an example, I need to toggle Port two each 200 msec, repeat that for 10 sec, then stop for 2 sec, then repeat this operation.

void main()
{
    P2 = 0xAE;

    while (1) {
        P2 = ~P2;
        Delay_ms(200);
    }
}

Thank you

the busybee
  • 10,755
  • 3
  • 13
  • 30
Elia
  • 37
  • 1
  • 8
  • Is `Delay_ms()` a function of a library of MicroC? Did you consider using a counter to measure the 10 s and the 2 s? BTW, your source is incomplete and can not be compiled. – the busybee Nov 28 '19 at 06:51
  • Thanks for your replay. the code in the example is correct and tested. MikroC has many weird commands – Elia Nov 28 '19 at 09:22
  • @Elia: you cannot do this using a delay since you don't know how long the rest of your code takes to execute. You will need a way of measuring time or clock ticks. The simplest way would probably be to create a (say) 1 ms timer which will increment a variable atomically, and then act when this variable becomes larger than 10000. – vgru Nov 28 '19 at 10:15
  • @Groo It depends on the required accuracy of the 200 ms. In the code shown the overhead of the other instructions and the loop is magnitudes lower than the delay and therefore negligible. – the busybee Nov 28 '19 at 11:02
  • which 8051 mcu are you using? – old_timer Nov 29 '19 at 04:29

1 Answers1

1

You can use a counter to measure the time: For example:

#define MS_PER_TICK       200
#define BLINK_PERIOD_IN_S 10
#define PAUSE_PERIOD_IN_S 2

#define BLINK_PERIOD_IN_TICKS (BLINK_PERIOD_IN_S * 1000 / MS_PER_TICK)
#define PAUSE_PERIOD_IN_TICKS (PAUSE_PERIOD_IN_S * 1000 / MS_PER_TICK)

void main(void) {
    unsigned char ticks = 0;

    P2 = 0xAE;

    for (;;) {
        Delay_ms(MS_PER_TICK);
        ticks++;

        if (ticks <= BLINK_PERIOD_IN_TICKS) {
            P2 = ~P2;
        }
        if (ticks == BLINK_PERIOD_IN_TICKS + PAUSE_PERIOD_IN_TICKS) {
            ticks = 0;
        }
    }
}
the busybee
  • 10,755
  • 3
  • 13
  • 30
  • Thank you very much for your support, I have applied it to my code and it works perfectly, the only problem is it never switch to case(2) The code is below – Elia Nov 28 '19 at 12:29
  • This approximation might work for simple programs, but future readers who come here asking for a similar solution might get the wrong impression that it's generally correct. Timing problems in microcontrollers are meant to be solved using timers. – vgru Nov 28 '19 at 14:51
  • I have tested that solution for a code to send a text message through the serial port and it works perfectly – Elia Nov 28 '19 at 16:48
  • @Groo Without looking into the source of `Delay_ms()` we don't know how it delays. There might well be a timer which ticks at exactly 1 ms, as exact as a crystal can be. The rest of the program will need by far less than 1 ms so it will be OK. But as said before, we have no requirement for accuracy, that's why I chose the simple solution as near to the OP's code as possible. – the busybee Nov 28 '19 at 17:26
  • @Elia Using serial communication will introduce some noticeable delay depending on the baudrate and the number of characters sent. It's fine if you meet your requirements, but keep in mind what Groo pointed at. – the busybee Nov 28 '19 at 17:28
  • @thebusybee: it's not an issue in this case, I wasn't saying that `Delay_ms()` is imprecise, it's likely a busy loop with a much better resolution than the 1ms timer (unless OP has a 1kHz crystal, which I doubt). But the end result will depend heavily on the duration of the rest of the code, and most people beginning to program microcontrollers tend to place everything into a single `main()` function and depend on these busy loops for timing, which creates problems as the program grows. – vgru Nov 28 '19 at 18:35