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

SPI Problem with CS5463(related to FEB 2009 thread)
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mka879



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

SPI Problem with CS5463(related to FEB 2009 thread)
PostPosted: Thu Dec 03, 2015 1:05 am     Reply with quote

I am using CS5463 and PIC16f877A in a project. I am getting the wrong values of register when reading using spi interface. I also used the code posted by PCM programmer in reply to the following thread

https://www.ccsinfo.com/forum/viewtopic.php?p=110600

It solved the problem of the thread originator(mat11eg) but I am still getting wrong values.

I have checked the SPI connection(PIC -> CS5463)
Pin18(SCK) -> Pin5(SCLK)
Pin16(C1) -> Pin7(CS)
Pin23(SDI) -> Pin6(SDO)
Pin24(SDO) -> Pin23(SDI)

I have also applied the modification suggested by matt1eg in the thread but the result is the same. I seriously need help.

The code is

Code:
#include <testspi.h> 

#include "flex_lcd.c"

#define CS     PIN_C1
#define RESET  PIN_D0

#define CS5463_CONFIG_REG  0
#define CS5463_TEMP_REG    19
#define CS5463_CYCLE_COUNT_REG 5
#define CS5463_PULSERATE_REG 6

// 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);
delay_ms(1000);
spi_write(command);
output_high(CS);
}

//---------------------------------
void CS5463_write_reg(int8 reg, int8 msb, int8 mid, int8 lsb)
{
output_low(CS);
delay_ms(1000);
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);
msb = spi_read(0xFF);
mid = spi_read(0xFF);
lsb = spi_read(0xFF);
output_high(CS);

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

return(mid);
}

//---------------------------------
void CS5463_initialize(void)
{
   spi_write(0xFF);
   spi_write(0xFF);
   spi_write(0xFF);
   spi_write(0xFE);
}

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

output_high(CS);
output_high(RESET);

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

setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);

CS5463_initialize();

lcd_init();

while(1)
  {
   temp32 = CS5463_read_reg(CS5463_CYCLE_COUNT_REG);
   //temp8 = make8(temp32, 3);  // Get upper byte of temp32
   printf(lcd_putc, "\f N = %lu", temp32);
   delay_ms(500);
   CS5463_initialize();
  }
}


The testspi.h looks like



Code:
#include <16F877A.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O

#use delay(crystal=20000000)


I am using PCWHD Compiler IDE version 5.015
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Thu Dec 03, 2015 2:15 am     Reply with quote

Er.

Look again at your read_register routine.

Look at the data sheet 'SDO read timing'. Read sequence is _four_ transmissions. Sends the register number, then reads the three reply bytes.
Your routine is not sending the register number....

Then the routine is meant to return the 24bit value - currently it is only returning the middle byte?.

Code:

#define LSB 0
#define MID 1
#define MSB 2
#define EMPTY 3

int32 CS5463_read_reg(int8 reg)
{
   union
   {
       int8 bytes[4];
       int32 whole;
   } joiner; //single area of memory to 'join' four bytes to make an int32

   joiner.bytes[EMPTY]=0; //clear the extra byte
   output_low(CS); //select chip
   joiner.bytes[LSB]=spi_read(reg); //send the register number - dummy return
   joiner.bytes[MSB] = spi_read(0xFF); //now read the reply - three bytes
   joiner.bytes[MID] = spi_read(0xFF); //MSB first
   joiner.bytes[LSB] = spi_read(0xFF);
   output_high(CS); //de-select

   return(joiner.whole); //er you were only returning the mid byte
}


This also shows how to use a union to join 3*8bit values into a 32bit value, without having to use temporary storage (the bytes are directly written to the locations in the final result).

You are also sending the initialise sequence, without dropping CS.....

The chip also takes time to perform it's sampling. How soon after an initialisation, is the data available?
mka879



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

PostPosted: Thu Dec 03, 2015 4:20 am     Reply with quote

Hmmm.... how I missed the register number Embarassed I have modified the code
Code:
#include <testspi.h> 

#include "flex_lcd.c"

