Interface mBed with LED Matrix using Max 7221

06 Oct 2009

Has anyone attempted to hook up the mbed to an LED matrix with the max7221 7segment led driver chip? I have been trying but I cannot seem to get the code running. The max chip works by taking registers or "bytes" of information.

Only three digital pins need to be used to run 64 LEDs (data, clock and load)

06 Oct 2009

Can you post your code (and schematics)?

06 Oct 2009 . Edited: 06 Oct 2009

I have been basing everything I have done off of examples done with the arduino.

 

The code I have been using is fragments off of this website: http://www.arduino.cc/playground/LEDMatrix/Max7219

I am trying to find the equivelent of a byte for the mbed. No additional librarys should be needed.

Thanks for all your help!

06 Oct 2009

byte is probably just a byte (8-bit) variable, C equivalent is unsigned char. However, using int (32-bit) is usually faster on a 32-bit MCU like the ARM used in mbed.

Here's a quick "conversion" of the code from arduino.cc to mbed API. I don't have the chip so can't check but I think it should work.

#include "mbed.h"

DigitalOut dataIn(p5);
DigitalOut load(p6);
DigitalOut clock(p7);

int maxInUse = 4;    //change this variable to set how many MAX7219's you'll use

int e = 0;           // just a varialble

// define max7219 registers
int  max7219_reg_noop        = 0x00;
int  max7219_reg_digit0      = 0x01;
int  max7219_reg_digit1      = 0x02;
int  max7219_reg_digit2      = 0x03;
int  max7219_reg_digit3      = 0x04;
int  max7219_reg_digit4      = 0x05;
int  max7219_reg_digit5      = 0x06;
int  max7219_reg_digit6      = 0x07;
int  max7219_reg_digit7      = 0x08;
int  max7219_reg_decodeMode  = 0x09;
int  max7219_reg_intensity   = 0x0a;
int  max7219_reg_scanLimit   = 0x0b;
int  max7219_reg_shutdown    = 0x0c;
int  max7219_reg_displayTest = 0x0f;

#define LOW 0
#define HIGH 1

void putByte(char data) {
    int i = 8;
    unsigned char mask;
    while (i > 0) {
        mask = 0x01 << (i - 1);      // get bitmask
        clock = LOW;                 // tick
        if (data & mask) {           // choose bit
            dataIn = HIGH;           // send 1
        } else {
            dataIn = LOW;            // send 0
        }
        clock = HIGH;                // tock
        --i;                         // move to lesser bit
    }
}

void maxSingle( int reg, int col) {
//maxSingle is the "easy"  function to use for a     //single max7219

    load = LOW;                    // begin
    putByte(reg);                  // specify register
    putByte(col);//((data & 0x01) * 256) + data >> 1); // put data
    load = LOW;                    // and load da shit
    load = HIGH;
}

void maxAll (int reg, int col) {    // initialize  all  MAX7219's in the system
    int c = 0;
    load = LOW;                    // begin
    for ( c =1; c<= maxInUse; c++) {
        putByte(reg);  // specify register
        putByte(col);//((data & 0x01) * 256) + data >> 1); // put data
    }
    load = LOW;
    load = HIGH;
}

void maxOne(int maxNr, int reg, int col) {
//maxOne is for adressing different MAX7219's,
//whilele having a couple of them cascaded

    int c = 0;
    load = LOW;

    for ( c = maxInUse; c > maxNr; c--) {
        putByte(0);    // means no operation
        putByte(0);    // means no operation
    }

    putByte(reg);  // specify register
    putByte(col);//((data & 0x01) * 256) + data >> 1); // put data

    for ( c =maxNr-1; c >= 1; c--) {
        putByte(0);    // means no operation
        putByte(0);    // means no operation
    }

    load = LOW;
    load = HIGH;
}


void setup () {
//initiation of the max 7219
    maxAll(max7219_reg_scanLimit, 0x07);
    maxAll(max7219_reg_decodeMode, 0x00);  // using an led matrix (not digits)
    maxAll(max7219_reg_shutdown, 0x01);    // not in shutdown mode
    maxAll(max7219_reg_displayTest, 0x00); // no display test
    for (e=1; e<=8; e++) {    // empty registers, turn all LEDs off
        maxAll(e,0);
    }
    maxAll(max7219_reg_intensity, 0x0f & 0x0f);    // the first 0x0f is the value you can set
    // range: 0x00 to 0x0f
}

void loop () {


    //if you use just one MAX7219 it should look like this
    /*
     maxSingle(1,1);                       //  + - - - - - - -
     maxSingle(2,2);                       //  - + - - - - - -
     maxSingle(3,4);                       //  - - + - - - - -
     maxSingle(4,8);                       //  - - - + - - - -
     maxSingle(5,16);                      //  - - - - + - - -
     maxSingle(6,32);                      //  - - - - - + - -
     maxSingle(7,64);                      //  - - - - - - + -
     maxSingle(8,128);                     //  - - - - - - - +

    */
    //if you use more than one MAX7219, it should look like this

    /*
    maxAll(1,1);                       //  + - - - - - - -
    maxAll(2,3);                       //  + + - - - - - -
    maxAll(3,7);                       //  + + + - - - - -
    maxAll(4,15);                      //  + + + + - - - -
    maxAll(5,31);                      //  + + + + + - - -
    maxAll(6,63);                      //  + + + + + + - -
    maxAll(7,127);                     //  + + + + + + + -
    maxAll(8,255);                     //  + + + + + + + +
    */

    //

    //if you use more then one max7219 the second one should look like this


    maxOne(2,1,1);                       //  + - - - - - - -
    maxOne(2,2,2);                       //  - + - - - - - -
    maxOne(2,3,4);                       //  - - + - - - - -
    maxOne(2,4,8);                       //  - - - + - - - -
    maxOne(2,5,16);                      //  - - - - + - - -
    maxOne(2,6,32);                      //  - - - - - + - -
    maxOne(2,7,64);                      //  - - - - - - + -
    maxOne(2,8,128);                     //  - - - - - - - +


    //
    wait_ms(2000);

}

int main() {
  loop ();
}
06 Oct 2009

You are a hero, as soon as I get home I will wire this up and give it a go and let you know. I will also document it and add it to the cookbook, with your credit of course.

06 Oct 2009

Since datasheet claims that chip supports SPI, theoretically we should be able to use mbed's SPI controller instead of bit-banging. Here's a simplified version making use of that. I'm not sure if p6 can be used as digital out when we use p5-p7 for SPI, so I've changed load pin to p8. Again, I have no idea if it will actually work...

#include "mbed.h"

// p5: DIN, p7: CLK, p8: LOAD/CS
SPI max72_spi(p5, NC, p7);
DigitalOut load(p8);

int maxInUse = 1;    //change this variable to set how many MAX7219's you'll use

// define max7219 registers
#define max7219_reg_noop         0x00
#define max7219_reg_digit0       0x01
#define max7219_reg_digit1       0x02
#define max7219_reg_digit2       0x03
#define max7219_reg_digit3       0x04
#define max7219_reg_digit4       0x05
#define max7219_reg_digit5       0x06
#define max7219_reg_digit6       0x07
#define max7219_reg_digit7       0x08
#define max7219_reg_decodeMode   0x09
#define max7219_reg_intensity    0x0a
#define max7219_reg_scanLimit    0x0b
#define max7219_reg_shutdown     0x0c
#define max7219_reg_displayTest  0x0f

#define LOW 0
#define HIGH 1
#define MHZ 1000000

void maxSingle( int reg, int col) {
//maxSingle is the "easy"  function to use for a
//single max7219
    load = LOW;            // begin
    max72_spi.write(reg);  // specify register
    max72_spi.write(col);  // put data
    load = HIGH;           // make sure data is loaded (on rising edge of LOAD/CS)
}

