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 support@ccsinfo.com

Driver L6470
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
MotronixGS



Joined: 13 Jul 2011
Posts: 19

View user's profile Send private message

Driver L6470
PostPosted: Tue Nov 26, 2013 3:20 am     Reply with quote

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: 19436

View user's profile Send private message

PostPosted: Tue Nov 26, 2013 4:32 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Nov 26, 2013 4:57 am     Reply with quote

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: 19436

View user's profile Send private message

PostPosted: Tue Nov 26, 2013 8:37 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Nov 27, 2013 4:05 am     Reply with quote

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: 19436

View user's profile Send private message

PostPosted: Wed Nov 27, 2013 5:22 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Nov 27, 2013 7:21 am     Reply with quote

Thank you so much for your advice, but the problem remains :(, I receive the address that I send
temtronic



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

View user's profile Send private message

PostPosted: Wed Nov 27, 2013 7:36 am     Reply with quote

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: 19436

View user's profile Send private message

PostPosted: Wed Nov 27, 2013 8:31 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Nov 27, 2013 9:09 am     Reply with quote

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: 19436

View user's profile Send private message

PostPosted: Wed Nov 27, 2013 10:45 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Nov 27, 2013 2:31 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Nov 28, 2013 2:31 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Nov 28, 2013 6:08 am     Reply with quote

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: 1334

View user's profile Send private message

PostPosted: Thu Nov 28, 2013 7:53 am     Reply with quote

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.
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