Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
baker158
PostPosted: Apr 18, 2010 - 05:07 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

hi everyone i'm new so if i have put this in the wrong place i'm sorry.
i am currently working on a project, and i am trying to get some numbers output on 8 7-segment displays. the displays are driven by a Maxim max7219 chip. i have PIN.B0, on the Atmega 16 connected to the DIN pin of the 7219, B1 connected to LOAD and B2 connected to CLK.

my question is how do i code the program to output the numbers to the the 7-segment displays?
I'm using AVR studio 4 with WinAVR.

also if the connections are wrong or there needs to be additional connections that advice would be greatly appreciated.
 
 View user's profile Send private message  
Reply with quote Back to top
ka7ehk
PostPosted: Apr 18, 2010 - 05:32 AM
10k+ Postman


Joined: Nov 22, 2002
Posts: 12193
Location: Tangent, OR, USA

I assume that your "b1" refers to I/O pin PB1 on the AVR.

This chip communicates via SPI, so you want to use the hardware SPI port. That would be PB4-PB7 on the Mega16.

It takes TWO of these chips, a 7219 and and a 7221 to drive multiple digits. For one digit, you can use a 7221, only. I don't see how you would use a 7219, by itself. The 7219 is a "digit selector" and the 7219 is the "segment selector".

Jim

_________________
Jim Wagner
Oregon Research Electronics, Consulting Div.
Tangent, OR, USA

"The only thing standing between us and victory is defeat" P.G.Wodhouse in Wooster & Jeeves series
 
 View user's profile Send private message  
Reply with quote Back to top
baker158
PostPosted: Apr 18, 2010 - 06:00 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

the way i was told it works is the 7219 only enables one digit at a time but if the cycle rate is high enough it looks like it is driving all 8 digits at once.
 
 View user's profile Send private message  
Reply with quote Back to top
ka7ehk
PostPosted: Apr 18, 2010 - 07:31 AM
10k+ Postman


Joined: Nov 22, 2002
Posts: 12193
Location: Tangent, OR, USA

You have the principle right, but not the detail.

Yes, 7219 enables one digit at a time. BUT, you are talking about starting with only one digit. So, you have to enable various SEGMENTS of that digit in order to create various symbols. Thus, for this one digit, you need a 7221 to control the segments of that digit.

Now, the way the whole thing works. You send the serial data to a 7221 to turn on various digits for the first character. Then you send data to the 7219 to turn on the digit for the segments you just enabled. That turns on the display digit. Then, strictly, you would send a new message to the 7219 to turn off the digit that was just on. THen you send the message to the 7221 to turn on the desired segments of the second digit. Then you send the data to the 7219 to turn on just that digit. You then continue this pattern until all digits have been displayed and THEN you start over.

Each of the "messages" (data) to a 7219 or 7221 goes out the SPI port. You enable the desired chip, then send the 8 bits to achieve the desired operation,

Hope this helps
Jim

_________________
Jim Wagner
Oregon Research Electronics, Consulting Div.
Tangent, OR, USA

"The only thing standing between us and victory is defeat" P.G.Wodhouse in Wooster & Jeeves series
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Apr 18, 2010 - 10:58 AM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16547
Location: Wormshill, England

Jim is over complicating it.

You have the MAX7219 connected to a load of 7 segment displays according to the schematic in the data sheet.

Then you just write 16 bit command words to the MAZ7219. The multiplexing, brightness, display contents etc are all determined by the commands that you give it.

Then it will continue to do everything by itself. Just like a Computer terminal. You type -- it displays. You can still read the display days later. Unless you type something different.

Since you are not using the official SPI pins, you will need to bit-bash the 16 bit command words.

Code:

#define SDP8_CLOCK   (1<<2)
#define SDP8_LOAD   (1<<1)
#define SDP8_DATA   (1<<0)
#define DDR_WRITE   0x07      /* bits 0-2 o/p */

#define sdp8_data       PORTB
#define sdp8_ctl        DDRB

static void shft8bit(unsigned char val)
{
   unsigned char cnt;
   sdp8_data &= (~SDP8_CLOCK & ~SDP8_LOAD);   /* CLOCK = LOAD = 0 */
   for (cnt = 8; cnt; --cnt, val <<= 1) {
      sdp8_data &= ~SDP8_DATA;
      if (val & 0x80) sdp8_data |= SDP8_DATA;
      sdp8_data |= SDP8_CLOCK;
      sdp8_data &= ~SDP8_CLOCK;
   }
   sdp8_data |= SDP8_DATA;
}

void sdp8(unsigned char posn, unsigned char val)
{
   shft8bit(posn);
   shft8bit(val);
   sdp8_data |= SDP8_LOAD;
   sdp8_data &= ~SDP8_LOAD;
}

void initsdp8(void)
{
   sdp8_ctl = DDR_WRITE;
   sdp8(0x0a, 0x01);   /* low intensity */
   sdp8(0x0b, 0x07);   /* scan limit */
   sdp8(0x09, 0xff);   /* decode each digit */
   sdp8(0x0c, 0x01);   /* not shutdown */
   sdp8(0x0f, 0x00);   /* display test */
}

Each 16 bit word is made up with the 8 bit 'command' and the 8 bit 'argument'. Once you have done the initialising, you just write to position 1..8 and it will display data in that 7-seg.

If you write 0x00 for command #9, it will do the decoding for you.
Code:

   sdp8(0x09, 0x00);   /* automatic decode */

e.g. you just write the raw data to each digit
Code:

        // show 567
   sdp8(0x01, 0x05);   /*  */
   sdp8(0x02, 0x06);   /*  */
   sdp8(0x03, 0x07);   /*  */

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
baker158
PostPosted: Apr 19, 2010 - 01:58 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

would it be simpler to just move the connections to the official SPI pins as they are not being used by anything at the moment?
 
 View user's profile Send private message  
Reply with quote Back to top
ka7ehk
PostPosted: Apr 19, 2010 - 02:08 AM
10k+ Postman


Joined: Nov 22, 2002
Posts: 12193
Location: Tangent, OR, USA

Absolutely!

Jim

_________________
Jim Wagner
Oregon Research Electronics, Consulting Div.
Tangent, OR, USA

"The only thing standing between us and victory is defeat" P.G.Wodhouse in Wooster & Jeeves series
 
 View user's profile Send private message  
Reply with quote Back to top
baker158
PostPosted: Apr 20, 2010 - 02:21 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

Ok with the SPI all i need to do is use the code in the ATmega16's data sheet and it should be capable of transmitting a 16-bit word to the 7219, is that right or is there more i need to do?
Thanks for the help

