|
|
View previous topic :: View next topic |
Author |
Message |
MotronixGS
Joined: 13 Jul 2011 Posts: 19
|
Driver L6470 |
Posted: Tue Nov 26, 2013 3:20 am |
|
|
Hello everybody,
I am developing a library for a l6470 (Datasheet: http://www.st.com/web/en/resource/technical/document/datasheet/CD00255075.pdf ), a motor driver which use spi. At first, I am trying to read a register, for example STATUS and ADC_OUT registers. The board is this: https://www.sparkfun.com/products/10859
I think my connections are ok, because are the same for others spi peripherals.
On the other hand, the page 58 explains how get a param (using 0b00100000 mask, I suppose mask | register_addres), but to get status register I must send a 0b11010000(page 64), contrary to mask to get a register.
This is my first code:
//Status.
Code: | unsigned int16 GetStatusL6470(){
unsigned int8 temp1;
unsigned int8 temp2;
CS_L6470 = 0;
spi_write(0xD0);
temp1 = spi_read(0);
temp2 = spi_read(0);
CS_L6470 = 1;
return (temp1<<8) | temp2;
}
|
//ADC_OUT
Code: |
unsigned int16 GetParamL6470(){
unsigned int8 temp1;
unsigned int8 temp2;
CS_L6470 = 0;
spi_write(0b00110010);
temp1 = spi_read(0);
temp2 = spi_read(0);
CS_L6470 = 1;
return ((temp1<<8) | temp2);
}
|
Is it ok?
Regards, |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Tue Nov 26, 2013 4:32 am |
|
|
What SPI mode are you using?.
Having to send a wrong value, almost certainly means you are not clocking on the edge the chip expects, so it is reading different values to what you think.....
Note that the clock idles _high_ for this device. It's output is generated on the falling edge of clock, and can then be read by the master, and it reads its input on the rising edge. This is CPOL=1, CPHA=1. Mode 3.
As a general comment, look in the manual at make8, and make16. These make assembling the returns (and sending data when you get this far), easier and quicker. There is a potential problem with your returns, from not using this. 8bit integer<<8, gives nothing. You are rotating an 8bit integer, _as_ an 8bit integer, so there is nowhere for the extra bits to go to. To use a rotation like this, you need to cast the value up to an int16, before performing the rotation. Better to use the make16, which inherently generates a 16bit value.
Best Wishes |
|
|
MotronixGS
Joined: 13 Jul 2011 Posts: 19
|
|
Posted: Tue Nov 26, 2013 4:57 am |
|
|
Thank you for your reply.
Yes, I use spi mode 3. In accordance with make16, you are right, I made a big mistake!!
Anyway I still read a "0" in the registers (STATUS, ADC_OUT, KVAL(first set, later read)) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Tue Nov 26, 2013 8:37 am |
|
|
You don't say what PIC clock rate you are using?. There is a 350nSec setup time required between CS dropping and starting sending via SPI. Unless you are running at a low CPU clock, you will need to add some cycles delay to meet this. Then also max SPI rate 5MHz. Again the CS needs to be held low for 800nSec _after_ the SPI finishes.
Best Wishes |
|
|
MotronixGS
Joined: 13 Jul 2011 Posts: 19
|
|
Posted: Wed Nov 27, 2013 4:05 am |
|
|
Sure! I solved it. My clock is 8Mhz, so I used a secondary prescaler 1:2, but the problem persists. With this function:
Code: | unsigned int8 GetParamL6470(){
unsigned int8 temp1=0;
unsigned int8 temp2=0;
unsigned int8 temp3=0;
CS_L6470 = 0;
delay_us(1);
spi_write(0b00101011); //KVAL_ACC(0x0B) | GET_RESGISTER(0x20)
temp1 = spi_read(0);
CS_L6470 = 1;
delay_us(1);
return temp1;
} |
This return 0x2B, that is the address to read the register (the number that I write in spi buffer)
Thanks and regards, |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Nov 27, 2013 5:22 am |
|
|
That would do.
You need:
Code: |
unsigned int8 GetParamL6470(){
unsigned int8 temp1=0;
unsigned int8 temp2=0;
unsigned int8 temp3=0;
int8 dummy;
CS_L6470 = 0;
delay_us(1);
dummy=spi_read(0b00101011); //KVAL_ACC(0x0B) | GET_RESGISTER(0x20)
temp1 = spi_read(0);
CS_L6470 = 1;
delay_us(1);
return temp1;
}
|
The point is that an spi_write, returns _immediately_. The value at this point is loaded to the output register, and starts sending.
If you follow this with an spi_read, the value in the write register will be returned (this is documented). At this point the byte hasn't yet finished being sent!....
a 'dummy read', forces the write to complete, and then reads the return (garbage for the first byte).
One of the delights of SPI, is understanding when the byte actually sends or receives....
Best Wishes |
|
|
MotronixGS
Joined: 13 Jul 2011 Posts: 19
|
|
Posted: Wed Nov 27, 2013 7:21 am |
|
|
Thank you so much for your advice, but the problem remains :(, I receive the address that I send |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Nov 27, 2013 7:36 am |
|
|
might be time to post a small,complete program so we can help debug.
there might be 'something' else going on that we can't see....
hth
jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Nov 27, 2013 8:31 am |
|
|
Yes, and particularly what compiler version, and what chip. There are a significant number of SPI errata, and some compiler versions also have problems...
Best Wishes |
|
|
MotronixGS
Joined: 13 Jul 2011 Posts: 19
|
|
Posted: Wed Nov 27, 2013 9:09 am |
|
|
Well, I use a old version, 4.1 and I have practice with 2 differents pics (20Mhz and 8Mhz) with same results. For example, with PIC18F458 (20Mhz) (with SBC44B board) the code is:
Main:
Code: | #include <18F458.h>
#fuses HS, NOWDT
#use delay(clock=20000000)
//#use fast_io(b) //Optimizo E/S del PORTB
//#use fast_io(c)
#build(reset=0x200)
#build(interrupt=0x208)
#org 0x0000,0x01ff
void bootloader() {
#asm
nop
#endasm
}
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
#define CS_L6470 PIN_D4
//#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, STREAM=STREAM_UART)
//#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, ERRORS)
#use spi(DI=PIN_C4, DO=PIN_C5, CLK=PIN_C3, BITS=8) //#use I2C(MULTI_MASTER,sda=RTC_SDA, scl=RTC_SCL)
float datoF = 0;
#include <LCD2.c>
#include <l6470_driver.c>
void main()
{
set_tris_B(0b11111111);
set_tris_C(0b10000011); //TX como salida y RX como entrada
set_tris_D(0b00000000);
//set_tris_E(0b111);
//Interrupciones en el puerto B para apretar botones del DEV16T
//port_b_pullups(TRUE);
setup_spi(SPI_MASTER|SPI_H_TO_L|SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);
lcd_init();
delay_ms(2);
initL6470();
while(1)
{
lcd_gotoxy(1,1);
printf(lcd_putc, "%u",GetParamL6470());
delay_ms(1000);
}
} |
The l6470 library:
Code: | void initL6470(){
output_bit(PIN_D4, 1);
}
unsigned int8 GetParamL6470(){
unsigned int8 temp1=0;
unsigned int8 temp2=0;
unsigned int8 temp3=0;
int8 dummy;
output_bit(PIN_D4, 0);
delay_us(1);
dummy = spi_read(0b00101011); //KVAL_ACC(0x0B) | GET_RESGISTER(0x20)
temp1 = spi_read(0);
delay_ms(200);
output_bit(PIN_D4, 1);
delay_us(1);
return temp1;
} |
So the output is 0x43...
Regards!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Nov 27, 2013 10:45 am |
|
|
Versions are x.xxx 3digits after the decimal. Look at the top of the .lst file if you don't know what version you have. It matters, there are over 100 'sub versions' for V4...
Best Wishes |
|
|
MotronixGS
Joined: 13 Jul 2011 Posts: 19
|
|
Posted: Wed Nov 27, 2013 2:31 pm |
|
|
Sorry, my version is v4.104. I have used this for 8bits microcontroller and I have never had problems |
|
|
MotronixGS
Joined: 13 Jul 2011 Posts: 19
|
|
Posted: Thu Nov 28, 2013 2:31 am |
|
|
I use this board: https://www.sparkfun.com/products/10859 . My connections are:
MASTER-------------SLAVE (L6470)
==========================
5V--------------------5V
5V--------------------SW
5V--------------------STBY
SDI (RC4)-----------SDO
SDO(RC5)-----------SDI
SCK(RC3)-----------SCK
12V-------------------(Vs in schematic, V+ in printed board)
Motor-----------------01B,01A,02B, 02A (Different names schematic vs board) |
|
|
MotronixGS
Joined: 13 Jul 2011 Posts: 19
|
|
Posted: Thu Nov 28, 2013 6:08 am |
|
|
Well, it seems work. I generate a toggle in CS every SPI function, such as:
Code: | unsigned int16 GetConfigL6470(){
unsigned int8 temp1=0;
unsigned int8 temp2=0;
unsigned int16 temp3=0;
unsigned int8 dummy;
output_bit(PIN_D4, 0);
delay_us(1);
dummy = spi_read(0x18 | 0x20); //KVAL_ACC(0x0B) | GET_RESGISTER(0x20)
output_bit(PIN_D4, 1);
delay_us(1);
output_bit(PIN_D4, 0);
delay_us(1);
temp1 = spi_read(0);
output_bit(PIN_D4, 1);
delay_us(1);
output_bit(PIN_D4, 0);
delay_us(1);
temp2 = spi_read(0);
output_bit(PIN_D4, 1);
delay_us(1);
temp3 = make16(temp1,temp2);
return temp3;
} |
I have never seen this in a SPI. Furthermore, page 38 datasheet shows a timings diagram, CS is low while the transmission is active. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Thu Nov 28, 2013 7:53 am |
|
|
MotronixGS wrote: | page 38 datasheet shows a timings diagram, CS is low while the transmission is active. |
This is typical for SPI. CS is low for the entire transaction for most devices out there. |
|
|
|
|
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
|