Seven Segment Displays using MAX7219 and SPI

I am trying to control seven segment displays with MAX 7219 and SPI on MEGA 2560. My goal is to make a count down or count up clock. This should be easy but it isn't working. The compiles and loads to the board with no errors. I have tried other sketch examples and confirmed the board I have is working.

#define DIN 51
#define CSpin 53
#define CLK 52

unsigned long counterValue = 0;
byte digits[8];

void displayCounter();

void setup() {
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST);

digitalWrite(CSpin, HIGH);
pinMode(CSpin, OUTPUT);
SPI.begin();

digitalWrite(CSpin, LOW);//come out of shutdown
SPI.transfer(0x0C);
SPI.transfer(0x01);
digitalWrite(CSpin, HIGH);

digitalWrite(CSpin, LOW);//decode 8 digits
SPI.transfer(0x09);
SPI.transfer(0xFF);
digitalWrite(CSpin, HIGH);

for (int i = 1; i < 9; i++) {//set all digits OFF
digitalWrite(CSpin, LOW);//digit 0
SPI.transfer(i);
SPI.transfer(0x0F);
digitalWrite(CSpin, HIGH);
}

digitalWrite(CSpin, LOW);//intensity MIN
SPI.transfer(0x0A);
SPI.transfer(0x00);
digitalWrite(CSpin, HIGH);

digitalWrite(CSpin, LOW);//scan limit - all 8
SPI.transfer(0x0B);
SPI.transfer(0x07);
digitalWrite(CSpin, HIGH);

}

void loop() {
displayCounter();
counterValue++;

// for (byte num = 0; num < 10; num++) {
// for (byte i = 1; i < 9; i++) {
// digitalWrite(CSpin, LOW);//digit 0
// SPI.transfer(i);
// SPI.transfer(num);
// digitalWrite(CSpin, HIGH);
// delay(1);
// }
// delay(500);
// }

}

void displayCounter() {
unsigned long digitsCounter = counterValue;

for (int i = 0; i < 8; i++) {
digits[i] = digitsCounter % 10;

if(counterValue< pow(10,i))// 1, 10, 100, 1000....
digits[i] = 0x0F;

digitsCounter /= 10;
PORTD &= ~(1<<CSpin);
SPI.transfer(i + 1);
SPI.transfer(digits[i]);
PORTD |= (1<<CSpin);

}

}

MAX7219 is not a SPI device.
You need to use one of the available libraries.

The datasheet seems to say it is.

In any case, @danhixon might help move things along by…

... properly posting the code she is working with.

Use the IDE Autoformat tool, then use the IDE Copy for Forum tool and come back and paste it in a new post.

Also, paste the sketch you used that makes you think everything is wired up and ready to run the code you really want.

a7

1 Like

No.
The MAX7219/7221 datasheet say

The MAX7221 is compatible
with SPI™, QSPI™, and MICROWIRE™

And

The MAX7219 and MAX7221 are identical except for two parameters:
the MAX7221 segment drivers are slew-rate... and its serial interface is fully SPI compatible

Sorry, I guess coming across things like Nick Gammon's

Arduino library for MAX7219 display using SPI.

led me astray. I figured if you can write a library to use SPI to control the MAX7219 that the chip itself must be controllable by SPI.

a7

Off the top of my head, you're not entirely wrong. It's one of those "yes, but..." things. You can control the 7219 with SPI; it does work. Here's the difference:

For the MAX7219, serial data at DIN, sent in 16-bit packets, is shifted into the internal 16-bit shift register with each rising edge of CLK regardless of the state of LOAD. For the MAX7221, CS must be low to clock data in or out.

So if there was a second device on the SPI bus, the 7219 would be clocking in its data as well. An SPI peripheral probably shouldn't do that. Would it be a big deal? From the 7219's point of view, probably not. As long as it gets its 16 bits before a rising edge on its LOAD pin, it should be okay. But if there was an errant low pulse on LOAD before it got its 16 bits, strange things could happen. That wouldn't bother the 7221.

I'll be sure to learn more if I use the MAX7219, but aren't we in trouble generally if there are errant pulses flitting about with any protocol, like I2C or serial comms?

The code I see looks like it treats LOAD as if it were /CS. And proceeds to use SPI with LOAD taken low before the transfer and returned to high after.

a7

Yeah, I was reaching; an errant low pulse on LOAD was the only thing I could think off the top of my head of that would differentiate how the two of them would react.

I treat LOAD as /CS when I'm using the 19 as well. I've never had the need to have it share the SPI bus when using one; maybe one day I will and I'll smack my forehead and go "of, of course, THAT's the issue!"

works

No SPI! but this might help

// pin 8 is connected to the MAX7221        pin 1
// pin 7 is connected to the CLK           pin 13
// pin 6 is connected to LOAD              pin 12

#include "LedControl.h" 
LedControl lc=LedControl(8,7,6,1); // lc is our object

float input;
int num; 
int digit0, digit1, digit2, digit3;

void setup()
{
  Serial.begin (9600);
  // the zero refers to the MAX7219 number, it is zero for 1 chip
  lc.shutdown(0,false);// turn off power saving, enables display
  lc.setIntensity(0,8);// sets brightness (0~15 possible values)
  lc.clearDisplay(0);// clear screen 
input = 34.56;
num = input*100;    // i.e. 3456
}

void loop()
{
  cfgdigits();

  lc.setDigit(0,0,digit0,false);  
  lc.setDigit(0,1,digit1,false);
  lc.setDigit(0,2,digit2,true);// true gives DP!
  
if (num > 999)
  {
  lc.setDigit(0,3,digit3,false);  
  }
else
  {
    lc.setChar(0,3,' ',false);
  }
  
  delay(500);
  num --;//count down!!
}
  
void cfgdigits () { 
if (num > 999)
  {
    float result = num / 1000;  // = 3.456
    digit3 = result; //digit3 is int, so it's just thous  =3
    int remain = num%1000; // result is int so this gets the remainder = 456
    digit2=remain/100; //digit2 is int, so its just the huns = 4
    remain = num%100; // result is float so this gets the remainder =56.00
    digit1=remain/10; //digitTwo is int, so its just the tens = 5
    digit0 = remain % 10;  //this gets the remainder of 56.00/10 =6
  }
else if (num > 99)
  {
    float result = num / 100;  // = 4.56
    digit3 = 0;   // NO diigit3 - leading zero is blank
    digit2 = result; //digitThree is int, so it's just huns  =4
    int remain = num%100; // result is float fo this gets the remainder =56.00
    digit1=remain/10; //digitTwo is int, so its just the tens = 5
    digit0 = remain % 10;  //this gets the remainder of 56.00/10 =6
  }
else if (num>9)
  {
    float result = num / 10;  
    digit3 = 0;   // 
    digit2 = 0; 
    digit1 = result;
    digit0 = num % 10;  
  }
else
  {
    digit3 = 0;
    digit2 = 0;// 
    digit1 = 0;
    digit0 = num;  
  }
}

@danhixon
Before you go any further you need to read the following:

Also provide a schematic/wiring diagram

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.