Interrupt driven display driver for the Arduino nano

CircuitPicture

There are a number of 7 segment display available on the Internet. Some of them use 74595 shift registers to control them. These require the display to be refreshed continuously as the LED’s are multiplexed across a number of digital output pins. I bought one from dx.com (link) though I see they are now out of stock. With a bit of fiddling I came up with the following interrupt driven code to drive it.

The PWM system is used to generate a periodic interrupt on digital output 3. Arduino allows you to attach an interrupt to this pin which works even if the pin is a PWM output. This is done in the setup function. The interrupt handler is set to RefreshDisplay.

The RefreshDisplay function copies the contents of the global array DisplayMemory to the 74595 shift registers in the the display module. One digit is written for each interrupt. After 8 interrupts, all digits have been updated and the process starts over.

The main loop calls on the DisplayNumber function whose job is to take a apart the supplied number into each of its individual digits. The digits are converted to 7-segment LED codes which are stored in DisplayMemory.
The display is connected to the ICSP header of an Arduino nano as shown. The clock and data pins are driven by software.

int SCKPin = 13;
int DIOPin = 11;
int RCKPin = 12;
int DisplayMemory[8];
void setup()
{
  pinMode(RCKPin,OUTPUT);
  pinMode(DIOPin,OUTPUT);
  pinMode(SCKPin,OUTPUT);
// Establish periodic interrupt on digital pin 3 so that RefreshDisplay
// is called regularly
  analogWrite(3,100);
  attachInterrupt(1,RefreshDisplay,RISING);
}
long Count=0;
void loop()
{ 
  DisplayNumber(Count++);
}
const char LED_Codes[]={ 0b11000000,0b11111001,0b10100100,0b10110000,0b10011001,0b10010010,0b10000010,0b11111000,0b10000000,0b10010000 };

void DisplayNumber(long Number)
{
  int Digit;
  for (Digit=0;Digit<8;Digit++)
  {
    DisplayDigit(7-Digit,Number % 10);
    Number = Number / 10;
  }
}
void DisplayDigit(int DigitNumber,int Digit)
{
  DisplayMemory[DigitNumber]=LED_Codes[Digit];
}
void RefreshDisplay()
{
  static  int Digit=1;
  static int Index=0;
  SendByte(Digit);
  SendByte(DisplayMemory[Index]);
  digitalWrite(RCKPin,LOW);
  digitalWrite(RCKPin,HIGH);  
  Digit = Digit << 1;  
  Index++;
  if (Index > 7)
  {
    Index = 0;
    Digit = 1;
  }

}
void SendByte(int Byte)
{
  int Bit;
  for (Bit = 0; Bit < 8; Bit++)
  {
    if (Byte & 0x80)
      digitalWrite(DIOPin,HIGH);
    else
      digitalWrite(DIOPin,LOW);
    Byte = Byte << 1;
    digitalWrite(SCKPin,LOW);
    digitalWrite(SCKPin,HIGH);
  }
}