#define CS     PIN_C1
#define RESET  PIN_D0

#define CS5463_CONFIG_REG  0
#define CS5463_TEMP_REG    19
#define CS5463_CYCLE_COUNT_REG 5
#define CS5463_PULSERATE_REG 6

// 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);
delay_ms(1000);
spi_write(command);
output_high(CS);
}

//---------------------------------
void CS5463_write_reg(int8 reg, int8 msb, int8 mid, int8 lsb)
{
output_low(CS);
delay_ms(1000);
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);
lsb = spi_read(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);
}

//---------------------------------
void CS5463_initialize(void)
{
   output_low(CS);
   spi_write(0xFF);
   spi_write(0xFF);
   spi_write(0xFF);
   spi_write(0xFE);
}

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

output_high(CS);
output_high(RESET);

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

setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);

lcd_init();

CS5463_initialize();

delay_ms(1000);

while(1)
  {
   temp32 = CS5463_read_reg(CS5463_CYCLE_COUNT_REG);
   //temp8 = make8(temp32, 3);  // Get upper byte of temp32
   printf(lcd_putc, "\f N = %lu", temp32);
   CS5463_initialize();
   delay_ms(500);
  }
}

For single byte return, I only wanted to see what was returned in the middle byte.

I added delays after initialization. The datasheet says that if spi interface somehow becomes unsynchronized with the clock then the initialization sequence is one of the 3 ways to correct the problem.

The code still runs the same way.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Thu Dec 03, 2015 4:21 am     Reply with quote

You need to raise CS after you have sent the initialisation.....
mka879



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

PostPosted: Thu Dec 03, 2015 5:46 am     Reply with quote

Ttelmah wrote:
You need to raise CS after you have sent the initialisation.....


Modified the code and also added delays to ensure that spi data is received before receiving next byte. 100ms inserted between consecutive reads is just an arbitrary value. I thought that there might be considerable capacitance between the tracks of PCB which might take long in transitions therefore added extra delay when CS is asserted and de asserted. But the result has not changed.

Here is the code.

Code:
#include <testspi.h> 

#include "flex_lcd.c"

#define CS     PIN_C1
#define RESET  PIN_D0

#define CS5463_CONFIG_REG  0
#define CS5463_TEMP_REG    19
#define CS5463_CYCLE_COUNT_REG 5
#define CS5463_PULSERATE_REG 6

// 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)

// SPI buffer address
#byte sspbuf = 0x13
//--------------------------------
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);
delay_ms(1000);
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);
delay_ms(1000);
lsb = spi_read(reg << 1);
delay_ms(100);
msb = spi_read(0xFF);
delay_ms(100);
mid = spi_read(0xFF);
delay_ms(100);
lsb = spi_read(0xFF);
delay_ms(100);
output_high(CS);
delay_ms(1000);

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

return(retval);
}

//---------------------------------
void CS5463_initialize(void)
{
   int8 temp;
   output_low(CS);
   delay_ms(1000);
   spi_write(0xFF);
   delay_ms(100);
   temp = sspbuf;
   spi_write(0xFF);
   delay_ms(100);
   temp = sspbuf;
   spi_write(0xFF);
   delay_ms(100);
   temp = sspbuf;
   spi_write(0xFE);
   delay_ms(100);
   temp = sspbuf;
   output_high(CS);
   delay_ms(1000);
}

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

output_high(CS);
output_high(RESET);

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

setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);

lcd_init();

CS5463_initialize();

delay_ms(1000);

while(1)
  {
   temp32 = CS5463_read_reg(CS5463_CYCLE_COUNT_REG);
   //temp8 = make8(temp32, 3);  // Get upper byte of temp32
   printf(lcd_putc, "\f N = %lu", temp32);
   CS5463_initialize();
   delay_ms(500);
  }
}


The datasheet can be found on the following link

http://www.mouser.com/ds/2/76/CS5463_F3-48303.pdf

Forgot to tell that PFMON pin of CS5463 has been left floating. Referring to the datasheet I understand that it only set certain bits when analog supply falls below threshold, therefore, it should not disturb read write operations.


