Sunday, July 12, 2015

Experimenting with MAX6955

MAX6955 is an interesting LED driver chip. It is the primordial charlieplexing device, being the materialization of a technique invented by Charlie Allen of Maxim Integrated. Without understanding how charelieplexing works, it is actually counter-intuitive to wire multiple (up to 8) 16-segment displays to such a driver chip. Fortunately, Maxim has great documentation on how to do it.

My experimenting actually started with MAX6954. After many failed tries due to SPI issues (Maxim uses a special interpretation of the protocol, I read), I switched to MAX6955.

MAX6955 is the I2C sibling of MAX6954 (which uses SPI). They both have identical LED driving abilities, only the microcontroller interface part of the chips differ. Once, both chips were available in DIP-40 package. Now, MAX6955 only comes in SSOP-36 (MAX6954 is still available in DIP-40). Luckily, the pin configurations for the two chips are compatible, which allows for easy swap. For this reason, I designed a breakout board (shared at oshpark), so I can use the same setup I built for MAX6954.

Beside Maxim's, there isn't much documentation on how to control these chips. One of the reasons they are rarely used by hobbyists is probably their price (about $20 at digikey), although in the same range as the wildly popular MAX72xx LED driver (available at around $10 from digikey). In "reality", for some reason, MAX72xx could be had for $1 or less on ebay, unlike MAX6954/6955. Therefore, a hobby kit designed around MAX6955 would be "extremely" expensive compared with others using different LED driving chips (e.g. MAX72xx).

MAX6954/6955 was designed to drive common cathode LED displays, like MAX72xx. But unlike MAX72xx, it cannot be used for displays with common segments (which require multiplexing), like the ones below (and used here). MAX6954/6955 requires the 14/16-segment displays to be single digit/character, because not all segments will be wired together.

Below is the Arduino sketch I wrote that works very well with MAX6955. Although it uses a minimal set of commands, it is capable of displaying a character at a given position, light up the dot, and even scroll a long message.

A nice feature of the chip is that the fonts are predefined, this making it an "intelligent" display driver, like Avago's HDSP-2534. To display a character, only its ASCII code needs to be supplied.

#include "Wire.h"

#define ID_MAX6955 B1100000 
#define NUM_DISPLAYS 6

#define max6955_reg_decodeMode      0x01
#define max6955_reg_globalIntensity 0x02
#define max6955_reg_scanLimit       0x03
#define max6955_reg_configuration   0x04
#define max6955_reg_displayTest     0x07
#define max6955_reg_digitType       0x0C

int writeMAX6955(char command, char data)

void initMAX6955()
    // ascii decoding for all digits;
    writeMAX6955(max6955_reg_decodeMode, 0xFF);
    // brightness: 0x00 =  1/16 (min on)  2.5 mA/seg;
    // 0x0F = 15/16 (max on) 37.5 mA/segment
    writeMAX6955(max6955_reg_globalIntensity, 0x07);
    // active displays: 0x07 -> all;
    writeMAX6955(max6955_reg_scanLimit, 0x07);
    // set normal operation;
    writeMAX6955(max6955_reg_configuration, 0x01);
    // segments/display: 0xFF=14-seg; 0=16 or 7-seg;
    writeMAX6955(max6955_reg_digitType, 0x00);
    // display test off;
    writeMAX6955(max6955_reg_displayTest, 0x00);

void setup()
  // set D8 and D9 to GND (for I2C address);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);

//  writeDisplay("HI");
//  writeChar(0, 'A', true);
//  scrollDisplay("     HELLO WORLD", 300);
  writeTime(15, 24, 39);

void loop()

void writeDisplay(char* msg)
  for (byte i=0; i < NUM_DISPLAYS; i++)
    if (i < strlen(msg))
      writeMAX6955(0x25-i, msg[i]);
      writeMAX6955(0x25-i, ' ');

