Why?

Despite the fact that the ESP8266 was designed as a serial-wifi device, I’ve recently found the need to extend the ESP’s the UART support using an another IC, to allow myself to reliably interface to a heat meter supporting the M-Bus protocol.

  • otb-iot uses the standard hardware serial port on GPIO 1/3 to output debug information. I don’t want to lose out on this debugging information, so don’t want to use these PINs to connect to other devices.

  • The ESP8266’s hardware serial support can be remapped to pins 13 and 15. Sadly I don’t have pin 15 free in otb-iot - it’s used for controlling the status LED (a WS2812B) - so I can’t just temporarily remap the hardware UART to these pins.

  • I’ve tried a software serial library for the ESP8266 non-OS SDK and integrated this with the otb-iot software already, but sadly I’m finding it unreliable when communicating with a device at 2,400 baud. I think this is because occasionally, because 2,400 baud takes so long to send data, the wifi is kicking in and delaying the RX interrupts, meaning I’m losing bytes.

What?

My search for an external IC to solve this problem led me to NXP’s SC16IS752, which provides a UART with I2C and SPI interface. There’s a few variants of this device:

  • SC16IS740 - single UART, no GPIOs

  • SC16IS750 - single UART, GPIOs

  • SC16IS760 - single UART, GPIOs, faster SPI bus support

  • SC16IS752 - dual UART, GPIOs

  • SC16IS760 - dual UART, GPIOs, faster SPI bus support

I mostly chose the SC16IS752 as it’s what RS had in stock, for about £2.50 each - I don’t need dual UART for my application, but the GPIOs are handy to provide status LEDs on a module based on the IC, without using up more ESP GPIOs. The GPIOs don’t have any fancy function like PWM, and may not be spare in some more advanced UART use cases (but they are in mine).

I built a sample application to get to know the SC16IS752 IC. This program:

  • Uses the I2C interface

  • Registers an interrupt handler to listen for interrupts from the device

  • Soft resets the device

  • Initialises the device at adress 0x48 (A0 and A1 pulled to VDD)

  • Blinks GPIOs 0 and 1

  • Sends “Hello World” at 2400,8,N,1

  • Waits a while for received data - and if received outputs it to console

  • Performs a hard reset of the device, by pulling the RESET pin low

  • Outputs some stats

  • Starts again

These are essentially the operations I intend to make use of in my finished device.

Hopefully the code will be useful to others getting to know the SC16IS devices.

How?

Key wiring details to set this up yourself using an ESP based device (all pin numbers assume the SC16IS752 TSSOP-28):

  • 1 RTSA - NC

  • 2 CTSA - NC

  • 3 TxA - Connect to Rx on receiving device - such as a USB-TTY on a windows PC, running putty connected to the appropriate COM port, with serial settings as above

  • 4 RxA - Connect to Tx on receiving device - such as a USB-TTY on a windows PC, running putty connected to the appropriate COM port, with serial settings as above

  • 5 Reset - Connect to ESP GPIO13, with 10K pull-up to 3.3V

  • 6 Xtal1 - Connect to pin 1 of 1.8432MHz oscillator, with 10-22pF capacitor to Gnd

  • 7 Xtal2 - Connect to pin 2 of 1.8432MHz oscillator, with 10-22pF capacitor to Gnd

  • 8 Vdd - 3.3V

  • 9 I2C - 3.3V

  • 10 A0 - 3.3V

  • 11 A1 - 3.3V

  • 12 NC

  • 13 SCL - Connect to ESP GPIO5, with 10K pull-up to 3.3V

  • 14 SDA - Connect to ESP GPIO4, with 10K pull-up to 3.3V

  • 15 IRQ - Connec to ESP GPIO12, with 1K pull-up to 3.3V (per datasheet)

  • 16 CTSB - NC

  • 17 RTSB - NC

  • 18 GPIO0 - Connect to -ve leg of LED, with +ve connected to current limiting resistor (GPIOs are capable of 4mA per datasheet) then to 3.3V

  • 19 GPIO1 - Connect to +ve leg of LED, with -ve connected to current limiting resistor (GPIOs are capable of 4mA per datasheet) then to 3.3V

  • 20 GPIO2 - NC

  • 21 GPIO3 - NC

  • 22 Vss - Gnd

  • 23 TxB - NC

  • 24 RxB - NC

  • 25 GPIO4 - NC

  • 26 GPIO5 - NC

  • 27 GPIO6 - NC

  • 28 GPIO7 - NC

There wasn’t anything too tricky once I’ve gone through the datasheet a few times - although table 33 - which indicates that the registers aren’t actually as indicated in the rest of the document - is quite important to find. (Essentially the device has duplicate sets of registers for UARTs A and B), and hence the registers listed elsewhere in the document are modified so duplicate sets can be addressed.)

Output

Here’s sample output from the program:

Step 0 - init I2C bus
  I2C stack init ... success

Step 1 - soft reset device
  Reset SC16IS752 ...
  IOControl reg: 0x0e actual reg: 0x70 val: 0x08
  Read LSR register
  First read may fail:
    read failure: 2
  Second should succeed:
    success

Step 2 - initialize device
SC16IS752 init ...
  IER reg: 0x01 actual reg: 0x08 val: 0x01
  FCR reg: 0x02 actual reg: 0x10 val: 0x01
  LCR reg: 0x03 actual reg: 0x18 val: 0x03
  MCR reg: 0x04 actual reg: 0x20 val: 0x00
  IODir reg: 0x0a actual reg: 0x50 val: 0x03
  IOIntEna reg: 0x0c actual reg: 0x60 val: 0x00
  IOControl reg: 0x0e actual reg: 0x70 val: 0x00
  EFCR reg: 0x0f actual reg: 0x78 val: 0x00
  LCR reg: 0x03 actual reg: 0x18 val: 0x83
  DLL reg: 0x00 actual reg: 0x00 val: 0x30
  DLH reg: 0x01 actual reg: 0x08 val: 0x00
  LCR reg: 0x03 actual reg: 0x18 val: 0x03

Step 3 - turn GPIOs 0,1 on
  IOState reg: 0x0b actual reg: 0x58 val: 0xff

Step 4 - turn GPIOs 0,1 off
  IOState reg: 0x0b actual reg: 0x58 val: 0xfc

Step 5 - send "Hello World #1"
  Hello World #1

Step 6 - NOP

Step 7 - NOP

Step 8 - NOP

!!! Received data: h



!!! Received data: e



!!! Received data: l



!!! Received data: l



!!! Received data: o



Step 9 - NOP

!!! Received data:



!!! Received data: b



!!! Received data: a



!!! Received data: c



Step 10 - NOP

!!! Received data: k



!!! Received data:



Step 11 - NOP

Step 12 - NOP

Step 13 - NOP

Step 14 - hard reset device
  Resetting device ... done
  Checking device reset ... success

Step 15 - Output stats
  Cycles:          1
  IRQ cleared:     0
  Bytes received:  11

M-Bus Postscript

Just in case anyone coming here wants to connect to a meter over M-Bus, you can’t connect serial directly into an M-Bus device - it needs stepping up to 34V. See about halfway down this page for more info. otb-iot includes some apps to process received M-Bus data into human readable form.

comments powered by Disqus