Code:
void SPI_MasterInit(void)
{
/* Set MOSI and SCK output, all others input */
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
/* Enable SPI, Master, set clock rate fck/16 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}
void SPI_MasterTransmit(char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
{;}
}
 
 View user's profile Send private message  
Reply with quote Back to top
js
PostPosted: Apr 20, 2010 - 04:40 AM
10k+ Postman


Joined: Mar 28, 2001
Posts: 20630
Location: Sydney, Australia (Gum trees, Koalas and Kangaroos, No Edelweiss)

Quote:
should be capable of transmitting a 16-bit word
No such thing with SPI, all transactions happen 8 bit at a time. So you will need to spit the 16 bit word into 2, send the first byte, wait for SPIF (as above) send 2nd byte.

_________________
John Samperi
Ampertronics Pty. Ltd.
www.ampertronics.com.au
* Electronic Design * Custom Products * Contract Assembly
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Jepael
PostPosted: Apr 20, 2010 - 05:39 AM
Raving lunatic


Joined: May 24, 2004
Posts: 6028
Location: Tampere, Finland

baker158 wrote:
Ok with the SPI all i need to do is use the code in the ATmega16's data sheet and it should be capable of transmitting a 16-bit word to the 7219, is that right or is there more i need to do?
Thanks for the help


You need to control the chip select or load too yourself. Also with proper timing related to bytes. SPI hardware only transmits 8-bit bytes via clock and data pins. So a 16-bit word is two bytes.
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Apr 20, 2010 - 09:29 AM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16547
Location: Wormshill, England

I showed a bit-bash solution because the OP said he was using non-SPI lines.

However if you use SPI lines yo just use:
Code:

void sdp8(unsigned char posn, unsigned char val)
{
   sdp8_data &= ~SDP8_LOAD;  // enable SPI
   spi(posn);
   spi(val);
   sdp8_data |= SDP8_LOAD;   // latch the data
}

Note that the MAX7219 happily reads in whatever you send it. However it only latches the information when the 'LOAD' pin goes high. ( /SS going high )

If you cascade several MAX7219's you propagate the relevant 16 bit command to each MAX7219 in the chain. As /SS goes high, the command is latched and the display is updated accordingly.

Oh, for those people who find difficulty with a 16 bit command: 16 bits is two times 8 bits.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
baker158
PostPosted: May 14, 2010 - 07:28 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

ok i've been trying to get this to work, below shows the connections between the atmega16 and max7219
atmega-max7219
PB0-LOAD
PB5(MOSI)-DIN
PB7(SCK)-CLK

below is the code i am using, it should just be displaying the test function of the max7219 but i get nothing on the 7-segment display.

Code:
#include <avr/io.h>




#define SDP8_LOAD   (1<<0)

#define sdp8_data       PORTB
#define sdp8_ctl        DDRB

void SPI_MasterInit(void)
{
/* Set MOSI and SCK and B0 (B0 is load pin) output, all others input */
DDRB = (1<<DDB5)|(1<<DDB7)|(1<<DDB0);
/* Enable SPI, Master, set clock rate fck/16 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void spi(char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;
}

void sdp8(unsigned char posn, unsigned char val)
{
   sdp8_data &= ~SDP8_LOAD;  // enable SPI
   spi(posn);
   spi(val);
   PORTB|=0b00000001;   // latch the data
}


void initsdp8(void)
{
//   sdp8_ctl = DDR_WRITE;
   sdp8(0x0A, 0x01);   /* low intensity */
   sdp8(0x0B, 0x00);   /* scan limit set to digit 0 only, 0x07 for all digits*/
   sdp8(0x09, 0x01);   /* decode digit 0 (FF for decode all digits)*/
   sdp8(0x0C, 0x01);   /* not shutdown */
   sdp8(0x0F, 0x01);   /* display test */
  // _delay_ms(100);      /*display test for 1 second*/
  // sdp8(0x0F, 0x00);   /* stop test*/

}

int main(void)
{
   initsdp8();
}


are there any problems? what is the likely hood that the max7219 is fried? and is there any way of testing it its fried apart from writing a program as above?

Thanks for the help.
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: May 14, 2010 - 08:25 AM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16547
Location: Wormshill, England

Your code should work. I would be happier with you driving 8 displays even if you only have one connected.

After all, if you have the wrong display selected, you will not see anything.

So wire up your hardware according to the schematic in the 7219 data sheet. And display the test on all displays.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
baker158
PostPosted: May 15, 2010 - 12:04 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

ok it works but only when i enable the test feature
Code:
sdp8(0x0F,0x01)

i get nothing with the following code which should output a number to the display depending on which digit of the 7219 the 7-segment display is connected to.
for reference i know it is connected to Digit0 but i still get nothing.
Code:

void initsdp8(void)
{

   sdp8(0x0A, 0x0F);   /* high intensity */
   sdp8(0x0B, 0x07);   /* scan limit set to digit 0 only, 0x07 for all digits*/
   sdp8(0x09, 0xFF);   /* decode digit 0 (FF for decode all digits)*/
   sdp8(0x0C, 0x01);   /* not shutdown */
   //sdp8(0x0F, 0x01);   /* display test */
   //_delay_ms(1000);      /*display test for 1 second*/
   sdp8(0x0F, 0x00);   /* stop test*/

}




int main(void)
{
   initsdp8();
   while(1)
   {
      sdp8(0x01, 0x01);
      sdp8(0x02, 0x02);
      sdp8(0x03, 0x03);
      sdp8(0x04, 0x04);
      sdp8(0x05, 0x05);
      sdp8(0x06, 0x06);
      sdp8(0x07, 0x07);
      sdp8(0x08, 0x08);


   }
   return 1;
}


thanks again for the help
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: May 15, 2010 - 08:04 AM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16547
Location: Wormshill, England

Your code should display '12345678' or possibly '87654321'.

IME maximum intensity takes a LOT of current.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
baker158
PostPosted: May 16, 2010 - 05:59 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

david.prentice wrote:
Your code should display '12345678' or possibly '87654321'.

IME maximum intensity takes a LOT of current.

David.


thats true is should be displaying all those numbers but if i only have one 7-segment display connected shouldn't it only display the number that is being sent to that display?
ie. if i only have one 7-segment display which is connected to Digit0 on the 7219 then it should be showing 1 on that display and then be sending the other numbers to the other digits that are not connected.

I'll turn the intensity down Embarassed

thanks for the help
 
 View user's profile Send private message  
Reply with quote Back to top
baker158
PostPosted: Jun 21, 2010 - 10:41 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

ok i've finally got some time to work on this.

I have changed from a MAX7219 to a MAX7221, all other hardware is the same and the connections can be seen in the attachment.

i am trying to send the number 6 to digit 1 on the MAX7221, or any number for that matter.

the code i'm using is
Code:


#include <avr/io.h>
#include <util/delay.h>

#define SDP8_LOAD   (1<<0)
#define sdp8_data       PORTB
#define sdp8_ctl        DDRB

void SPI_MasterInit(void)
{
/* Set MOSI and SCK and B0 (B0 is load pin) output, all others input */
DDRB = (1<<DDB5)|(1<<DDB7)|(1<<DDB0);
/* Enable SPI, Master, set clock rate fck/16 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}


void spi(unsigned char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;
}

void sdp8(unsigned char posn, unsigned char val)
{
   PORTB &= ~0b00000001;  // enable SPI
   spi(posn);
   spi(val);
   PORTB|=0b00000010;   // latch the data
}


void initsdp8(void)
{
    sdp8(0x0A, 0x07);   /* high intensity */
    sdp8(0x0B, 0x07);   /* scan limit set to digit 0 only, 0x07 for all digits*/
    sdp8(0x09, 0xFF);   /* no decode (FF for decode all digits)*/
    sdp8(0x0C, 0x01);   /* not shutdown */
    sdp8(0x0F, 0x00);   /* stop test*/

}




int main(void)
{
     initsdp8();
     sdp8(0x01, 0x06);
}


my question is, is there anything wrong with the setup or code?
currently i can only get the 7-segment display to intermittently light up and when it does it's either erratic or simply lights up all segments.
any help would be greatly appreciated.
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Jun 21, 2010 - 10:57 AM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16547
Location: Wormshill, England

Your /CS is on PORTB.1 according to your schematic. So you should have:
Code:

    ...
    DDRB = (1<<DDB5)|(1<<DDB7)|(1<<DDB1);
    ...

void sdp8(unsigned char posn, unsigned char val)
{
   PORTB &= ~(1<<PB1);  // enable SPI
   spi(posn);
   spi(val);
   PORTB |= (1<<PB1);   // latch the data
}

Personally, I would prefer to use the macros:
Code:

#define SDP8_LOAD   (1<<PB1)     // PORTB.1
...
    ...
    DDRB = (1<<DDB5)|(1<<DDB7)|SDP8_LOAD;
    ...