Last edited by mka879 on Thu Dec 03, 2015 6:43 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Dec 04, 2015 3:19 am     Reply with quote

First, I note that the register number sent in the read_reg command, actually needs to be multiplied by 2. Are you doing this?.
What happens if you try the code as outlined in the original thread directly?. This is just to read the temperature, but will then prove that you are talking to the chip correctly. Until this works, stop trying to access other functions. One step at a time.
Your delays are pointless. You are clocking the bus at 312500bps. If there was a capacitance problem it would apply to this data, far before any delays get introduced....
I worry about your continuous resetting. Initialise the chip once, set it up for what is needed, and then talk to it. This chip does continuous maths on the incoming voltages, and I hate to think what the effect of keeping stopping this and restarting it is. Again look at the code you have already found.
mka879



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

PostPosted: Fri Dec 04, 2015 4:34 am     Reply with quote

For multiplication, shift operator is applied.

I tried the original code but it gives 0x00FFFFFF in the returned 32 bit number from the read routine only when RESET pin of CS5463 is pulled high from power source directly.

One observation is that when I attach reset pin of CS5463 with the microcontroller the voltage on E2(RESET) pin of microcontroller drops to 1.1V which effectively pulls CS5463 in reset. The output of the 32 bit number from read routine is 0x00000000. When I disconnect it the voltage on E2(Reset) jumps to 5V.

The code is
Code:

#include <16F877A.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)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,PARITY=N,BITS=8,STOP=1,ERRORS)
//--------------------------------
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(0xFF);
mid = spi_read(0xFF);
lsb = spi_read(0xFF);
output_high(CS);

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

return(retval);
}

//---------------------------------
void initialize_serial(void)
{
   output_low(CS);
   spi_write(0xFF);
   spi_write(0xFF);
   spi_write(0xFF);
   spi_write(0xFE);
   output_low(CS);
}

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

output_high(CS);
output_high(RESET);

output_high(pin_b7);   //initializing microcontroller
delay_ms(1000);
output_low(pin_b7);
delay_ms(1000);

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

setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);

initialize_serial();
delay_ms(1000);

//lcd_init();

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

}
There are only two changes, one is the use of serial port to display on terminal program rather than lcd and the other is 2s delay in the beginning to initialize the PIC board. Also the 7805 heats up when I directly connect RESET pin of CS5463 to 7805 output.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Dec 04, 2015 4:50 am     Reply with quote

You need to look at your hardware.

You are being given strong clues that something here is radically wrong in the behaviour of the reset pin. It's actually behaving as if either it is shorted to something else, or the chip is not being properly powered, and is being powered from the reset pin when this is taken high.

Clues like this need to be listened to.
mka879



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

PostPosted: Fri Dec 04, 2015 5:11 am     Reply with quote

Ttelmah wrote:
You need to look at your hardware.

You are being given strong clues that something here is radically wrong in the behaviour of the reset pin. It's actually behaving as if either it is shorted to something else, or the chip is not being properly powered, and is being powered from the reset pin when this is taken high.

Clues like this need to be listened to.


Thank you Ttelmah for your support. I will look into my hardware closely and will report the results.
mka879



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

PostPosted: Thu Dec 17, 2015 6:11 am     Reply with quote

Ttelmah wrote:
You need to look at your hardware.

You are being given strong clues that something here is radically wrong in the behaviour of the reset pin. It's actually behaving as if either it is shorted to something else, or the chip is not being properly powered, and is being powered from the reset pin when this is taken high.

Clues like this need to be listened to.


I prepared a separate PCB and connected it to microcontroller. Now the reset pin does not grounds and high signal remains on the reset pin. I also communicated with a slave microcontroller separately to ensure that code for spi communication is correct which was done successfully. Now the issue with CS5463 still remains the same, it gives 0 as output. The code is given below
Code:

#include <16F877A.h>
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or (PIC18) used for I/O
#use delay(crystal=20000000)

#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,PARITY=N,BITS=8,STOP=1,ERRORS)

