Go Down

Topic: starting with spi questions about code (Read 1 time) previous topic - next topic


Mar 11, 2008, 07:09 am Last Edit: Mar 11, 2008, 04:37 pm by unsped Reason: 1
im trying to interface a winbond chipcorder isd1700 via spi, i have it working with standalone buttons right now so i know it works, i have the spi lines hooked to the arduino, and this is sorta what i have so far.

can i use the opcodes like i am? do i need to do anything special for the hex codes, should i convert them to decimal? any hints on something im doing blatantly wrong?

i couldn't find a spi speed in the manual so i assumed the lowest

the datasheet specified
PU then CLR_INT then PLAY as a sample execution sequence
each of these command bytes is to be followed by a 0x00 value

the code doesn't work as is, but i don't exactly expect it to either. looking for some advice so i can work on it some more tommorrow thanks!

if your a masochist, here is the datasheet
most of the spi stuff starts on page 31

Code: [Select]
#define DATAOUT     4   //mosi
#define DATAIN      5   //miso
#define SPICLOCK    6   //sck
#define SLAVESELECT 7   //ss

#define PU          0x01
#define STOP        0x02
#define RESET       0x03
#define CLR_INT     0x04
#define RD_STATUS   0x05
#define RD_PLAY_PTR 0x06
#define PD          0x07
#define RD_REC_PTR  0x08
#define DEVID       0x09
#define PLAY        0x40
#define REC         0x41
#define ERASE       0x42
#define G_ERASE     0x43
#define RD_APC      0x44
#define WR_APC1     0x45
#define WR_APC2     0x65
#define WR_NVCFG    0x46
#define LD_NVCFG    0x47
#define FWD         0x48
#define CHK_MEM     0x49
#define EXTCLK      0x4A
#define SET_PLAY    0x49
#define SET_REC     0x81
#define SET_ERASE   0x82

void setup() {

 byte clr;
 pinMode(DATAIN, INPUT);
 digitalWrite(SLAVESELECT,HIGH); //disable device  
 SPCR = B01111111; //data lsb, clock high when idle, samples on falling

void loop() {
 spi_transfer(PU); // power up
 spi_transfer(0x00); // data byte
 spi_transfer(CLR_INT); // clear interupt and eom bit
 spi_transfer(0x00); // data byte

 spi_transfer(PLAY); // play
 spi_transfer(0x00); // data byte


char spi_transfer(volatile char data)
 SPDR = data;                    // Start the transmission
 while (!(SPSR & (1<<SPIF)))     // Wait for the end of the transmission
 return SPDR;                    // return the received byte


The hardware SPI, which you are attempting to work, only works on specific pins: SS is pin 10, MOSI is pin 11, MISO is pin 12, SCK is 13. That's a start, at least!


My hangup was this: SPI has four modes determined by two parameters, clock polarity (CPOL) and clock phase (CPHA).  The standard doesn't really specify which to use, so different vendors come up with different ways of doing it.  Of course #4 was the one that finally worked for my device.

As A_square pointed out, you've got to use the specified pins for MOSI, MISO, and CLK.  SPI is a bus, so if the peripherals are well behaved you can put multiple devices on these three lines (each will need its own slave select, of course).



Mar 12, 2008, 02:48 am Last Edit: Mar 12, 2008, 02:49 am by unsped Reason: 1
oddly enough the code does work once i changed the spi pins to the correct ones.

also the PU command needed to be put in setup for the loop to work. once i get everything working ill be sure to post a howto.

thanks all

to put multiple spi devices on the same bus wouldn't they need to all use the same SPCR settings?


Mar 12, 2008, 06:40 am Last Edit: Mar 12, 2008, 11:57 am by unsped Reason: 1
regarding how to read status registers on the chipcorder, and im assuming other spi devices....

alright i think i have an idea of how it works miso goes in SPDR after each SPDR load so you put a byte into spdr and it outputs a byte into spdr from the spi device now... lets say the spi device puts 3 bytes into spdr for a command spdr only appears to hold a single byte, so how do we read all 3 bytes? the spi commands im noticing have 0x00 bytes beyond the command byte the number of these 0x00 bytes seem to conform to how many miso bytes the command returns so at first glance the extra 0x00 for each command seem like nonsense because they are null values however what it does is give you seperate spi_transfer calls, each returning a byte so while RD_STATUS is 0x05,0x00,0x00 its 3 different spi_transfers, and 3 different MISO states so you read each miso value after each spi transfer, then you can put them together to get the full miso stream so for my chip corder, when i send a play command, then continue checking the 3rd returned byte of the rd_status spi command while the chip is playing, the 3rd bit of the 3rd byte (last 0x00 transfer of RD_STATUS) will be 1, it will go to 0 when the chip is done (actually it will go from 00100000 to 10000000 as the first bit is the ready flag .. what you should be looking for anyways).

two things don't help figuring this out, serial.print's deletion of leading zeros, and serial.prints erratic behaviour while the circuit is playing the speaker (need to track this down) i assume its either power draw or noise. bitwise math is what youll need to do to check status ... for instance you dont want to start another spi command until the play command has completed which you don't know unless you check the regsiter... so you have to keep cycling through RD_STATUS spi commands until the 3rd byte is what you want.

Go Up