SPI-Tutorial vs. shiftOut need some clarification

Hello,

I'm using an LCD-Display with SPI-Interface with the arduino. While reading up on the documentation
about SPI-connections I got a litte confused.

On the one hand there is the SPI-Tutorial http://www.arduino.cc/en/Tutorial/SPIEEPROM
I get the impression that the Pins used for MOSI,CLK etc. are hardwired into the library?
Or is there a way to define my own Pins for the SPI-Signals, like it can be done with the shiftOut()
function?

Then I read up on the shiftOut()-function.
I defined my own pins and successfully connected my display.

But what I'm missing here are ways to set the CPOL,CPHA, and (most important) the datarate at
which the bytes are shifted out. The defaults work fine with my display, but what if I had a device that
for instance expects CPOL to idle LOW when inactive or doesn't support the rate at which the data is shifted out?

Is there some (undocumented?) way to tweak these SPI-settings for the shiftOut()-function?

Eberhard

hey: can you post your source-code? i've tried defining my own SPI pins using shift-out but didnt manage to get it working

thx

hey: can you post your source-code? i’ve tried defining my own SPI pins using shift-out but didnt manage to get it working

Here it is , (the relevant parts at least). I connected a LCD-Display to the arduino that is capable to be driven with 4 Wire
SPI-commands. Datasheet for the display is to be found here
http://www.electronic-assembly.de/eng/dog/dog.htm

From the arduino I had to connect 4 pins :

MOSI the pin for the data to be sent to the LCD
CLK the clock for the data
CS when this pin goes low the LCD is listening for data coming in
RS this one is special for my LCD it selects wether the data sent is a character to be displayed, or a intsruction (like CursoHome etc.)
BACKLIGHT a pin used to switch the backlight of the display on/off. (No SPI functionality in here)

Here is some example code. It simply initializes the Display on startup, and the in loop()
it reads the uptime of arduino (millis()), formats it into hours,minutes, etc and prints it on the display forever.

//define the pins to use 
#define MOSI 12
#define CLK  11 
#define RS 10
#define CS 9
#define BACKLIGHT 8

//here the data is actually written to the display (pin 12 is for the data, pin11 is the clock)
void spi_transfer(volatile char data) {
  shiftOut(MOSI,CLK,MSBFIRST,data);
}


void setup() {
  //set all the oins we need as outputs
  pinMode(MOSI, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(RS,OUTPUT);
  pinMode(CS,OUTPUT);
  pinMode(BACKLIGHT,OUTPUT);

  //the CS pin  must be HIGH when we are not talking to the display
  digitalWrite(CS,HIGH); 
  digitalWrite(RS,HIGH);
 
  initLCD();
}

//We have to switch the display on, set the contrast, operation mode etc. This needs to be done only once.
void initLCD() {
  //Switch the backlight on
  digitalWrite(BACKLIGHT,LOW);
  //RS goes low because we ar sending instructions, not characterts to the display
  digitalWrite(RS,LOW);
  //CS goes low, the display is now listening for data
  digitalWrite(CS,LOW);
  //Now send the bytes needed initializing the display 
  spi_transfer(B00111001);
  spi_transfer(B00011100);
  spi_transfer(B01010010);
  spi_transfer(B01101001);
  spi_transfer(B01110001);
  spi_transfer(B00001100);
  spi_transfer(B00000001);
  spi_transfer(B00000010);
  //We are done CS goes high, display stops listening
  digitalWrite(CS,HIGH);
}

//Here we send the timervalue to the display
void writeUptime() {
  char uptimeVal[16];

  //build a String With the uptime
  unsigned long ut=millis();
  
  unsigned long m_sec=ut%1000;
  ut=ut/1000;
  unsigned long sec=ut%60;
  ut=ut/60;
  unsigned long m=ut%60;
  ut=ut/60;
  unsigned long h=ut%24;
  ut=ut/24;

  uptimeVal[0]=' ';
  uptimeVal[1]=' ';
  uptimeVal[2]=(h/10)+48;     
  uptimeVal[3]=(h%10)+48;
  uptimeVal[4]=':';
  uptimeVal[5]=(m/10)+48;     
  uptimeVal[6]=(m%10)+48;
  uptimeVal[7]=':';
  uptimeVal[8]=(sec/10)+48;     
  uptimeVal[9]=(sec%10)+48;
  uptimeVal[10]=':';
  uptimeVal[11]=(m_sec/100)+48;     
  m_sec=m_sec%100;
  uptimeVal[12]=(m_sec/10)+48;
  uptimeVal[13]=(m_sec%10)+48;
  uptimeVal[14]=' ';
  uptimeVal[15]=' ';

  //Return the cursor home an clear the display
  clearDisplay();
  
  //now print it to the LCD : CS goes low Display will be listening
  digitalWrite(CS,LOW);
  //RS goes HIGH : display knows we are sending characters
  digitalWrite(RS,HIGH);

  for(int i=0;i<16;i++) {
    //send the text
    spi_transfer(uptimeVal[i]);
  }
  digitalWrite(RS,HIGH);
  //CS goes high again, display will not listen any more
  digitalWrite(CS,HIGH);
}
        
void clearDisplay() {
  digitalWrite(CS,LOW);
  digitalWrite(RS,LOW);

  //clear the display, cursor home
  spi_transfer(B00000001);
  spi_transfer(B00000010);
  digitalWrite(RS,HIGH);
  digitalWrite(CS,HIGH);
 
}

//update the display every 100 ms        
void loop() {

  writeUptime();
  delay(100);
}

Hope this helps

Eberhard

To clarify part of what you asked about: there is built-in hardware support for SPI in the ATmega168 (or ATmega8) chip on the Arduino board. This works on fixed pins.

It's certainly possible that we need more flexibility in the shiftOut() function. For the moment, we just took the parameters from the BasicStamp version of the function. If you find a piece of hardware that doesn't work with the current function, please let us know.