void maxAll (int reg, int col) {    // initialize  all  MAX7219's in the system
    load = LOW;                    // begin
    for ( int c=1; c<= maxInUse; c++) {
        max72_spi.write(reg);  // specify register
        max72_spi.write(col);  // put data
    }
    load = HIGH;
}

void maxOne(int maxNr, int reg, int col) {
//maxOne is for adressing different MAX7219's,
//while having a couple of them cascaded
    int c = 0;
    load = LOW;

    for ( c = maxInUse; c > maxNr; c--) {
        max72_spi.write(0);  // no-op
        max72_spi.write(0);  // no-op
    }

    max72_spi.write(reg);  // specify register
    max72_spi.write(col);  // put data

    for ( c=maxNr-1; c >= 1; c--) {
        max72_spi.write(0);  // no-op
        max72_spi.write(0);  // no-op
    }
    load = HIGH;
}


void setup () {
    // initiation of the max 7219
    // SPI setup: 8 bits, mode 0
    max72_spi.format(8, 0);
    
    // going by the datasheet, min clk is 100ns so theoretically 10MHz should work...
    // max72_spi.frequency(10*MHZ);
    
    maxAll(max7219_reg_scanLimit, 0x07);
    maxAll(max7219_reg_decodeMode, 0x00);  // using an led matrix (not digits)
    maxAll(max7219_reg_shutdown, 0x01);    // not in shutdown mode
    maxAll(max7219_reg_displayTest, 0x00); // no display test
    for (int e=1; e<=8; e++) {    // empty registers, turn all LEDs off
        maxAll(e,0);
    }
    maxAll(max7219_reg_intensity, 0x0f & 0x0f);    // the first 0x0f is the value you can set
    // range: 0x00 to 0x0f
}

void loop () {


    //if you use just one MAX7219 it should look like this
     maxSingle(1,1);                       //  + - - - - - - -
     maxSingle(2,2);                       //  - + - - - - - -
     maxSingle(3,4);                       //  - - + - - - - -
     maxSingle(4,8);                       //  - - - + - - - -
     maxSingle(5,16);                      //  - - - - + - - -
     maxSingle(6,32);                      //  - - - - - + - -
     maxSingle(7,64);                      //  - - - - - - + -
     maxSingle(8,128);                     //  - - - - - - - +

    //if you use more than one MAX7219, it should look like this

    /*
    maxAll(1,1);                       //  + - - - - - - -
    maxAll(2,3);                       //  + + - - - - - -
    maxAll(3,7);                       //  + + + - - - - -
    maxAll(4,15);                      //  + + + + - - - -
    maxAll(5,31);                      //  + + + + + - - -
    maxAll(6,63);                      //  + + + + + + - -
    maxAll(7,127);                     //  + + + + + + + -
    maxAll(8,255);                     //  + + + + + + + +
    */

    //

    //if you use more then one max7219 the second one should look like this


    /*
    maxOne(2,1,1);                       //  + - - - - - - -
    maxOne(2,2,2);                       //  - + - - - - - -
    maxOne(2,3,4);                       //  - - + - - - - -
    maxOne(2,4,8);                       //  - - - + - - - -
    maxOne(2,5,16);                      //  - - - - + - - -
    maxOne(2,6,32);                      //  - - - - - + - -
    maxOne(2,7,64);                      //  - - - - - - + -
    maxOne(2,8,128);                     //  - - - - - - - +

    */
    
    //
    wait_ms(2000);

}

int main() {
    setup ();
    loop ();
}
06 Oct 2009

I've read the Maxim app note and apparently they use CPHA =1, so the format() call in above code will need to be changed to max72_spi.format(8, 1). Or maybe even format(16, 1), and double write() calls will need to be combined...

14 Jul 2012

I just wanted to let you know that changing max72_spi.format(8, 1)-> max72_spi.format(8, 0) makes the spi version of this code work!