Первоначальная настройка аналогична настройкам для Uart_Tx.
В самом верху файла после #include необходимо прописать заглушки (они необходимы для работы с прерываниями):
void ets_isr_mask(unsigned intr);
void ets_isr_unmask(unsigned intr);
Создадим переменные для работы:
uint8_t Uart_Rx_buf[5]={0}; //Буфер на прием
uint8_t Rx_Cnt=0; //счетчик принятых байт
uint8_t Rx_len=5; //длинна буфера
uint8_t Flag=0; //Флаг что приняли данные
Напишем callback функцию с обработкой событий:
void uart0_rx_intr_handler(void *para)
{
//прерывание для "других" ошибок по приему
if (UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_FRM_ERR_INT_ST))
{
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_FRM_ERR_INT_CLR);
}
//прерывание по событию приема всех данных (Rx fifo full event)
if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_FULL_INT_ST))
{
uart_rx_intr_disable(UART0);
}
//прерывание по таймауту приема
else if (UART_RXFIFO_TOUT_INT_ST== (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_TOUT_INT_ST))
{
uart_rx_intr_disable(UART0);
}
//нет данных на передачу
else if (UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_TXFIFO_EMPTY_INT_ST))
{
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_TXFIFO_EMPTY_INT_CLR);
}
//переполнение буфера на передачу
else if (UART_RXFIFO_OVF_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_OVF_INT_ST))
{
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_OVF_INT_CLR);
}
//смотрим наличие байта!!!
uint8_t Rx_len_buf=(READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT;
if(Rx_len_buf)
{
//копирум принятый байт
Uart_Rx_buf[Rx_Cnt]=READ_PERI_REG(UART_FIFO(UART0)) &0xff;
Rx_Cnt++;
if(Rx_Cnt<Rx_len) //если приняли не все байты, то перезапуск UART
{
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR|UART_RXFIFO_TOUT_INT_CLR);
uart_rx_intr_enable(UART0);
}
else Flag=0xff;
}
}
После функции настройки скоростей uart сделаем настройки для прерываний
//-----
uart_init(BIT_RATE_115200, BIT_RATE_115200);
ETS_UART_INTR_DISABLE(); //выкл прерывания
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, Uart_Rx_buf); //Функция прерывания и буфер
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); //Отключить подтяжку на выводе
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); //выбрать функцию для передатчика
ETS_UART_INTR_ENABLE(); //Включить прерывания
//-------------
В вечном цикле напишем код:
ets_delay_ms(500);
if(Flag==0xff) uart0_tx_buffer(Uart_Rx_buf,5); //передаем принятые байты
if(Rx_Cnt==Rx_len)
{
Rx_Cnt=0;
Flag=0;
//Очистка буфера UART
// SET_PERI_REG_MASK(UART_CONF0(UART0), UART_TXFIFO_RST);//RESET FIFO
SET_PERI_REG_MASK(UART_CONF0(UART0), UART_RXFIFO_RST);//RESET FIFO
CLEAR_PERI_REG_MASK(UART_CONF0(UART0), UART_RXFIFO_RST);
//Перезапуск UART
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR|UART_RXFIFO_TOUT_INT_CLR);
uart_rx_intr_enable(UART0);
}
system_soft_wdt_feed();
//—————————————————————
Примечания:
- Хоть в функции ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, Uart_Rx_buf); мы указываем буфер — по факту данные хранятся ВО ВНУТРЕННЕМ буфере ESP8266
- Из-за того что данных хранятся во внутреннем буфере (регистрах) ESP8266 необходимо выполнять очистку буфера приема uart
//Очистка буфера UART
SET_PERI_REG_MASK(UART_CONF0(UART0), UART_RXFIFO_RST);//RESET FIFO
CLEAR_PERI_REG_MASK(UART_CONF0(UART0), UART_RXFIFO_RST);Иначе при приеме большого объема данных и длительной обработке иожно долго обрабатывать сбщ.
Например посылается последовательность 1, 2…9 при нашем «программном» буфере 5 (Uart_Rx_buf[5]) а потом еще 1 число «10», то в буфере будут числа 1, 2…10. Т.е. будет 2 прерывания по «заполнению буфера».