Go Down

Topic: MAX6921 - need help (Read 1 time) previous topic - next topic

olof_n

Hi!

I am trying to get MAX6921 to drive my display.
http://datasheets.maximintegrated.com/en/ds/MAX6921-MAX6931.pdf

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 :) )

Here is one of my code examples:

Code: [Select]

     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:

Code: [Select]

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

fungus


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


You seem to have this pin backwards...

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

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?

/Olof

fungus


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
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

dhenry

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:

Code: [Select]
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%.

olof_n

Now it works, thanks for the help :)

This is a great forum!


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

Code: [Select]

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

robot797

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

olof_n

#7
Aug 15, 2013, 07:44 pm Last Edit: Aug 15, 2013, 07:55 pm by olof_n Reason: 1
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.


Code: [Select]

#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;
 }  
}

8163jb

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!

Go Up