07. Работа с UART (Receive)

Первоначальная настройка аналогична настройкам для 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();

 

//—————————————————————

Примечания:

  1. Хоть в функции ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, Uart_Rx_buf); мы указываем буфер — по факту данные хранятся ВО ВНУТРЕННЕМ буфере ESP8266
  2. Из-за того что данных хранятся во внутреннем буфере (регистрах) 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 прерывания по «заполнению буфера».

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *