• Post comments:0 Comments
  • Reading time:4 mins read

When I was trying to use a clarkwise touch screen with ESP8266 on Arduino IDE, I noticed that the serialEvent(); function doesn’t work. I’ve been googling around but found no luck.

Finally, I checked the ESP8266 documentation and also the Documentation for the ESP8266 Arduino Core, I finally got what I need. If you are looking for this too, you are lucky, here is the right answer.

Short answer:

You need 3 steps to make a UART RX Interrupt for ESP8266, it is called UART RX Timeout interrupt.

Step 1 – Copy the handler to your code

Include the header file “uart_register.h”. Then you need to have a handler function, here is one from the documentation:

				
					#include "uart_register.h"
				
			
				
					void uart0_rx_intr_handler(void *para){
  uint8_t RcvChar;
  uint8_t uart_no = UART0;
  uint8_t fifo_len = 0;
  uint8_t buf_idx = 0;
  uint32_t uart_intr_status = READ_PERI_REG(UART_INT_ST(uart_no));//get uart intr status
  while(uart_intr_status != 0x0) {
    if (UART_FRM_ERR_INT_ST == (uart_intr_status & UART_FRM_ERR_INT_ST)){ // if it is caused by a frm_err interrupt
      WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
      Serial.println("caused by a frm_err interrupt");
    } else if (UART_RXFIFO_FULL_INT_ST == (uart_intr_status & UART_RXFIFO_FULL_INT_ST)) { //if it is caused by a fifo_full interrupt
      Serial.println("caused by a fifo_full interrupt");
      fifo_len = (READ_PERI_REG(UART_STATUS(uart_no)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT; //read rf fifo length
      char r[fifo_len];
      buf_idx = 0;
      while (buf_idx < fifo_len) {
        r[buf_idx] = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF;
        buf_idx++;
      }
      r[fifo_len] = '\0';
      WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); //clear full interrupt state
    } else if (UART_RXFIFO_TOUT_INT_ST == (uart_intr_status & UART_RXFIFO_TOUT_INT_ST)) { //if it is caused by a time_out interrupt
      Serial.println("caused by a time_out interrupt");
      fifo_len = (READ_PERI_REG(UART_STATUS(uart_no)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT; //read rf fifo length
      char r[fifo_len];
      buf_idx = 0;
      while (buf_idx < fifo_len) {
        r[buf_idx] = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF;
        buf_idx++;
      }
      r[fifo_len] = '\0';
      WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_TOUT_INT_CLR); //clear full interrupt state
    } else if (UART_TXFIFO_EMPTY_INT_ST == (uart_intr_status & UART_TXFIFO_EMPTY_INT_ST)) { //if it is caused by a tx_empty interrupt
      Serial.println("caused by a tx_empty interrupt");
      WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR);
      CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_TXFIFO_EMPTY_INT_ENA);
    } else {

    }
    uart_intr_status = READ_PERI_REG(UART_INT_ST(uart_no)); //update interrupt status
  }
}
				
			

It is farily straight forward. Copy the code to your file.

Step 2 – Create your call back function

Create a function about what you gonna do, and call it from the Serial.println(“…”); sentences.

IMPORTANT:

  • Your function must not call delay() or yield(), or call any routines which internally use delay() or yield() either.
  • Runs within 1ms. Long-running (>1ms) tasks in interrupts will cause instability or crashes. WiFi and other portions of the core can become unstable if interrupts are blocked by a long-running interrupt. 

Inside the code, you can see there is no Serial.readString(); Because there is a delay() inside it. We read the byte directly from the buffer and got the data in String r.

If you want to execute complex commands, better set a flag and run it in the loop.

Step 3 – Install the handler

 

				
					static void install_uart_tout(){
  ETS_UART_INTR_DISABLE();
  ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, NULL);
  
  WRITE_PERI_REG(UART_CONF1(0), UART_RX_TOUT_EN |
    ((0x2 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S));

  WRITE_PERI_REG(UART_INT_CLR(0), 0xffff);
  SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_TOUT_INT_ENA);
  CLEAR_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA);
  
  ETS_UART_INTR_ENABLE();
}
				
			

The code above is a time out handler. Call it from setup().

This will:

  • Turn on UART RX Timeout interrupt
  • Turn off UART RX Buffer Full Interrupt
  • Set the time out to 2 bits receiving time (about 1/4800 s with the UART baud rate of 9600 bps)
  • Attach the uart0_rx_intr_handler() function as the interrupt handler

I will have a longer tutorial full introduce the ESP8266 UART Rx Interrupt.

Cheers!

Reference:

https://www.espressif.com/sites/default/files/documentation/esp8266-technical_reference_en.pdf

https://arduino-esp8266.readthedocs.io/en/2.7.4_a/index.html

close

Updates

Tips

Coupons

We don’t spam! Read our privacy policy for more info.

Leave a Reply