CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Another SPI problem (CS5463)
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 08, 2009 6:08 pm     Reply with quote

If your code doesn't work, then try this one. This should display the
temperature (about 24 degrees C, at room temperature). By looking
at the CS5463 data sheet and AN220 from Microchip, I think this code
has a chance to work.
Code:

#include <18F4520.H>
#fuses HS,NOWDT,NOBROWNOUT,PUT,NOLVP
#use delay(clock=20000000)

#include "Lcd2.c"

#define CS     PIN_A5
#define RESET  PIN_E2

#define CS5463_CONFIG_REG  0
#define CS5463_TEMP_REG    19

// SPI modes
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

//--------------------------------
void CS5463_write_command(int8 command)
{
output_low(CS);
spi_write(command);
output_high(CS);
}

//---------------------------------
void CS5463_write_reg(int8 reg, int8 msb, int8 mid, int8 lsb)
{
output_low(CS);
spi_write((reg << 1) | 0x40);   // OR with Write bit
spi_write(msb);
spi_write(mid);
spi_write(lsb);
output_high(CS);
}

//---------------------------------
int32 CS5463_read_reg(int8 reg)
{
int8 msb, mid, lsb;
int32 retval;

output_low(CS);
spi_write(reg << 1);
msb = spi_read(0x00);
mid = spi_read(0x00);
lsb = spi_read(0x00);
output_high(CS);

retval = make32(0, msb, mid, lsb);

return(retval);
}


//===============================
void main()
{
int32 temp32;
int8 temp8;

output_high(CS);
output_high(RESET);

delay_ms(100);  // CS5463 osc start-up time is 60 ms typ.

setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);

lcd_init();

while(1)
  {
   temp32 = CS5463_read_reg(CS5463_TEMP_REG);
   temp8 = make8(temp32, 3);  // Get upper byte of temp32
   printf(lcd_putc, "\f Temp = %d", temp8);
   delay_ms(500);
  }

}
                 
matt1eg



Joined: 05 Feb 2009
Posts: 14

View user's profile Send private message

PostPosted: Sun Feb 08, 2009 6:49 pm     Reply with quote

Thats superb thanks very much. Wasn't expecting that amount of help Shocked Very Happy .

Will try that out tomorrow as well. If that works then least I know there are no hardware errors. Then I can at least work on my code knowing only it is wrong if nothing happens (stubborness and small sense of acheivement as my motivation).

I may resort to modifying yours though, I only have so much hair left to pull out, that is of course if you don't mind me using it as a base.
matt1eg



Joined: 05 Feb 2009
Posts: 14

View user's profile Send private message

PostPosted: Mon Feb 09, 2009 3:01 pm     Reply with quote

Hi

Tested both versions today, yours worked with a little bit of moding. I changed
Quote:
Code:
int32 CS5463_read_reg(int8 reg)
{
int8 msb, mid, lsb;
int32 retval;

output_low(CS);
spi_write(reg << 1);
msb = spi_read(0xFF);
mid = spi_read(0xFF);
lsb = spi_read(0xFF);
output_high(CS);

retval = make32(0, msb, mid, lsb);

return(retval);
}


The 0xFF are sync commands that are required when no data is to be written. When reading the temp register it seemed to go a bit weird though. Get a value of -128 for MSB which corresponds to 0 degrees C?! (I'm assuming so as anyway as its a 2's complement and MSB is 0b1000000 and other 2 bytes are 0x00). Reading other registers that have default non zero values produces correct results so I'm not sure why its not measuring the temp but its not really an issue wasn't planning on using it.

Using your code as an example I simplified my own to just do a read and with some modifying got it to it as well but its a bit temperamental. Going to start afresh and with my own to tidy it up and attempt to use some ISRs. Hopefully all will be good.

Thanks again for your help
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 09, 2009 3:25 pm     Reply with quote

I think my byte extraction in that sample program is wrong:
Quote:
temp8 = make8(temp32, 3); // Get upper byte of temp32

The topmost byte is always 0x00, in the returned value from the
CS5463_read_reg() routine. Because the CS5463 returns a 24-bit
value (and it's right justified), the 2nd from the top in the return value
is the one that needs to be extracted. Example:
Code:
temp8 = make8(temp32, 2);  // Get byte 2 (of bytes 0-3) of temp32
matt1eg



Joined: 05 Feb 2009
Posts: 14

View user's profile Send private message

PostPosted: Mon Feb 09, 2009 3:38 pm     Reply with quote

Oh yeah forgot to mention that I noticed that. Was just getting 0 for a while but then noticed it, I have it as 2 now, this is when I get -128.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 09, 2009 3:42 pm     Reply with quote

Print the entire int32 returned value in Hex and see what you get.
Here are the required changes to do that:
Quote:

temp32 = CS5463_read_reg(CS5463_TEMP_REG);
// temp8 = make8(temp32, 3); // Get upper byte of temp32
printf(lcd_putc, "\f Temp32 = %LX", temp32);
matt1eg



Joined: 05 Feb 2009
Posts: 14

View user's profile Send private message

PostPosted: Mon Feb 09, 2009 3:58 pm     Reply with quote

I get 000000. It's either really cold here and I haven't noticed or its not measuring the temperature.

One other thing I did to modify your code was to send a command to start conversions. In the data sheet it said that it measures the temperature during continuous conversions.
Quote:
Code:
while(1)
  {
   CS5463_write_command(0xE8);
   temp32 = CS5463_read_reg(CS5463_TEMP_REG);
   //temp8 = make8(temp32, 0);  // Get upper byte of temp32
   //printf(lcd_putc, "\f Temp = %d", temp8); 
   printf(lcd_putc, "\f Temp32 = %LX", temp32);
   delay_ms(500);
  }

}


It also says
Quote:
Once a temperature characterization
is performed, the temperature sensor can then be
utilized to assist in compensating for temperature drift.


I am unsure if this means that it for that particular use it needs characterization(which I assume means setting the temp offset) or if this is needed for any measurements to be done?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 09, 2009 4:13 pm     Reply with quote

It might be that temperature data is only available as a side effect of
some other operation (such as reading or using the ADC). I don't have
time to research this now. I've got to do some work for the company.
matt1eg



Joined: 05 Feb 2009
Posts: 14

View user's profile Send private message

PostPosted: Mon Feb 09, 2009 4:17 pm     Reply with quote

Thats ok you don't have to worry I will see what happens when I get it doing proper calculations and post an update later this week.
spelltwister



Joined: 12 Feb 2009
Posts: 1

View user's profile Send private message

PostPosted: Thu Feb 12, 2009 10:25 am     Reply with quote

Greetings,

I believe I have followed everything done here and am still having problems :/ I have scoped all values that are being sent from the uC (HCS08QG) and they are correct. However, I am only getting 0 from the cirrus chip. I had RESET float and tied it high. This got rid of the error of random pulses being sent out of the cirrus chip. Thx ;D

I've tried using the auto Chip Select feature and manual chip select feature to drive the CS pin high after each byte and I've tried driving it high after each operation (cs_low, read, 3 writes, cs_high). I have the signal coming in at about 4464 Hz. I have also tried running at 1 MHz. Same results.

Summary of what is done:
Code:

void reset_spi(){
  write_spid(0xFF);
  write_spid(0xFF);
  write_spid(0xFF);
  write_spid(0xFE);
}

char read_spid(void){
 write_spid(0xFF);
 while(!(SPIS & 0x80));//wait for full buffer
 return SPID;
}

void page_and_read_register(char page, char ra, char* buff){
if(page != cur_page){
     change_page(page);
     cur_page = page;
 }
 write_spid(ra<<1);//which page to read
 buff[0] = read_spid();//SYNC0
 buff[1] = read_spid();
 buff[2] = read_spid();
}