void sdp8(unsigned char posn, unsigned char val)
{
   PORTB &= ~SDP8_LOAD;  // enable SPI
   spi(posn);
   spi(val);
   PORTB |= SDP8_LOAD;   // latch the data on rising edge
}


David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
baker158
PostPosted: Jun 22, 2010 - 01:02 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

ok fixed those mistakes though i'm still getting the same results.
the code is now
Code:

#include <avr/io.h>
#include <util/delay.h>

#define SDP8_LOAD   (1<<PB1)     // PORTB.1
#define sdp8_data       PORTB
#define sdp8_ctl        DDRB





void SPI_MasterInit(void)
{
/* Set MOSI and SCK and B0 (B0 is load pin) output, all others input */
DDRB = (1<<DDB5)|(1<<DDB7)|SDP8_LOAD;
/* Enable SPI, Master, set clock rate fck/16 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}


void spi(unsigned char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;
}

void sdp8(unsigned char posn, unsigned char val)
{
   PORTB &= ~SDP8_LOAD;  // enable SPI
   spi(posn);
   spi(val);
   PORTB |= SDP8_LOAD;   // latch the data on rising edge
}


void initsdp8(void)
{
    sdp8(0x0A, 0x07);   /* high intensity */
    sdp8(0x0B, 0x07);   /* scan limit set to digit 0 only, 0x07 for all digits*/
    sdp8(0x09, 0xFF);   /* no decode (FF for decode all digits)*/
    sdp8(0x0C, 0x01);   /* not shutdown */
    //sdp8(0x0F, 0x01);   /* start test*/
   //_delay_ms(2000);
   sdp8(0x0F, 0x00);   /* stop test*/

}




int main(void)
{
   
   initsdp8();
   sdp8(0x01, 0x06);



}


 



i know the problem is neither of the chips as they are brand new.
are there any other problems?
Thanks
 
 View user's profile Send private message  
Reply with quote Back to top
baker158
PostPosted: Jun 22, 2010 - 01:17 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

i have just realised that the code doesn't initialise the SPI so i have changed the main function to
Code:

int main(void)
{
   SPI_MasterInit();
   initsdp8();
        sdp8(0x01, 0x06);


}


and now i get nothing no output to the seven segment intermittent or otherwise Sad
 
 View user's profile Send private message  
Reply with quote Back to top
js
PostPosted: Jun 22, 2010 - 03:52 AM
10k+ Postman


Joined: Mar 28, 2001
Posts: 20630
Location: Sydney, Australia (Gum trees, Koalas and Kangaroos, No Edelweiss)

DO NOT connect reset to VCC directly. Use a 10K pullup resistor (and a 100nF cap to ground) or leave it open as it has it's own weak internal pullup.

_________________
John Samperi
Ampertronics Pty. Ltd.
www.ampertronics.com.au
* Electronic Design * Custom Products * Contract Assembly
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
baker158
PostPosted: Jun 22, 2010 - 08:03 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

ok so i've been doing some reading and have found that the MAX7221 is not a true SPI device and so i have managed to get it to work using the bit bash solution thanks to david. Very Happy
Thanks everyone for all the help
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Jun 22, 2010 - 09:08 AM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16547
Location: Wormshill, England

Your program would work just fine if you put a pull-up resistor on PORTB.4 (the SS pin).

The SPI is receiving noise on this input pin, and jumping into Slave mode.

As a general rule, an SPI Master chooses the SS pin for its first slave. Then uses other o/p pins for all its other Slaves.

To stop jumping into Slave mode, either put a pull-up on PORTB.4 or make it an o/p pin.

Code:

int main(void)
{
   SPI_MasterInit();   
   initsdp8();
   // write 87654321 on the display
   for (uint8_t i = 1; i < 9; i++)
       sdp8(i, i);
}


I would strongly advise that you use spi() as God intended. i.e. you send it a value, and receive a value back. OK, in this case you may not have connected the MISO pin. But if you did, you could see the command propagate through your MAX7219 chip. You would also help my worldwide war on void functions.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
baker158
PostPosted: Jun 23, 2010 - 06:16 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

ok that works thanks:D
the next step it to cascade two MAX7221 so that i can display 16 digits
i have my circuit connected as in the attachment

i have modified the code as follows so that the data can be latched to the correct max7221
Code:


#include <avr/io.h>
#include <util/delay.h>

#define SDP8_LOAD0   (1<<PB0)     // PORTB.0
#define SDP8_LOAD1   (1<<PB1)     // PORTB.1
#define sdp8_data       PORTB
#define sdp8_ctl        DDRB





void SPI_MasterInit(void)
{
/* Set MOSI and SCK and B1 (B1 is load pin) output, all others input */
DDRB = (1<<DDB5)|(1<<DDB7)|SDP8_LOAD0|SDP8_LOAD1;
/* Enable SPI, Master, set clock rate fck/16 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}


void spi(unsigned char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;
}

void sdp8(unsigned char posn, unsigned char val,unsigned char load)
{
   
    PORTB &= ~SDP8_LOAD0;  // enable SPI
    PORTB &= ~SDP8_LOAD1;
    spi(posn);
    spi(val);
    if (load==0){
         PORTB |= SDP8_LOAD0;   // latch the data on rising edge
   }
   else {
      PORTB |= SDP8_LOAD1;
   }
}


void initsdp8(void)
{
    int i;
   for (i=0;i<2;i++){
      sdp8(0x0A, 0x07, i);   /* high intensity */
               sdp8(0x0B, 0x07, i);   /* scan limit set to digit 0 only, 0x07 for all digits*/
               sdp8(0x09, 0xFF, i);   /* no decode (FF for decode all digits)*/
               sdp8(0x0C, 0x01, i);   /* not shutdown */
               sdp8(0x0F, 0x01, i);   /* start test*/
      _delay_ms(1000);
      sdp8(0x0F, 0x00, i);   /* stop test*/
   }
}




int main(void)
{
   
   SPI_MasterInit();
   initsdp8();

   
      sdp8(0x01, 0x01, 0);
      sdp8(0x02, 0x02, 1);
      sdp8(0x03, 0x03, 0);
      sdp8(0x04, 0x04, 1);
      sdp8(0x05, 0x05, 0);
      sdp8(0x06, 0x06, 1);
      sdp8(0x07, 0x07, 0);
      sdp8(0x08, 0x08, 1);


}


the first max7221 (load pin on PB0) is working as expected, however the second (load pin on PB1) seems to be displaying only the test function.
any suggestions?
Thanks.
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Jun 23, 2010 - 08:16 AM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16547
Location: Wormshill, England

Is there any chance that you can post schematics that are black on white. Can you read a yellow on black?

The way that you run two MAX7219's is to cascade the Data Out into Data In of the next chip. They both use the same Chip Enable line (Load pin).

So you would just use the regular commands. If you want to write to the x'th digit of the the n'th cascaded display of N displays, you send (N-n) NOP commands, the sdp8(x, value) followed by (N-n+1) NOP commands. With two cascaded displays, this means you write to digits 9-16 with sdp8(x-8, val), sdp8(NOP, val). And to digits 1-8 with sdp8(NOP, val), sdp8(x, val)

If you think about it, all your initialisation commands propagate through automatically.

As a silly question, have you thought of reading the data sheet?

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
baker158
PostPosted: Jun 27, 2010 - 06:10 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

yeah i have read the data sheet. my understanding of it is if you want to send the number 1 to the first digit on the first chip you first send the noop command (posn 0x00, val 0x00) then you send posn 0x01, val 0x01, THEN you latch the data. or if you wanted to send the same number to the same digit on the second chip you would send posn 0x01, val 0x01 then send the noop command, then latch the data,
as follows. is this correct.

