MAX6921 - need help

Hi!

I am trying to get MAX6921 to drive my display.

The segments is hooked up to OUT0-OUT6. Digits is connected to OUT7-OUT14.

From datasheet:
The MAX6921/MAX6931 are normally written using the following sequence:

  1. Take CLK low.
  2. Clock 20 bits of data in order D19 first to D0 last into DIN, observing the data setup and hold times.
  3. Load the 20 output latches with a falling edge on LOAD.
    LOAD can be high or low during a transmission. If LOAD is high, then the data shifted into the shift register at DIN appear at the OUT0 to OUT19 outputs.

I have tried to use shiftout and a self made “shiftout” funtion.

The output seems a bit random to me (digits lights up but not in the way I want :slight_smile: )

Here is one of my code examples:

     byte dummy=0; //Just to fill out the upper 4 bits 
     byte digit=1;     // Try to lit one digit

     digitalWrite(clockPin, LOW); 
     digitalWrite(loadPin, LOW); 
     shiftOut(dataPin, clockPin, MSBFIRST, dummy);
     shiftOut(dataPin, clockPin, MSBFIRST, digit);
     shiftOut(dataPin, clockPin, MSBFIRST, segFont[2]);   // segFont is a byte
  
     digitalWrite(loadPin, HIGH);

Example 2:

void send_word(long data) 
{ 
   digitalWrite(clockPin, LOW); 
   digitalWrite(loadPin, LOW); 

   for(byte i=0; i<20; i++) 
   { 
         if (data & (1 << i))
    {
      digitalWrite(dataPin, HIGH);
    }
    else
    {
      digitalWrite(dataPin, LOW);      
    }
      digitalWrite(clockPin, HIGH); 
      digitalWrite(clockPin, LOW); 
   } 
   digitalWrite(loadPin, HIGH);
}

I really would like to have some working Arduino code. I have looked at the code from Adafruits “Ice Tube Clock” but do not understand it.

/Olof

olof_n: 3) Load the 20 output latches with a falling edge on LOAD.

You seem to have this pin backwards...

Fungus, thanks for the reply.

I do not understand what "Load the 20 output latches with a falling edge on LOAD" means. I thought that was bringing load pin LOW before shifting in the 20 bits?

/Olof

olof_n: Fungus, thanks for the reply.

I do not understand what "Load the 20 output latches with a falling edge on LOAD" means. I thought that was bringing load pin LOW before shifting in the 20 bits?

No, it means the data is latched when load goes from high to low.

So: 1) Transfer your data to the chip 2) Make LOAD pin go HIGH then LOW to latch the data

A couple possibilities:

  1. I didn’t spend enough time to see how the device does with 20+ pulses - I think it takes the last twenty. You may want to investigate into that.
  2. pulse width: the device is fairly slow so you want to make sure that there is sufficient delay there.

I would rewrite your code as such:

void send_word(long data) 
{ 
   digitalWrite(clockPin, LOW); 
   digitalWrite(loadPin, LOW); 

   for(byte i=0; i<20; i++) 
   { 
      digitalWrite(clockPin, LOW); //data on rising edge

      if (data & (1 << i)) digitalWrite(dataPin, HIGH);
      else digitalWrite(dataPin, LOW);      

      digitalWrite(clockPin, HIGH); 
   }

You may want to take a scope on the clk pin to make sure that it is close to 50%.

Now it works, thanks for the help :slight_smile:

This is a great forum!

I changed segments to OUT19-OUT13 and digits to OUT14-OUT16.

void RefreshIV18() 
{ 
  long data=0;
  for (byte iDigit=1; iDigit<9;iDigit++)
  {
    data=0;
    data = (data << 8) + segFont[iDigit];  
    data ^= (1 << 6+iDigit); 
    digitalWrite(loadPin, LOW); 

    for(byte i=0; i<20; i++) 
    { 
      digitalWrite(clockPin, LOW); //data on rising edge
      if (data & (1 << i)) digitalWrite(dataPin, HIGH);
      else digitalWrite(dataPin, LOW);      
      digitalWrite(clockPin, HIGH); 
    }
    digitalWrite(loadPin, HIGH);
  }
}

/Olof

can you post your complete code i would also like to use it if i may

Hi!

No problem, the function is part of my “IV-18 Clock” project (http://forum.arduino.cc/index.php?topic=140456.0).
I used the digitalWriteFast library but you can change digitalWriteFast to digitalWrite (or access the ports direct).

I copied and pasted the important part of my code.

#include <digitalWriteFast.h>

#define  dataPin  7
#define  clockPin  4
#define  loadPin  8


//A F B G E C D H
//19-12 SEG
const byte segFont[] =
{
  B00111111, B00000110, B01011011, B01001111,	// 0123
  B01100110, B01101101, B01111100, B00000111,	// 4567
  B01111111, B01100111, B01000000               // 89-
};

unsigned long nowMicros=0;
unsigned long ulRefreshcounter;
byte bDigit=0;
byte bDot=0;
int iDots=0;
byte bChars[10];


void setup()
{
  pinModeFast(loadPin, OUTPUT);
  pinModeFast(clockPin, OUTPUT);
  pinModeFast(dataPin, OUTPUT);

  //timetoIV18(hours,minutes,seconds);
  timetoIV18(10,10,10);
  setDots(1);  

}

void loop()
{
  nowMicros=micros();


  if ((nowMicros-ulRefreshcounter)>1000)
  {
    RefreshIV18(); 
    ulRefreshcounter=nowMicros;
  }
}

void RefreshIV18() 
{ 
  // Need 20 bits variable  
  long data=0;
  //Refresh one digit for each call of RefreshIV18
  bDigit++;
  //Shift in 8 bits (segFont)
  //bChars is set with function timetoIV18
  data = (data << 8) + segFont[bChars[bDigit]]; 
  //Select position for digit. 
  data ^= ((long)1 << 7+bDigit); 
  //Set decimal dots
  //Stored in variable iDots
  if (iDots & (1 << (bDigit-1))) 
  {  
    data ^= (1 << 7);
  }
  //Set loadPin low
  digitalWriteFast(loadPin, LOW); 
  //Shiftin 20 bits
  for(byte i=0; i<20; i++) 
  { 
    //clockPin LOW
    //data on rising edge
    digitalWriteFast(clockPin, LOW);
    //datapin bit to 1 OR 0 
    digitalWriteFast(dataPin, (bool)(data & ((long)1 << i)) );
    //Set clockPin HIGH
    digitalWriteFast(clockPin, HIGH); 
  }
  //Done
  digitalWriteFast(loadPin, HIGH);
  //If digit = 9
  //Start from beginning with digit 1
  if (bDigit==9) 
  { 
    bDigit=0; 
  }
}

void timetoIV18(byte h,byte m,byte s)
{
  if (h>9)
  {
    bChars[7]=h % 10;	
    bChars[8]=h / 10;
  }
  else
  {
    bChars[8]=0;
    bChars[7]=h;
  }   

  bChars[6]=10;

  if (m>9)
  {
    bChars[4]=m % 10;	
    bChars[5]=m / 10;
  }
  else
  {
    bChars[5]=0;
    bChars[4]=m;
  }   

  bChars[3]=10;

  if (s>9)
  {
    bChars[1]=s % 10;	
    bChars[2]=s / 10;
  }
  else
  {
    bChars[2]=0;
    bChars[1]=s;
  }   
}

void setDots(byte bWhere)
{
  switch (bWhere) 
  {
  case 0:
    //Ta bort på timmar och minuter
    iDots &= ~((1 << (5-1)) | (1 << (4-1)));
    iDots &= ~( (1 << (8-1)) | (1 << (7-1)));
    break;
  case 1:
    //Hours
    iDots |= (1 << (8-1));
    iDots |= (1 << (7-1));
    iDots &= ~((1 << (5-1)) | (1 << (4-1)));
    break;
  case 2:
    //Minutes
    iDots |= (1 << (5-1));
    iDots |= (1 << (4-1));
    iDots &= ~( (1 << (8-1)) | (1 << (7-1)));
    break;     
  case 3:
    //Alarm
    iDots |= (1 << (9-1));
    break;          
  case 4:
    //No alarm
    iDots &= ~( (1 << (9-1)) );
    break; 
  }   
}

I did a blog post about this very thing, and I used a portion of your code! Do you have a website or any way I can credit you? the blog is here: http://doayee.co.uk/vfd-tube-clock/ :) hope this helps!