main(){
int counter = 0; //look at many registers
char data[5];

reset_spi();
write_command(0xE4);//continuous conversions

while(1){
  page_and_read_register(0, counter, data);
  if(counter++ >= 15)//cycle thru registers 0 - 15 to see if anything has data
      counter = 0;
}


I have tried setting the register I'm reading to V_Instant, Temp, config, etc and they all give back the same nothingness. I am using a logic analyzer also to see the waves leaving and entering the cirrus chip and uC. The waves leaving the uC see OK, but the cirrus chip seems like it's doing nothing. I tested the clock on the cirrus chip and it correctly reports 4.096MHz.

Any help is greatly appreciated!!![/code]
matt1eg



Joined: 05 Feb 2009
Posts: 14

View user's profile Send private message

PostPosted: Thu Feb 12, 2009 12:05 pm     Reply with quote

Hi

I'm no expert but looking through your code I can see some problems, although I have only worked with PICs and CCS compiler, I am not familiar with uC 'HCS08QG' at all, and are you using CCS compiler? If not My advice may not suit your application completely.

Quote:
Code:
write_command(0xE4);//continuous conversions

will not do continuous conversions you need 0xE8. Also here
Quote:
Code:
write_spid(ra<<1);//which page to read
 buff[0] = read_spid();//SYNC0
 buff[1] = read_spid();
 buff[2] = read_spid();

you need to send the SYNC1 command where as you are not sending anything.

I would just start by trying to read one register at a time no cycling through them.

Where in your code are storing the bytes you have read?

I would of also said that you need to set up the SPI. In mine you can see I use

Quote:
Code:
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);

where the SPI_Mode is defined by
Quote:
Code:
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

You need to make sure data is being clocked in and out at the times. The timing diagram in the CS5463 datasheet shows you the timings.

This
Quote:
Code:
void reset_spi(){
  write_spid(0xFF);
  write_spid(0xFF);
  write_spid(0xFF);
  write_spid(0xFE);


won't reset its an attempt to reinitialise but you need to drive CS pin high then low with the above code to do this. You need to have a seperate reset and cs pin. You have said that you use the reset pin thats good I use this at start up and then I just use CS low to initialise comms then when I'm done drive it high.
I do this after each command is carried out, e.g. when I do a read I set it low then do the read (write the register and read 3 bytes of data) then set it high. This works fine for me.

Like I said I am no expert but I think the pointers above should help.
avarachan



Joined: 24 Sep 2009
Posts: 3
Location: Buffalo, NY

View user's profile Send private message

CS5463 with microchip 18f67j60
PostPosted: Mon May 24, 2010 12:42 pm     Reply with quote

Hi,

I am working with the CS5463 and microchip 18f67j60. I have already gotten CS5463 working with pic 18f2620, but at 4 MHz. My new processor has a crystal of 25MHz. I can write data to the CS5463, signal looks good, I am following all the initialization, synchronization etc, as I did with 18f2620. The problem is I can't get data out from the CS5463. It always reads zero. Though, intermittently I can see a pulse on the SDO of CS5463.

Any suggestions would be greatly appreciated.

Thanks
AVC
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon May 24, 2010 1:08 pm     Reply with quote

The SPI clock from the PIC's MSSP hardware module is derived from
the oscillator of the PIC. If you increase the PIC oscillator frequency,
then you increase the SCLK frequency.

Download the CS5463 data sheet:
http://www.cirrus.com/en/pubs/proDatasheet/CS5463_F2.pdf

Look at the SPI specifications on page 11. It has a fairly low SCLK
frequency of only 2 MHz, maximum.
Quote:

Serial Port Timing

Serial Clock Frequency SCLK - - 2 MHz (Max)

If you increase your PIC frequency from 4 MHz to 25 MHz, without
changing your setup_spi() statement, you will easily create an SCLK
signal for which the frequency is too high.

To fix this, you need to change the SPI clock divisor in the setup_spi()
statement. Look in the .h file for your PIC:
Quote:
c:\program files\picc\devices\18f67j60.h

Look in this section of that file:
Quote:
// Constants used in SETUP_SPI() are:

Then choose a new divisor constant that, when divided into 25 MHz,
will give you an SCLK of 2 MHz or less. Edit your setup_spi() statement
and put in the new clock divisor.
aaronik19



Joined: 25 Apr 2011
Posts: 297

View user's profile Send private message

Design
PostPosted: Sat Jun 11, 2011 8:46 am     Reply with quote

Dear All, did you implemented the design on page 9 of the datasheet? Can you please send me the BOM because I did not find it.

Thanks in advance
aaronik19



Joined: 25 Apr 2011
Posts: 297

View user's profile Send private message

PostPosted: Thu Mar 14, 2013 8:22 am     Reply with quote

I am using the pic18f4550 with 20mhz cystal. Do. Need to connect the cpuclk pin on the cs5463(pin2) to the pic pin 13, altough i have the crystal to the PIC?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group