#define CS     PIN_A5
#define RESET  PIN_B5

#define CS5463_CONFIG_REG  0
#define CS5463_TEMP_REG    19
#define CS5463_CYCLE_COUNT_REG    5

#define sync 0xFF

#bit sspbuf0 = 0x13.0
#byte sspbuf = 0x13



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

output_bit(pin_a5,0);   //slave select
     
   temp = spi_read(CS5463_CYCLE_COUNT_REG << 1);     //send read command
   delay_ms(1);
   msb = spi_read(sync);   //read msb mid and lsb by sending sync commands
   delay_ms(1);
   mid = spi_read(sync);
   delay_ms(1);
   lsb = spi_read(sync);
   delay_ms(1);
   output_high(pin_a5);

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

return(retval);
}

//===============================
void main()
{
   int32 ccr;
   output_high(RESET);
   output_high(CS);
   
   output_high(pin_b7);
   delay_ms(1000);
   output_low(pin_b7);
   delay_ms(1000);
   
   setup_spi(SPI_MASTER|SPI_SCK_IDLE_LOW|SPI_CLK_DIV_64|SPI_XMIT_H_TO_L);  //set up spi module
   
   
   
   while(TRUE)
   {
      ccr = CS5463_read_reg(CS5463_CYCLE_COUNT_REG);
      printf("Cycle Count Register = %lu\r\n",ccr);
      delay_ms(5000);
   }

}
mka879



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

PostPosted: Thu Dec 17, 2015 6:13 am     Reply with quote

Also I have noticed everyone use mode 0 but that has not worked for me. Why is that so?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Dec 17, 2015 12:42 pm     Reply with quote

Can you post a link to the schematic of your current board ?

How to post an image on the CCS forum:
Go to this website: http://postimage.org/
Upload your image. Select family safe. Then click the first button for
"Hotlink to Forum" to get a link to the image.
Then go to the CCS forum and type Ctrl-V to paste the link into a post.

If postimage.org doesn't work in your country, then use Google to find
another free image hosting site for forums.
temtronic



Joined: 01 Jul 2010
Posts: 9224
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Dec 17, 2015 4:14 pm     Reply with quote

OK, I have not read the datasheet for the peripheral so these are general comments...

One possible problem is the lack of a structured 'peripheral setup' in main().
You just set a couple control bits, flash an LED,setup SPI then loop forever expecting the data to be correct.
I'd expect the peripheral requires a 'startup sequence' of setting/resetting some bits with defined delays between these operation.
The code output_high(RESET); says to me to reset the peripheral and you keep it there. I would expect a chip 'reset' function to be a pulse, not a steady state.

Also, if this chip has programmable features you NEED to have a 'setup function' to ensure the setup registers are set properly! It is entirely possible that due to miscoding, bad timing, ?? that you've accidentally programmed the chip for a function or feature you don't want. At the very least it should reset the peripheral to 'factory defaults'. That way you KNOW what mode the peripheral is set for.


Jay
mka879



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

PostPosted: Sat Dec 19, 2015 12:24 am     Reply with quote

Link to the schematic is given below
http://img4.imagetitan.com/img.php?image=12_schematic.png

Please note that I have not included R15 and R16 in my circuit.

Va+ = 5V comes from 7805.

Vin+,Vin-,Iin+,Iin- have been left disconnected since I only wanted to read register default values before making any power calculations.

CPUCLK has also been left disconnected.

Following are the connections between CS5463 and PIC16F877A
SCL --> C3(pin18)
SDO --> C4(pin23)
SDI --> C5(pin24)
CS --> A5(pin7)
RESET --> B5(pin38)

CS5463 runs from 4MHz crystal while PIC runs from 20MHz crystal.
mka879



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

PostPosted: Sat Dec 19, 2015 12:36 am     Reply with quote

Please refer to the following link to see complete setup

http://img4.imagetitan.com/img.php?image=12_schematic1.png

12V adapter is modeled here by 12V battery.

VDD and VSS pins of microcontroller are not shown here.
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  Next
Page 1 of 2

 
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