Search |
 |
|
 |
| Author |
Message |
|
|
Posted: Apr 18, 2010 - 05:07 AM |
|

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. |
|
|
| |
|
|
|
|
|
Posted: Apr 18, 2010 - 05:32 AM |
|


Joined: Nov 22, 2002
Posts: 12031
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
|
| |
|
|
|
|
|
Posted: Apr 18, 2010 - 06:00 AM |
|

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. |
|
|
| |
|
|
|
|
|
Posted: Apr 18, 2010 - 07:31 AM |
|


Joined: Nov 22, 2002
Posts: 12031
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
|
| |
|
|
|
|
|
Posted: Apr 18, 2010 - 10:58 AM |
|

Joined: Feb 12, 2005
Posts: 16254
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. |
|
|
| |
|
|
|
|
|
Posted: Apr 19, 2010 - 01:58 AM |
|

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? |
|
|
| |
|
|
|
|
|
Posted: Apr 19, 2010 - 02:08 AM |
|


Joined: Nov 22, 2002
Posts: 12031
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
|
| |
|
|
|
|
|
Posted: Apr 20, 2010 - 02:21 AM |
|

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)))
{;}
}
|
|
|
| |
|
|
|
|
|
Posted: Apr 20, 2010 - 04:40 AM |
|


Joined: Mar 28, 2001
Posts: 20311
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
|
| |
|
|
|
|
|
Posted: Apr 20, 2010 - 05:39 AM |
|

Joined: May 24, 2004
Posts: 5994
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. |
|
|
| |
|
|
|
|
|
Posted: Apr 20, 2010 - 09:29 AM |
|

Joined: Feb 12, 2005
Posts: 16254
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. |
|
|
| |
|
|
|
|
|
Posted: May 14, 2010 - 07:28 AM |
|

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. |
|
|
| |
|
|
|
|
|
Posted: May 14, 2010 - 08:25 AM |
|

Joined: Feb 12, 2005
Posts: 16254
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. |
|
|
| |
|
|
|
|
|
Posted: May 15, 2010 - 12:04 AM |
|

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 |
|
|
| |
|
|
|
|
|
Posted: May 15, 2010 - 08:04 AM |
|

Joined: Feb 12, 2005
Posts: 16254
Location: Wormshill, England
|
|
Your code should display '12345678' or possibly '87654321'.
IME maximum intensity takes a LOT of current.
David. |
|
|
| |
|
|
|
|
|
Posted: May 16, 2010 - 05:59 AM |
|

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
thanks for the help |
|
|
| |
|
|
|
|
|
Posted: Jun 21, 2010 - 10:41 AM |
|

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. |
|
|
| |
|
|
|
|
|
Posted: Jun 21, 2010 - 10:57 AM |
|

Joined: Feb 12, 2005
Posts: 16254
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. |
|
|
| |
|
|
|
|
|
Posted: Jun 22, 2010 - 01:02 AM |
|

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 |
|
|
| |
|
|
|
|
|
Posted: Jun 22, 2010 - 01:17 AM |
|

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  |
|
|
| |
|
|
|
|
|
Posted: Jun 22, 2010 - 03:52 AM |
|


Joined: Mar 28, 2001
Posts: 20311
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
|
| |
|
|
|
|
|
Posted: Jun 22, 2010 - 08:03 AM |
|

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.
Thanks everyone for all the help |
|
|
| |
|
|
|
|
|
Posted: Jun 22, 2010 - 09:08 AM |
|

Joined: Feb 12, 2005
Posts: 16254
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. |
|
|
| |
|
|
|
|
|
Posted: Jun 23, 2010 - 06:16 AM |
|

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. |
|
|
| |
|
|
|
|
|
Posted: Jun 23, 2010 - 08:16 AM |
|

Joined: Feb 12, 2005
Posts: 16254
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. |
|
|
| |
|
|
|
|
|
Posted: Jun 27, 2010 - 06:10 AM |
|

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? |
|
|
| |
|
|
|
|
|
Posted: Jun 27, 2010 - 08:01 AM |
|

Joined: Feb 12, 2005
Posts: 16254
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. |
|
|
| |
|
|
|
|
|
Posted: Jun 27, 2010 - 09:40 AM |
|

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:| |
|
|
| |
|
|
|
|
|
Posted: Jun 18, 2012 - 12:20 PM |
|


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. |
|
|
| |
|
|
|
|
|
|
|
|