|
|
View previous topic :: View next topic |
Author |
Message |
mka879
Joined: 30 Oct 2015 Posts: 34
|
SPI Problem with CS5463(related to FEB 2009 thread) |
Posted: Thu Dec 03, 2015 1:05 am |
|
|
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: 19552
|
|
Posted: Thu Dec 03, 2015 2:15 am |
|
|
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
|
|
Posted: Thu Dec 03, 2015 4:20 am |
|
|
Hmmm.... how I missed the register number 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: 19552
|
|
Posted: Thu Dec 03, 2015 4:21 am |
|
|
You need to raise CS after you have sent the initialisation..... |
|
|
mka879
Joined: 30 Oct 2015 Posts: 34
|
|
Posted: Thu Dec 03, 2015 5:46 am |
|
|
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: 19552
|
|
Posted: Fri Dec 04, 2015 3:19 am |
|
|
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
|
|
Posted: Fri Dec 04, 2015 4:34 am |
|
|
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: 19552
|
|
Posted: Fri Dec 04, 2015 4:50 am |
|
|
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
|
|
Posted: Fri Dec 04, 2015 5:11 am |
|
|
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
|
|
Posted: Thu Dec 17, 2015 6:11 am |
|
|
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
|
|
Posted: Thu Dec 17, 2015 6:13 am |
|
|
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
|
|
Posted: Thu Dec 17, 2015 12:42 pm |
|
|
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: 9246 Location: Greensville,Ontario
|
|
Posted: Thu Dec 17, 2015 4:14 pm |
|
|
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
|
|
Posted: Sat Dec 19, 2015 12:24 am |
|
|
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
|
|
|
|
|
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
|