Я предлагаю вам создать конечный автомат для этого в app.c.
Определите некоторые состояния с помощью enum
и struct
для хранения состояния и помещения их в app.h, включите app.h
в файлы, в которых вы хотите использовать этот модуль (например, файл system_interrupt.c).
Например, вы можете сделать это:
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
Затем создайте функцию для обслуживания вашего конечного автомата. Это будет обрабатывать состояние, в котором оно находится в данный момент, и переходить в другие состояния по желанию. Например, конечный автомат запускается в состоянии IDLE
, но как только ваше прерывание сработало и бит RCIF
установлен, вы перейдете в состояние START_RECEIVING
, которое включит светодиод, а затем перейдет к STILL_RECEIVING
укажите, где он будет опрашивать бит RCIF
до сброса. Это будет выглядеть примерно так:
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;
}
}
}
Теперь ваше прерывание будет выглядеть так:
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
}
}
Теперь вам просто нужно убедиться, что вы вызываете uartFSM()
где-то в APP_Tasks
, чтобы конечный автомат обслуживался.