OSEPP Mega 2560 SPI issue.

I'll try to keep the introduction short then get to the meat of the post quickly.

I started with the Basic Stamp 2, loved it... moved to Microchip's PIC lines 16F628A and the like. I liked them, it was fun, but still not quite the muscle I was looking for. I tried out the PIC32 line of micro controllers and got the PIC kit 3 and was so utterly frustrated and unhappy with my purchase. I saw the "100% Arduino compatible" OSEPP products in Fry's electronics store and impulsively purchased the UNO and Mega 2560.

I know the OSEPP products aren't actual "Arduinos" and that they are supsoedly 100% compatible. So I wanted to see if I could get some help with an SPI problem I'm having with the Mega. I haven't tried the UNO's SPI to see if it's just me, my circuit or an actual problem with the OSEPP Mega 2560.

Essentially the problem is this:

I include the SPI.h in my program, I set the mode to 0, bit order to MSB, and clock divider.

The pin modes and assignments are already made and dictated in the library.

I place a SPI.begin() in the setup function and initiate a transfer.

I leave the default SS pin as an output and high. I utilize another pin to act as the SS / CS for the slave device and I can "see" the clock on my O-scope.

Here's the problem: My MOSI output is inverted directly at the header with no external components connected, just my scope probe. So it's always "high" and drops "low" for what seems to be the data I'm shifting out.

so the process is:
my SS pin goes low.
the clk starts clocking (I can see it on the scope.)
I'm just transfering "0b10101010" out of the MOSI (I can see it, but it's inverted.)
my SS pin goes high.
throw in a delay of 1 second.

I've have had a 74HC244 connected to level shift from the 5vdc Mega2560 to the 3.3vdc minus the MISO pin. I've used a 74HC04 hex inverter minus the MISO pin and finally I tried voltage dividers minus the MISO pin.

If I directly control the pins I can get them to light LEDs in sequence with a delay (just making sure the pin isn't damaged.) but the MOSI is always inverted compared to the tutorials and what I've read. Nothing I've read so far says "the MOSI pin has to be inverted with external components."

My next step is to pour over the ATMEGA2560 datasheet in the hopes i'm just a bonehead and I'm missing something simple and hopefully someone here can educate me as to what I'm not setting up properly.

Feel free to flog and bash me if it really is something stupid I'm doing wrong or not paying attention to.

Thanks in advance,

Freezerburn

Feel free to flog and bash me if it really is something stupid I'm doing wrong or not paying attention to.

I always wonder about people that post in the Programming forum, but post no code. Makes me wonder whether they really want help, or just want to complain.

Yes, I imagine code would help... I'm not complaining at all, there isn't anything to complain about. Just looking for a little guidance to see if I'm not setting up SPI correctly or the MOSI output is inverted as a feature and needs to be corrected with external components.

There are some I2C functions read / write / test functions that I've commented out that I didn't include as well.

// ******************** Includes
#include <SPI.h>							// For SPI bus.
#include <Wire.h>                     				// For I2C bus.
#include <LiquidCrystal.h>            				// For 16x2 LCD Displays.

// ******************** Definitions
#define baProm0 0x50    					// 64kb EEPROM IC (24LC512) 1010000 = 0x50 address on I2C bus.
#define baProm1 0x51						// 64kb EEPROM IC (24LC512) 1010001 = 0x51 address on I2C bus.
#define baProm2 0x52						// 64kb EEPROM IC (24LC512) 1010010 = 0x52 address on I2C bus.
#define baProm3 0x53						// 64kb EEPROM IC (25LC512) 1010011 = 0x53 address on I2C bus.

#define spiMISO	0x32						// SPI MISO (pin 50).
#define spiMOSI	0x33						// SPI MOSI (pin 51).
#define spiCLK 0x34						// SPI CLK (pin 52).
#define spiSS 0x35						// Default SPI SS (pin 53) on Mega 2560.
#define ssRAM0 0x2C						// SS pin used for SPI RAM IC.

#define READram 0b00000011				// Read command for 32kb RAM IC (23K256) on SPI bus.
#define WRITEram 0b00000010				// Write command for 32kb RAM IC (23K256) on SPI bus.
#define RDSRram 0b00000101				// Read STATUS register for 32kb RAM IC (23K256) on SPI bus.
#define WRSRram 0b00000001				// Write STATUS register for 32kb RAM IC (23K256) on SPI bus.

// ******************** Variables
byte i2cdata=0; 							// Variable for data going in and out to EERPROMS on I2C bus.

byte spidata=1;							// Variable for data going in and out to RAM on SPI bus.

// ******************** Library Inits
LiquidCrystal lcd(12, 11, 10, 9, 8, 7); 

// ******************** Setup
void setup()
	{
	Serial.begin(9600); 					// For serial monitor output in Arduino IDE.
	
	Wire.begin();   						// Init for I2C.

	pinMode(spiMISO, INPUT);
	digitalWrite(spiMISO, LOW);
	
	pinMode(spiMOSI, OUTPUT);
	digitalWrite(spiMOSI, LOW);
	
	pinMode(spiCLK, OUTPUT);
	digitalWrite(spiCLK, LOW);
	
	pinMode(spiSS, OUTPUT);
	digitalWrite(spiSS, HIGH);				// Digi I/O 53 SS/CS high.
	
	pinMode(ssRAM0, OUTPUT);				// Digi I/O 53 SS/CS set to output.
	digitalWrite(ssRAM0, HIGH);
	
	SPI.setClockDivider(SPI_CLOCK_DIV128);		// Divide SCK by 128.
	SPI.setDataMode(SPI_MODE0);
	SPI.begin(); 						// Init for SPI.	
	  	
	lcd.begin(16,2);						// Init for LiquidCrystal (16 chars x 2 lines).    
	lcd.clear();							// Clear LCD.
	lcd.setCursor(0,0);					// Set cursor Position 0, Line 0.
	lcd.print(" Project:  Soma ");						
	lcd.setCursor(0,1);					// Set cursor Position 1, Line 1.
	lcd.print("    (c) 2012    ");
	delay(1000);					
	lcd.clear();							// Clear LCD.
	}

//******************** Main Loop 
void loop()
	{
	digitalWrite(ssRAM0, LOW);
	SPI.transfer(0b01010101);
	delay(100);
	digitalWrite(ssRAM0, HIGH);
	delay(100);
        }

freezerburn:
I'm just transferring "0b10101010" out of the MOSI (I can see it, but it's inverted.)

