Pages: [1]   Go Down
Author Topic: Completely new to SPI, I need some help  (Read 679 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi. I've decided to learn a little bit about SPI and later also I2C (when I get an IC that supports it). I'm using the MAX7219 display driver that's connected to a 4-digit display (digit 0-3). I've used the display driver library and it works fine so I know that there's nothing wrong with my connections. This is the code I came up with:

Quote
int LOAD = 8;

#include <SPI.h>

void setup() {
  SPI.begin();
  SPI.setDataMode(3);
  SPI.setBitOrder(LSBFIRST);
  pinMode(LOAD, OUTPUT);
}

void loop() {
  digitalWrite(LOAD, LOW);
  SPI.transfer(0xF1);
  SPI.transfer(0xAA);
  digitalWrite(LOAD, HIGH);
  delay(1000);
}

I figured that setbitorder must be LSBFIRST because the datasheet shows the clock signal with an arrow and the LSB closest to it. I also figured that setDataMode probably is 3 as the driver triggers on the rising edge of the clock. I've looked at the display driver library and I see that the LOAD pin is put LOW before data transfer and then back HIGH. It also says so in the datasheet that the data is stored after LOAD is pulled back high before the next clock cycle, if it happens after the 17th clock cycle, the data is lost. The transfer in that code is 11110001 10101010. The first word (MSB) doesn't matter (don't care). The next word is setting either which digit this relates to, or if brightness etc. should be adjusted. 0001 should make it relate to digit 0. The last eight bits correspond to the segments, I just chose some random values. I upload the code, the display blinks and then just shows every segment lit. I've been trying this and that the whole day, but the darn display won't show anything else than a bunch of eight's :S What am I doing wrong?
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 484
Posts: 18768
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a page about that chip and SPI here:

http://www.gammon.com.au/forum/?id=11516

More stuff about SPI: http://www.gammon.com.au/spi

My code didn't change the data mode nor the bit order, and it worked.
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for those links. I found the code that relates to controlling a 7-seg display rather than a matrix display, copied it, uploaded and saw a bunch of eights smiley-sad The code had "const byte SS = 10;  // omit this line for Arduino 1.0 onwards", but my compiler wasn't to happy about it. I their fore changed it to int LOAD = 10. It says that this can be omitted, but I don't know why :S This LOAD pin has to be pulled down regardless of your arduino software version and I don't think the SPI library has any function regarding this pin.

I'm thinking that my pinouts are wrong, but I've been over them a hundred times. DIN->digital input 11, LOAD -> digital input 10, CLK -> digital input 13.

Reading the code that you linked I can't see any difference from what I am doing in my code. LOAD gets LOW, 8bits is transferred followed by another 8bits, LOAD gets back high.

Another thing I noted. The atmega328p has it's mosi and miso marked, I guess there's some special SPI function already inside the mcu? In the link you gave me, the MAX is connected as I mentioned above, that is DIN->MOSI, this is also what it says in the SPI library. In the library specific for display control (the one that works), DIN is connected to MISO and the clk is connected to MOSI. What's up with that?
« Last Edit: February 27, 2013, 04:36:15 am by Plecto » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 484
Posts: 18768
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The SPI pins are done by hardware, you can't change that. You can however have multiple SS pins as long as the "real" SS pin (D10) is set to output.

Quote
In the library specific for display control (the one that works), DIN is connected to MISO

No it isn't. It's MOSI (master out, slave in) for DIN (data in ... to the 595 chip).

Quote
clk is connected to MOSI

Where did you see that?

Check your wiring, I suggest.
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
// pin 12 is connected to the MAX7219 pin 1
// pin 11 is connected to the CLK pin 13
// pin 10 is connected to LOAD pin 12

Pin 1 on the MAX is DIN, pin 12 on the arduino is MISO. Pin 11 on the arduino is MOSI which is connected to CLK.

I still wonder what I did wrong on the first code I linked smiley-sad
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've gotten a lot closer! I figured i needed to set some settings first, like the shutdown mode, scan limit and perhaps intensity and decoder mode. I did that and it actually worked! That was until I disconnected my scope which brought the display back to all eights smiley-sad I've uploaded the exact same code, turned the power on and off, but no. I tried connecting my scope again, but it didn't make any difference. What could cause this? Here's the code I came up with:

Code:
int LOAD = 10;

#include <SPI.h>

void setup() {
  SPI.begin();
  //SPI.setDataMode(3);
  //SPI.setBitOrder(MSBFIRST);
  pinMode(LOAD, OUTPUT);
  digitalWrite(LOAD, HIGH);
 
  digitalWrite(LOAD, LOW);
  SPI.transfer(0x0C); //Shutdown mode
  SPI.transfer(0x01); //X1 meaning normal operation
  digitalWrite(LOAD, HIGH);
  delay(10);
  digitalWrite(LOAD, LOW);
  SPI.transfer(0x0A); //Intensity
  SPI.transfer(0x0F); //XF meaning 100%
  digitalWrite(LOAD, HIGH);
  delay(10);
  digitalWrite(LOAD, LOW);
  SPI.transfer(0x0B); //Scan limit
  SPI.transfer(0x07); //X7 meaning all digits
  digitalWrite(LOAD, HIGH);
  delay(10);
  digitalWrite(LOAD, LOW);
  SPI.transfer(0x09); //Decode mode
  SPI.transfer(0x00); //X0 meaning no decode for digits 7-0
  digitalWrite(LOAD, HIGH);
  delay(10);
 
}

void loop() {
 
 
  digitalWrite(LOAD, LOW);
  SPI.transfer(0x01); //choose digit 0
  SPI.transfer(0xAA); //write some wierd symbol
  digitalWrite(LOAD, HIGH);
  delay(10);
 
}
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 484
Posts: 18768
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
// pin 12 is connected to the MAX7219 pin 1
// pin 11 is connected to the CLK pin 13
// pin 10 is connected to LOAD pin 12

Pin 1 on the MAX is DIN, pin 12 on the arduino is MISO. Pin 11 on the arduino is MOSI which is connected to CLK.

I still wonder what I did wrong on the first code I linked smiley-sad

That's wrong, sorry. You do not connect to MISO (pin D12) because that is for incoming data. Don't proceed until you fix that.

On my wiring D12 is not used. And it works.


Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, do make that display library work I have to connect it to the MISO pin. I guess that library doesn't use the internal PSI thingy in the MCU and rather bit-bang everything? I'm not connecting it that way when testing the code I have pasted in this thread though, I'm following the pinout given by the SPI library.

I still wonder what's wrong with my code though as I know there's nothing wrong with my connections.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 484
Posts: 18768
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If they bit-banged, perhaps. A link to where you are getting this info from would be good.

Quote
I know there's nothing wrong with my connections

I don't know how you can say that if you are connecting to MISO.
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm getting the information from this site: http://tronixstuff.wordpress.com/2010/07/09/review-maxim-max7219-led-display-driver-ic/

I just said: "I'm not connecting it that way when testing the code I have pasted in this thread though, I'm following the pinout given by the SPI library."
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 484
Posts: 18768
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks like they must be doing bit-banging:

Quote
The first 3 arguments are the pin-numbers on the Arduino that are connected to the MAX72XX. You are free to choose any of the digital IO-pins on the arduino, ...



Quote
I still wonder what's wrong with my code though as I know there's nothing wrong with my connections.

Can you try something for me? Just run the example code on my page, the code for the 7-segment display, namely this:

Code:

#include <SPI.h>
const byte SS = 10;  // omit this line for Arduino 1.0 onwards

const byte MAX7219_REG_NOOP        = 0x0;
// codes 1 to 8 are digit positions 1 to 8
const byte MAX7219_REG_DECODEMODE  = 0x9;
const byte MAX7219_REG_INTENSITY   = 0xA;
const byte MAX7219_REG_SCANLIMIT   = 0xB;
const byte MAX7219_REG_SHUTDOWN    = 0xC;
const byte MAX7219_REG_DISPLAYTEST = 0xF;

void sendByte (const byte reg, const byte data)
  {    
  digitalWrite (SS, LOW);
  SPI.transfer (reg);
  SPI.transfer (data);
  digitalWrite (SS, HIGH);
  }  // end of sendByte
 
void setup ()
  {
  SPI.begin ();
  sendByte (MAX7219_REG_SCANLIMIT, 3);      // show 4 digits
  sendByte (MAX7219_REG_DECODEMODE, 0xFF);  // use digits (not bit patterns)
  sendByte (MAX7219_REG_DISPLAYTEST, 0);    // no display test
  sendByte (MAX7219_REG_INTENSITY, 7);      // character intensity: range: 0 to 15
  sendByte (MAX7219_REG_SHUTDOWN, 1);       // not in shutdown mode (ie. start it up)
}   // end of setup
 
void number (const int num)
  {
 
 char buf [5];
 sprintf (buf, "%4i", min (max (num, 0), 9999));
 
 // send all 4 digits
 for (byte digit = 0; digit < 4; digit++)
   {
   byte c = buf [digit];
   if (c == ' ' )
     c = 0xF;  // code for a blank
   else
     c -= '0';
   sendByte (digit + 1, c);  
   }  
  }  // end of number
  
unsigned int i;

void loop ()
 {
 number (i++);
 delay (100);
 }  // end of loop

If that works, and your code doesn't, yes it's your code. If not, it's your connections. What current-limiting resistor did you choose?
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I get the message "redefinition of 'const byte SS'" I'm not sure what "const" means though. I replaced it with LOAD and it works smiley So it is the code. It's counting quickly as I assume it's supposed to do.

I chose a 62k current limiting resistor. I also have a 470nF smd cap close to the pin. I know the datasheet mentioned a 10uF cap as well, but I'm not sure how important this is unless the display is far away from the power source.

Edit: Wierdly enough, the code I linked to earlier also works! I did absolutely nothing. I disconnected the arduino, minimized the program, said "Screw this, I'm doing something else" and then posted on the forum. I didn't change the code, wiring or nothing.
« Last Edit: February 27, 2013, 04:24:19 pm by Plecto » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 484
Posts: 18768
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
const byte SS = 10;  // omit this line for Arduino 1.0 onwards

Omit that line if you are using the 1.0 version of the IDE onwards.



Quote
I also have a 470nF smd cap close to the pin

Which pin? Those devices can be a bit fiddly if you omit decoupling capacitors. Also you might try the 10 uF (or similar value) as that would help absorb current fluctuations.
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah, I see. Out of curiosity, how can that line be omitted? The LOAD has to be pulled low and high regardless of ardunio software version, right?

The 470nF is close to the +V pin. I do remember getting some unwanted results when using the display library mentioned as well. The problems were similar to the ones I'm having now, the display only showing eights, but it was usually fixed by re uploading the code. Could it be that the settings given in void setup isn't quite registered by the MAX chip in time? Could it be an idea to set things like the shutdown mode in the loop instead so that in case (for some reason) the power to the chip get's disrupted without resetting the arduino?
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 484
Posts: 18768
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah, I see. Out of curiosity, how can that line be omitted?

In recent version of the IDE the variable SS is already defined.

eg. in pins_arduino.h:

Code:
static const uint8_t SS   = 10;
static const uint8_t MOSI = 11;
static const uint8_t MISO = 12;
static const uint8_t SCK  = 13;

Quote
Could it be that the settings given in void setup isn't quite registered by the MAX chip in time?

Well, I didn't have any delays in my code.
Logged


Pages: [1]   Go Up
Jump to: