I'm trying to keep a led ON while PIC is receiving a character (while a button is pressed), the led being OFF by default, but I can't seem to find a solution.
I'm 3 months in learning using microcontrollers (specifically PIC) coding with MPLABX IDE and started understanding UART communication. At first I tried turning a led ON/OFF when a charater is received, it went pretty good and worked, but right now I'm trying to keep a led active while a button is pressed but can't really get over this problem. I have my code in a interrupt function like this :
//#define LED RB5
void __interrupt () ISR (void)
{
if(RCIF) // data is received
{
data = RCREG; // get the value
if (data == '1') // if value received is '1'
LED = 1; //turn ON led
RCIF = 0;
}
LED = 0; // turn OFF led
}
Using the above code makes so the led turns on/off really fast while I keep pressing a button and isn't really what I wanted.
I hope someone can help me understand what I need to do. Thanks !
I suggest you create a state machine for this in app.c.
Define some states with an enum
and a struct
to hold the state and place them in app.h, include app.h
in files where you wish to use this module (e.g. your system_interrupt.c file).
For example you could do this:
typedef enum{
IDLE,
START_RECEIVING,
STILL_RECEIVING,
}uart_state_t;
typedef struct{
uart_state_t current_state;
}uart_module_t
volatile uart_module_t uart_module = {0}; // initial state = IDLE, needs to be volatile because it will be updated via interrupt
Then create a function to service your state machine. This will handle the state that it is currently in and transition to other states as desired. For instance, the state machine starts in the IDLE
state but once your interrupt has fired and RCIF
bit is set then you'll transition in to the START_RECEIVING
state which will turn the LED on then transition to the STILL_RECEIVING
state where it will poll the RCIF
bit until cleared. That would look something like this:
void uartFSM(void){
switch(uart_module.current_state){
case IDLE:
{
break;
}
case START_RECEIVING:
{
LED = 1; // Turn LED on
uart_module.current_state = STILL_RECEIVING; // state update
break;
}
case STILL_RECEIVING:
{
if(!RCIF){
// done receiving
LED = 0; // Turn LED off
uart_module.current_state = IDLE; // state update
}
break;
}
default:
{
// whoops
break;
}
}
}
Now your interrupt will look like this:
void __interrupt () ISR (void)
{
if(RCIF) // data is received
{
data = RCREG; // get the value
// if value received is '1'
if (data == '1') uart_module.current_state = START_RECEIVING; // state update
}
}
Now you just have to make sure that you call the uartFSM()
some where in APP_Tasks
so that the state machine gets serviced.