You say that here....

but then when you posted your code it has:

freezerburn:

	SPI.transfer(0b01010101);

So which one are you looking for?

I typed it wrong.

The actual data being transferred is inconsequential though.

The issue I'm experiencing is that the MOSI output is in fact outputting something, it's just inverted.

When I probe with a scope what I expected to see was the trace starting low and going by my example data was a trace with four square waves from 0v to 5v.

What I'm actually seeing with the scope is a trace at a 5v and produces four square waves from 5v to 0v.

For example when nothing is on the line, the output of MOSI is high, I'd expect it to be a high impedance zero.

So this has me thinking that there is a register that is not set right, but I've set the 4 data modes in code and the MOSI data is inverted in the SPI library, and now I'm trying to implement SPI without using the library at all by assigning values to the proper registers directly.

Or there is an anomaly with the OSEPP Mega 2560.

EDIT***

Also the OSEPP Mega 2560 doesn't use the same method to create a usb to serial port (802u?) that the Arduino Mega 2560 uses. The OSEPP board uses and FTDI chip. I wonder if that has something to do with it...

I'm also going to make a new sketch that only works with the SPI library to see what I get.

freezerburn:
When I probe with a scope what I expected to see was the trace starting low and going by my example data was a trace with four square waves from 0v to 5v. For example when nothing is on the line, the output of MOSI is high, I'd expect it to be a high impedance zero.

That is a faulty assumption. High Impedance can be anything. In fact when High-Z the pin would be floating. The ATmega likely uses the pin's internal pull-up resistor when going High-Z to keep the pin from floating which means it'll be high when idle.

freezerburn:
Or there is an anomaly with the OSEPP Mega 2560.

It uses the same processor as "official" arduinos so this is not likely.

I'm attaching two files. The first one is your code writing a b01010101.
The pin starts high and the first bit is a 0, followed by four 1s. The last 1 stays high since it is the last bit to be shifted out.
So I am seeing exactly what I would expect.

The second file is your code writing b10101010
Here you see the pin starting high with the first bit being a 1, followed by 3 more 1s and a 0. The last transition seen is the pin being pulled high after going high-Z.

01010101.bmp (146 KB)

10101010.bmp (146 KB)

Here's one more screen shot. Again, your code writing b10101010. (Your code with the LCD stuff removed).

I connected channel two as SCLK to make it clear that the rising edges are clocking out the values exactly as they should.