to send 1 to first chip
sdp8(0x01,0x01,0);
to send 1 to second chip
sdp8(0x01,0x01,1);

Code:

void sdp8(unsigned char posn, unsigned char val, unsigned char  load)
{
   
    PORTB &= ~SDP8_LOAD0;  // enable SPI
   
   if (load==0){
       spi(0x00); //No op address
      spi(0x00); //No op data
      spi(posn);
       spi(val);
   }
   if (load==1){
      spi(posn);
       spi(val);      
       spi(0x00); //No op address
      spi(0x00); //No op data
   }
         PORTB |= SDP8_LOAD0;   // latch the data on rising edge


another problem i am having is the displays turn off after a couple of seconds and don't come back on until i turn the power off and on again. any suggestions?
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Jun 27, 2010 - 08:01 AM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16547
Location: Wormshill, England

Yes, your function looks about right. Personally I would choose a different name for parameter #3.

Your code was setting maximum intensity. This will draw a very large current from your power supply. Is it shutting down?

If you have a noisy environment or a breadboad/clothes-peg wiring system, it is very easy to get a duff command on the shift register. So it is wise to periodically send the initialisation commands.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
baker158
PostPosted: Jun 27, 2010 - 09:40 AM
Rookie


Joined: Apr 18, 2010
Posts: 43
Location: Wollongong, Australia

i have changed the code to draw minimum intensity and as far as i can tell the power supply is not shutting down.
my circuit is soldered to a vero board which i have checked.
i'll try sending the initialisation command again however one of the circuits shuts down after half a second which isn't really enough time to do anything:|
 
 View user's profile Send private message  
Reply with quote Back to top
hanemagne
PostPosted: Jun 18, 2012 - 12:20 PM
Hangaround


Joined: Feb 10, 2011
Posts: 164
Location: Trondheim, Norway

Sorry for reviving this ancient thread, but try this (written for ATmega48):
Code:

#include <avr/io.h>

#define SPI_PORT PORTB
#define SPI_DDR DDRB
#define SCK_PIN PB5
#define MISO_PIN PB4
#define MOSI_PIN PB3
#define SS_PIN PB2

#define LOW(x)      ((x) & 0xFF)
#define HIGH(x)      (((x)>>8) & 0xFF)

void initPorts(void);
void initSPI(void);
void sendSPI(uint16_t);
void initDriver(void);
void blankDisplay(void);

int main(void){
   initPorts();
   initSPI();
   initDriver();
   blankDisplay();
   
   /* Here comes code */
   
    while(1){
        //TODO:: Please write your application code
    }
}

void initPorts(void){
   SPI_DDR = 0xFF;
   SPI_PORT |= (1 << SS_PIN);
}

void initSPI(void){
   SPCR = ((1 << SPE) | (1 << MSTR));
   SPSR = (1 << SPI2X);
}

void sendSPI(uint16_t data){
   SPI_PORT &= ~(1 << SS_PIN);
   SPDR = HIGH(data);
   while(!(SPSR & (1 << SPIF)));
   SPDR = LOW(data);
   while(!(SPSR & (1 << SPIF)));
   SPI_PORT |= (1 << SS_PIN);
}

void initDriver(void){
   sendSPI(0x0C01);
   sendSPI(0x0B07);   
   sendSPI(0x0A0F);
   sendSPI(0x0900);
}

void blankDisplay(void){
   sendSPI(0x0100);
   sendSPI(0x0200);
   sendSPI(0x0300);
   sendSPI(0x0400);
   sendSPI(0x0500);
   sendSPI(0x0600);
   sendSPI(0x0700);
   sendSPI(0x0800);
}


I've tested this myself, and I know it works (tested with MAX7221, but should theoretically work with MAX7219 also).
It's configured for 8 digits, no B decode and max intensity. Just change the configuration parameters to suit your needs.
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits