0
\$\begingroup\$

I am using PIC32MX795F512L Micro Controller.

I need to develop an application where 4 led's connected to pins of controller will blink continuously at a rate of 1sec and there are 15 inputs connected to controller. These inputs will send some data to UART whenever they get HIGH. For example:

while(1)
{
if(input1 == HIGH)
{
 putsUART1("input1 HIGH"); 
}
if(input2 == HIGH)
{
 putsUART1("input2 HIGH");
}

//same for rest of the inputs

LED1 = HIGH
delay(1000);
LED2 = HIGH
delay(1000);
LED3 = HIGH
delay(1000);
LED4 = HIGH
delay(1000);

LED1 = LOW
delay(1000);
LED2 = LOW
delay(1000);
LED2 = LOW
delay(1000);
LED2 =LOW
delay(1000);
}

above technique is polling method and is not giving real time input data to UART. I thought of using UART TX Interrupt but dont have good experience in it. I have just downloaded FreeRTOS for PIC32 and created few task and using RTOS it is working fine. Should I continue using RTOS or switch to use Interrupts. If there is any other way of doing it, Please help

\$\endgroup\$

4 Answers 4

1
\$\begingroup\$

Modify your delay() rotuine such that the polling is done inside of it, something like this:

void my_delay(int ms)
{
  int tens_ms, units_ms;

  tens_ms = ms / 10;
  units_ms = ms % 10;

  for (i=0; i < tens_ms; i++)
  {
    if(input1 == HIGH)
    {
      putsUART1("input1 HIGH"); 
    }
    if(input2 == HIGH)
    {
      putsUART1("input2 HIGH");
    }
    //same for rest of the inputs

    delay(10);
  }

  delay(units_ms);
}

while(1)
{
  LED1 = HIGH
  my_delay(1000);
  LED2 = HIGH
  my_delay(1000);
  LED3 = HIGH
  my_delay(1000);
  LED4 = HIGH
  my_delay(1000);
}

So now a call to delay(1005) (as an example) would be broken up into 100 calls to delay(10) and one call to delay(5). Assuming you are running the UART at a high baud rate like 115.2K (so sending one of the strings should take only a millisecond or so) and your inputs don't change too often, the overall timing of the LEDs should not be affected too much.

Meanwhile, the UART output should not be more than 10 milliseconds behind the input changes.

Just an aside, you may want to add a \r\n at the end of each string, unless your putsUART1 function automatically adds those.

\$\endgroup\$
3
  • \$\begingroup\$ thanks I have done the same thing. I have made a function inputs for all inputs and calling input after every led. So its working but now I have managed to write a code for TX RX interrupts. Here is my new question: electronics.stackexchange.com/questions/202873/… \$\endgroup\$ Commented Nov 26, 2015 at 11:24
  • \$\begingroup\$ This code creates a tight coupling between the UART transmission time and the delays, where they depend on each other. Suppose there is not enough TX buffers to store the whole message, so that the transmission routine has to wait for the message to get sent; the delays would be arbitrary and real-time non-existent. \$\endgroup\$
    – Lundin
    Commented Nov 26, 2015 at 13:33
  • \$\begingroup\$ @Lundin Agree, that's why I brought up the issue of the UART speed, input rate etc. At 115.2K baud, one message should not take more than about a ms. Obviously an interrupt driven system is a better way to go. This was meant to be a quick refactoring of the original code. I assumed the chances of all the chances of all inputs firing at once are low. \$\endgroup\$
    – tcrosley
    Commented Nov 26, 2015 at 14:50
3
\$\begingroup\$

your problem lies within the delay() statements. You've got multiple options:

  • Stay with a main forever loop (while (1) {}), but poll the inputs more often, so you can send on your uart.
  • Switch to interrputs to handle either the input handling (the UART TX interrupt won't help you, you'll need to get an interrupt, when an input event occurs
  • on the other hand, you could set up an timer on the chip, to give you interrupts on 1000ms (or 100ms or wahtever) intervalls, so you can control the lights from the interrupt subroutine.
  • you could use RTOS and implement tasks, which does stuff like that under the hood
\$\endgroup\$
3
\$\begingroup\$

Both are valid choices, actually it's up to you which way you'll be going.

Advantages of using interrupts without a RTOS are that your system complexity is reduced in such a small system. Usually the burden is to get the RTOS up and running and have it handle the various subtasks (e.g. USB, Ethernet, ...).

The advantage of using the RTOS certainly is that you already have it up and running and it's obviously working as you would expect it to.

Just for reference, here is some very simple source code that describes how you can easily create your own logic (when not using an RTOS):

volatile uint32_t ms_ticks = 0;
volatile bool tick_1ms_elapsed = false;
volatile bool tick_10ms_elapsed = false;
volatile bool tick_100ms_elapsed = false;
volatile bool tick_1000ms_elapsed = false;
volatile bool tick_5000ms_elapsed = false;

// This is the interrupt handler
void SysTick_Handler(void)
{
    ms_ticks++;

    tick_1ms_elapsed = true;

    if (ms_ticks % 10 == 0) {
        tick_10ms_elapsed = true;
    }
    if (ms_ticks % 100 == 0) {  
        tick_100ms_elapsed = true;
    }
    if (ms_ticks % 1000 == 0) {
        tick_1000ms_elapsed = true;
    }
    if (ms_ticks % 5000 == 0) {
        tick_5000ms_elapsed = true;
    }
}

int main() {
    while(true) {

        if (tick_1ms_elapsed) {
            tick_1ms_elapsed = false;
            // Task every 1ms here
        }
        if (tick_10ms_elapsed) {
            tick_10ms_elapsed = false;
            // Task every 10ms here
        }
        if (tick_100ms_elapsed) {
            tick_100ms_elapsed = false;
            // Task every 100ms here
        }
        if (tick_1000ms_elapsed) {
            tick_1000ms_elapsed = false;
            // Task every 1000ms here
        }   
        if (tick_5000ms_elapsed) {
            tick_5000ms_elapsed = false;
            // Task every 5000ms here           
        }       
    }
}
\$\endgroup\$
0
\$\begingroup\$

A professional solution does not use any hobbyist "software delays" at all, but simply a few hardware timers:

  • One timer is set to behave as a very low-frequent PWM, to toggle the blinking LEDs. Timer cycles are handled by the hardware entirely or by small ISRs, depending on timer hardware.
  • One timer is set to poll all inputs synchronously and continuously, at a certain frequency. Could involve digital filters if needed.
  • There needs to be a double-buffer mechanism so that a complete series of inputs are stored in another buffer than the one getting periodically filled.
  • Printing on UART etc is done from the main program, on the copied buffer. Depending on the number of tx hardware buffers in the UART, DMA availability etc, you may or may not need another software buffer to store the things the UART should print. Under no circumstances should you busy-wait for the UART transmission to be complete.
  • UART TX interrupt is only useful if you have a UART peripheral with limited hardware buffers. You'll then have to set up a FIFO which you can grab new data from, upon each UART TX interrupt.
  • When not doing any of the above, the main program can either run at full speed, doing what else needs to be done, or the CPU can sleep in a low power consumption mode.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.