1010_w_clk.bmp (146 KB)

Very much solved then...

Your scope screen shots confirm that I am in fact very wrong in my assumption of what the wave form should look like.

The wave form you show looks just like mine...

Thank you very much for your time and effort! So now I know that the hardware is functioning as intended.

Now to figure out why I can't write to and read from a 23K256 IC.

Once again, thank you. My overall problem isn't solved, but I was trying to solve it by going in the wrong direction altogether.

freezerburn:
Once again, thank you. My overall problem isn't solved, but I was trying to solve it by going in the wrong direction altogether.

That is what usually happens.[/quote]

freezerburn:
Now to figure out why I can't write to and read from a 23K256 IC.

According to this data sheet, http://ww1.microchip.com/downloads/en/DeviceDoc/22100F.pdf, the 23K256 has a VCC of 3.3V. Max VCC is 4.5V. Are you driving this 3V3 device with 5V I/O? It doesn't not appear to be tolerant of 5V, at all.

I've used a 7404, 74244 of various types, LS, HC, HCT with current limiting resistors, powered by 5v if I had to, or 3.3v if the device would allow it (some devices tolerated a very low supply voltage according to the data sheets.)

My most recent attempt was using a voltage divider circuit for each SPI output (except the MISO I fed that directly to the Mega 2560. To the best of my knowledge at no point did 5v directly encounter the 23K256 IC.

I made a series of definitions for the read, write, read SR, write SR.

Per the various tutorials that exist on the web my order of operation is

the hold pin is held high.
transition the devices CS pin from high to low.
from MOSI to the SI pin shift in 8 bits that equal an instruction.
from MOSI to the SI pin shift in 16 bits that equal the memory address I want to write to or read from depending on the initial command.
conduct another "SPI.transfer(dataout)" out if it's a write or "data = SPI.transfer(0xFF)" if it's a read.
transition the devices CS pin from low to high.

So i'd write data to the device then Serial.print(data) that data just to confirm what I sent... "A" for example.
Then I'd read from the device and Serial.print(data) that was read. typically the symbol received was a "0" or "y" with two dots on top.

So obviously I'm doing something wrong there as well... my first impression (which we've determined I was wrong about) was that SPI was configured incorrectly and the MOSI wave form was inverted.)

Maybe my pinout is incorrect, MOSI pin to SI pin, and SO pin to MISO pin, SS pin to CS pin, CLK pin to CLK pin and the hold pin held high. Aside from Vss and Vcc that's all the pins.

I'm rebuilding the circuit on the breadboard using voltage dividers again. The actual IC is powered from the MEGA 2560's 3v3 supply.
Maybe my voltage divider circuit used resistor values that were too high and really limited the current (4k7, and 10k). The voltage divider circuit gave me a voltage of about 3.40+/-.

As long as I know the Mega2560 is function properly, and the SPI code is correct, assuming 1 of the 4 23K256 ICs I have isn't damage then it's my circuit that needs work.

Half the battle was finding out that the problems was NOT the Mega 2560, the SPI library (and implementation,) or the circuit.

Following the tutorials and reading the datasheet for the 23K256 everything seemed to be fine...

The problem:

spidata = SPI.transfer(0f00);
Serial.println(spidata); <-------------- PROBLEM

The solution:

spidata = SPI.transfer(0f00);
Serial.println(spidata, BIN); <-------------- PROBLEM...

8 + hours for three letters...

Cheers James, the assistance you gave helped a great deal in pointing me in the right direction.

freezerburn:
spidata = SPI.transfer(0f00);

Was that a typo? I dont understand what "0f00" is suppose to mean.

I'm surprised the fix involved the Serial. Was it just that the data you saw on the Serial Monitor didn't match what you expected to see?

yes, had to be a typo or a mental slip from working with Python "foo" or "bar" being used as names for example functions or variables in example code.

it should have read 0x00 instead of 0f00.

I "hoped" to see on the serial monitor the equivalent ASCII symbol for the 8 bits that were stored in my spidata variable.

If the variable contained 0x23 I'd like to have seen '#', or 0x2A to see a '+'.

I would have been happy with seeing anything except a ' ÿ ' which is what was printed no matter what data I tried to write then read to the ram device on the SPI bus.

Maybe something else was wrong at the time, and the confidence of know the problem wasn't X, Y or Z helped...

Either way, problem solved, working code snippet printed, example schematic drawn, and both stored nicely in a sheet protector in my new "Arduino" binder.

Thanks again!