SAA1064 I2C 7-Segment LED Driver

LED displays with 7-segments and decimal point are still widely used. They are relatively cheap, even for larger displays, and look good since they have nice bright colors. The seven segment display can represent numbers 0-9 and some characters like A-F. The seven segments and decimal point are usually identified by the characters a-g and dp. Each segment consists of one or more LEDs. Each segment has a separate external pin and they all share a common anode (or common cathode) pin. In most cases the display also features an additional LED for the decimal point (dp) or two LEDs for a semicolon.

Displays with more than one digit in a single package are also available. The corresponding segments of all digits are all connected and brought out on a single pin. The common cathodes (or anodes) are available separately for each digit. This approach reduces the number of pins. A processor will activate each digit sequentially at a high update rate (> 75 Hz) and the result is that all digits seem to be on continuously. This solution is known as multiplexing and it serves to reduce to number of required processor pins for driving the display and also reduces the required electrical power.

Driving these displays still requires rather significant number of processor pins. Given the relatively low update rate other solutions are possible. Driver chips are available that perform all multiplexing independently from the CPU. The driver has internal memory for storing the segment data and often supports additional features like brightness control.

An example of such an LED driver is the NXP SAA1064. The device support 4 digits of 8 LEDs (seven segments and dp). The interface of the SAA1064 is I2C. Upto 4 devices can be connected to the same bus since it supports 4 different I2C slaveaddresses. Each segment can be individually controlled so obviously the display driver can also be used to control 4x8 LEDs and any particular geometry. Note that some other types of display drivers have internal decoders for BCD to 7-segment and do not allow easy control of individual LEDs.

Hardware Schematic

The SAA1064 is available in SMD and 24pin DIP

/media/uploads/wim/saa1064-dip.jpg

Typical circuitry is shown here:

/media/uploads/wim/saa1064_7_segment.jpg

The two NPN transistors are used to multiplex between the 2 pairs of 7-segment displays. You could use BC547 or similar. The powersupply decoupling capacitors should be 47uF (16V) in parallel to 100 nF.

The SAA1064 supports 4 different I2C slaveaddresses. Meaning you can have upto 4 devices on the same I2C bus. The device address is selected at power up by the voltage on the ADR pin. A simple resistor network with some jumpers may be used to easily select the slave address. See below.

/media/uploads/wim/saa1064_addr.jpg

SlaveaddressADR voltageJumper
0x70GNDJP2
0x723/8 Vccnone
0x745/8 VccJP3
0x76VccJP1

The appropriate slaveaddress also needs to be set in the declaration of the SAA1064 object to identify your device. Default address is 0x70.

5 V Device!

The SAA1064 display driver is a 5V device. It will NOT work on a 3V3 powersupply and does NOT communicate reliably with the mbed 3V3 I2C bus. I have used a Sparkfun 3V3-5V level converter between mbed's I2C signals (SDA, SCL) and the displaydriver.

The display prototype for testing of the mbed lib was used before in an older project (note the datestamp on the SAA1064, it was made in 1989!). The wiring diagram is pretty much the same as printed in the datasheet and also shown in the figure above. Note that the software assumes that Digit1 is on the lefthand side (most significant digit or minus sign) and Digit4 is on the righthandside (least significant digit, representing units).

/media/uploads/wim/img_2885.jpg

The hardware and software was tested with an mbed LPC1768 and with an LPC812.

Software Library

Control of the device is rather straightforward. There is one internal register (Address 0) to control the device mode and the display intensity. In addtion there are 4 separate registers (Address 1, 2, 3, 4) for the digit data: each digit has its own 8 bit register, one bit for each segment. The I2C message consists of the slaveaddress, the selected register address, followed by the data for that register. The register address will be incremented automatically after each data write. Subsequent databytes will go to the next register without having to send the next register address again. The LED brightness can selected between 0 (off) and 7 (max 21 mA/segment) in increments of 3 mA. The segments are current controlled which means you dont need limiting series resistors and the intensity will not depend on the number of activated LEDs.

The SAA1064 Class instantiation requires a pointer to an I2C object and a device slaveaddress. Methods are provided for setting all digits to a user specific LED pattern, setting the intensity and writing integer values to the display. The writeInt() method supports the range -999 to 9999. The method has parameters to select leading zero suppression and to set the decimal point of a specific digit.

The API documentation

Import library

Public Member Functions

SAA1064 (I2C *i2c, uint8_t deviceAddress=SAA1064_SA0)
Create a SAA1064 LED displaydriver object using a specified I2C bus and slaveaddress.
void setIntensity (uint8_t intensity)
Set segment brightness.
void write (uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4)
Write digits.
void writeInt (int value, uint8_t dp_digit=0, bool leading=true)
Write Integer.
void snake (uint8_t count)
snake: show a short animation
void splash (uint8_t count)
splash: show a short animation

Protected Member Functions

void _init ()
Initialise LED driver.

The code can be found here:

Import librarySAA1064

7 Segment LED Displaydriver, I2C interface, SAA1064

Example

/** Driver for SAA1064 I2C 4-Digit 7-Segment LED Driver
 *
 */
#include "mbed.h"
#include "SAA1064.h"
 
// I2C Communication
I2C i2c_lcd(p28,p27); // SDA, SCL for LPC1768
//I2C i2c_lcd(P0_10,P0_11); // SDA, SCL for LPC812

SAA1064 LED(&i2c_lcd); // I2C bus, Default SAA1064 Slaveaddress
 
int main() {
   uint8_t count = 0; 

   // Display 0, 1, 2, 3
   LED.write(SAA1064_SEGM[0], SAA1064_SEGM[1], SAA1064_SEGM[2], SAA1064_SEGM[3]);
   wait(1);    
   
   while(1) {
     wait(0.3);    
     count++;       
   
     LED.writeInt(-150 + count, 3, false);  // Display value, dont suppress leading zero's
   }
  
}

Have fun!


Please log in to post comments.