void writeChar(byte pos, char letter, boolean dotLit)
  writeMAX6955(0x25-pos, (dotLit? 0x80 : 0) | letter);

void clear()
  for (byte i=0; i < NUM_DISPLAYS; i++)
    writeMAX6955(0x25-i, ' ');

void scrollDisplay(char* msg, int delayMs)
  for (int i=0; i<=strlen(msg); i++)

void writeTime(int hours, int minutes, int seconds)
  char h1 = (hours/10)? '0' + hours/10 : ' ';
  writeChar(0, h1, false);
  char h2 = '0' + (hours%10);
  writeChar(1, h2, true);
  char m1 = '0' + (minutes/10);
  writeChar(2, m1, false);
  char m2 = '0' + (minutes%10);
  writeChar(3, m2, true);
  char s1 = '0' + (seconds/10);
  writeChar(4, s1, false);
  char s2 = '0' + (seconds%10);
  writeChar(5, s2, false);

The I2C address of B1100000 was set by grounding AD0 and AD1 (see table 5 in the datasheet on how to change that address). In my setup, these 2 pins are connected to D8 and D9. Don't forget to pull-up SDA and SCL with 4k7-10k resistors.

The left-most digit is at position 0, accessible at address 0x25. "Digit 1" is the second from left, accessible at address 0x24, and so on. This is determined by the wiring. In my case, "CC0" (in the table 1 of this application note) represents the right-most display, and it is accessible at address 0x20.


  1. Interesting article but i find a little bit difficult to understand why did you say MAX6954 uses a 'special interpretation of the spi'?. Can you be more specific with the details? what problems did you encountered? I also would like to use that chip for my project but not with arduino (instead microchip 8-bit series) and if possible I would like to avoid unnecesary hastle and bustle with the code. By the way, i find it some strange the schematic for both chips share common cathode connection between digits 0,1 and 0a,1a. Are those tied together?. I hope not making a wrong interpretation from the documentation. Mind sharing your views?. :)

    1. Chris,
      Like many others (see this link, for example), I was not able to get the MAX6954 work with Arduino on SPI. I am not knowledgeable to do bit-banging for SPI, so I only used the "standard" Arduino SPI, which did not work. I'm sure that the chip works with other processors (otherwise Maxim wouldn't have had it released).

    2. I checked the link you provided, it was worth to read. But it doesn't mention much about hardware connections between the 7 segments to the MAX6955. Probably i'll end up asking maxim directly on my doubts. However your article does say that it is not suitable to use with shared displays (multiplexing), i find this very important. I also think the price can be an issue as well. Looking at Digikey catalog lists them as 21.79 bucks. But it wont disuade me from using them in my project. On SPI vs I2C, since i am a BASIC guy (no pun intended) i hope not to have any problems with the code for using it with a 16F628. Btw i bookmarked your blog in my favorites list. :)

    3. MAX6954 and MAX6955 use charlieplexing for driving the LEDs, that's why connections to LED displays are shared. Use the datasheet, it documents the wiring very clearly (ask me questions if you are in doubt). I would also try MAX6954 with PIC, SPI may work (and please report back on your findings, I am very interested).
      I also have some MAX6955 in TQFN package (pins on the bottom, impossible to solder by hand, requires oven); I could send you a couple if you wish.

  2. Very nice ... thanks for the head start ...

  3. Hi

    I was successful in using MAX6954 SPI using C. I was not successful with MAX6955 I2C. My MAX6955 address lines are grounded. I am using your code and it is not working. Please help me with this. You can email me at jayanthd2k12(at)gmail(dot)com

  4. I can provide you the code I have written for MAX6954 SPI. Email me at jayanthd2k12(at)gmail(dot)com

    I used PIC for the project and mikroC PRO PIC Compiler.

  5. Thank you Florin. Your code worked. I had to write 0x01 to max6955_reg_configuration. I have a working MAX6954 SPI C Code. If you are interested then email me at jayanthd2k12(at)gmail(dot)com and I will send you the project.