Max7219 and Common Anode Displays

How to drive common anode displays with the Max7219 and an Arduino

Finding myself with a bunch of common anode 7 segment displays and some left over max7219s, I was soon scratching my head wondering why I couldn’t get anything working. I eventually realised that the max7219 is designed for common cathode displays only, it doesn’t work at all with common anode displays.

Or does it? With a little effort and some mind-bending thinking The max7219 can be persuaded to control these common anode displays too.

Reverse the wiring

Simple right? Just flip anode and cathode connections on the IC. All segment pins on the max7219 now connect to the common anode pins on the display and all digit pins on the max7219 connect to the segment cathode pins on the display.

A little something like :

reverse

Turn off BCD mode

Goes without saying as each segment will need to be addressed individually. BCD mode will be turned off. Set the max7219 decode mode register 0x09 to 0.

Turn addressing on its head

Normally (with bcd mode off) to turn on, say, segment C on digit 1 you would just send 0b00000100 to digit 1.

A simple spi transfer command might be :

 MAX7219Send(1,0b00000100);  // sends bit 3 / seg C, to digit 1

or, to digit 2 :

MAX7219Send(2,0b00001000);  // sends bit 4 / seg D, to digit 2

Clearly this isn't going to work with the new wiring. As the segments are now connected to the digit pins on the max7219. I need to send the 8 bit segment data across all digit pins, so :

Bit 3 / segment C to digit 1 :

 
MAX7219Send(1,0b0000000); // seg A
MAX7219Send(2,0b0000000); // seg B
MAX7219Send(3,0b0000001); // seg C 
MAX7219Send(4,0b0000000); // seg D
MAX7219Send(5,0b0000000); // seg E
MAX7219Send(6,0b0000000); // seg F
MAX7219Send(7,0b0000000); // seg G
MAX7219Send(8,0b0000000); // seg dp

All segments on, digit 2 :


MAX7219Send(1,0b0000010); // seg A
MAX7219Send(2,0b0000010); // seg B
MAX7219Send(3,0b0000010); // seg C 
MAX7219Send(4,0b0000010); // seg D
MAX7219Send(5,0b0000010); // seg E
MAX7219Send(6,0b0000010); // seg F
MAX7219Send(7,0b0000010); // seg G
MAX7219Send(8,0b0000010); // seg dp

I've written some basic code for the Arduino (but the same principle will work with the Raspberry Pi) to send numbers to each digit position on my 4 digit module.


// Controlling a common anode 4 digit 7seg display with the Max7219
// David Barton, 2016

#include <SPI.h>

// The Max7219 Registers :

#define DECODE_MODE   0x09                       
#define INTENSITY     0x0a                        
#define SCAN_LIMIT    0x0b                        
#define SHUTDOWN      0x0c                        
#define DISPLAY_TEST  0x0f       

byte chip_select=10;  // spi chip select pin

byte display_num[4];  // array to hold our 4 digits

// standard 7 seg display numbers
byte number_seg[]=
{
  0b00111111,  // 0 
  0b00000110,  // 1
  0b01011011,  // 2
  0b01001111,  // 3
  0b01100110,  // 4
  0b01101101,  // 5  
  0b01111101,  // 6
  0b00000111,  // 7
  0b01111111,  // 8
  0b01100111   // 9
};


void MAX7219Send(uint8_t address, uint8_t value) 
{
  // Ensure LOAD/CS is LOW
  digitalWrite(chip_select, LOW);

  // Send the register address
  SPI.transfer(address);

  // Send the value
  SPI.transfer(value);

  // Tell chip to load in data
  digitalWrite(chip_select, HIGH);
}
  
 
void setup() 
{
  pinMode(chip_select,OUTPUT); // chip select
  
  SPI.begin();

  // set up max7219

  // Disabled BCD mode
  MAX7219Send(DECODE_MODE, 0x00);
  
  // brightness
  MAX7219Send(INTENSITY, 0x14);
  
  // Scan
  MAX7219Send(SCAN_LIMIT, 0x07);
  
  // Turn on chip
  MAX7219Send(SHUTDOWN, 0x01);

 // fill with 4 numbers
 display_num[0]=1;
 display_num[1]=2;
 display_num[2]=3;
 display_num[3]=4;

 for (byte each_segment=1;each_segment<=8;each_segment++)
 {
     // build the byte to send 
     byte output=0b00000000;

    // 4 digits 
    for (byte digits = 0; digits < 4; digits++)
    {
      
    byte number_to_display = display_num[digits];  
  
   // for out chosen number to display get it's segment bit at the position current position of 'each_segment'
    bool seg= number_seg[number_to_display] & (0b00000001 << (each_segment-1) );
 
    //set this bit in our output byte   
     output = output | (seg << digits);
      
    }

     MAX7219Send( each_segment, output);
  }
   
}

void loop() {
  
}

It's possible to address up to 8 digits with one max7219. Here's my final setup controlling 8 common anode digits :

Common Anode and the Max7219

Leave a Reply

Your email address will not be published. Required fields are marked *