|
|
View previous topic :: View next topic |
Author |
Message |
rdesgagn
Joined: 30 Jul 2008 Posts: 3
|
SPI communication |
Posted: Wed Jul 30, 2008 1:49 pm |
|
|
Hello everyone,
I'm using a PIC18F4520 with an Infineon H-Bridge (TLE6209-R) to control an actuator. The H-Bridge receives a PWM another signal to specify the direction. The H-Bridge has a SPI interface to set some current/voltage protection settings and also diagnostic message to get the H-Bridge status. I'm using the SPI hardware interface on the PIC to link the PIC to the H-Bridge. I connected those pins:
PIC_C3 SCLK -> H-Bridge SCLK
PIC_C4 SDI -> H-Bridge SDO
PIC_C5 SDO -> H-Bridge SDI
PIC_B6 -> H-Bridge CSN
From the H-Bridge datasheet, here is how work the SPI link :
The SPI is used for bidirectional communication with a control unit. The 8-bit
programming word or control word (see Table 1) is read in via the SDI serial data input, and this is synchronized with the serial clock input SCLK. The status word appears synchronously at the SDO serial data output (see Table 4).
The transmission cycle begins when the chip is selected with the chip-select-not (CSN) input (H to L). When the CSN input changes from L to H, the word which has been read into the shift register becomes the control word.
Here is my source code for the PIC :
Code: |
#define CSN_SPI PIN_B6
int8 spiDataIn, spiDataOut;
#int_ssp
void spi_rx_interrupt(){
spiDataIn = spi_read();
printf("spiDataIn %x\r\n",spiDataIn);
}
void spiRead(){
output_low(CSN_SPI); //enable spi comm with h-bridge
spiDataIn = spi_read();
printf("spiDataIn %x\r\n",spiDataIn);
delay_ms(1);
output_high(CSN_SPI); //disable spi comm
}
void spiWrite(int8 inSpiOutData){
output_low(CSN_SPI); //enable spi comm with h-bridge
spi_write(inSpiOutData);
delay_ms(1);
output_high(CSN_SPI); //disable spi comm
}
void main(){
enable_interrupts(int_ssp); //SPI received data interrupt
enable_interrupts(GLOBAL);
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16); //setup spi interface
output_high(CSN_SPI); //disable spi comm to the H-Bridge
spiRead();
delay_ms(1000);
spiWrite(0xFF);
delay_ms(1000);
spiRead();
delay_ms(1000);
spiWrite(0xAA);
delay_ms(1000);
spiRead();
}
|
After the first read, I get 0x3F. However, for the subsequent write, I always get 0x02 as a response from the H-Bridge and from the datasheet, I don't think it's working. My question is am I using the SPI correctly to read and write a byte to the H-Bridge ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jul 30, 2008 3:07 pm |
|
|
According to Figure 7 in the TLE6209-R data sheet in the line for "SDI",
the chip samples data on the falling edge of SCLK and the clock idles
in a low state.
According to the diagram on SPI modes, shown near the bottom of this
page, the TLE6209-R chip is using SPI Mode 1.
http://elm-chan.org/docs/spi_e.html
Also, the Electrical Characteristics section of the TLE6209-R data sheet
says the minimum period for SCLK is 500 ns, which means the maximum
frequency is 2 MHz. You didn't say what your PIC oscillator frequency is,
but if it's 20 MHz then your divisor of 16 would give 1.25 MHz, which
would be OK.
Here are the #define statements for the SPI modes:
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) |
Based on all this information, the setup_spi() statement can be written:
Code: | setup_spi(SPI_MASTER | SPI_MODE_1 | SPI_CLK_DIV_16); |
In your program, you're using using the #int_ssp interrupt. That's
completely unnecessary. Remove the isr and the lines that enable
interrupts.
Also, in SPI the master supplies the clock. In CCS, when you call the
spi_read() function and you want to clock data out of the slave chip, you
need to give the function a parameter. Typically this parameter is 0x00.
Then the PIC will clock out a 0x00 byte, and the byte from the slave
will be clocked into the PIC and read.
Example of how to read a byte from an SPI slave:
Code: | int8 data_read;
data_read = spi_read(0x00); |
|
|
|
rdesgagn
Joined: 30 Jul 2008 Posts: 3
|
|
Posted: Wed Jul 30, 2008 3:36 pm |
|
|
Thanks for your answer PCM programmer. I applied the changes that you told me to do. I'm using a 20 MHz oscillator, so I'm ok with SPI_CLK_DIV_16 . Now, I think it's working fine but I still have a question. With the H-Bridge, I have two possible messages : the control and the diagnostic word. The control word is used to set current/voltage protection settings and the diagnostic one is used to get the chip status. However, I don't understand when I do this code below if data_read is the control word or the diagnostic message ? I want to have both, first I want to send the right settings for my application then sometimes I want to read the spi interface to get the chip status. Do you have an idea how can I accomplish that ?
Code: |
int8 data_read;
data_read = spi_read(0x00);
|
René |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jul 30, 2008 4:32 pm |
|
|
This chip has a really simple SPI interface. When you shift in the
control byte, you are shifting out the status byte at the same time.
So you can do it two different ways:
You can do it with two lines of spi code, like this:
Code: |
int8 control_byte;
int8 diagnosis_data;
control_byte = 0x55;
spi_write(control_byte);
diagnosis_data = spi_read();
|
Or you can do it with one line, like this:
Code: |
int8 control_byte;
int8 diagnosis_data;
control_byte = 0x55;
diagnosis_data = spi_read(control_byte); |
These two methods produce the same ASM code in the .LST file.
Note that 0x55 is just a representative value. You need to choose
the real value.
-----------------
I just noticed something about this chip. It claims to be an SPI interface
but it sends the LSB (bit 0) first. But the hardware SPI module in the
PIC sends and receives the MSB (bit 7) first.
There are two possible solutions to this. You can switch to using
software SPI and send the data LSB first. Or, you can use hardware
SPI as shown in the code above, but then you need to call a bit reversal
routine to convert both the transmitted data and the received data.
There are several bit reversal routines shown in the Code library:
http://www.ccsinfo.com/forum/viewtopic.php?t=23364
The revised code would look like this:
Code: | spi_write(reverse_bits(control_byte));
data = reverse_bits(spi_read()); |
I have just used the function name of 'reverse_bits' as a generic name
for any of the routines shown in the Code Library. |
|
|
rdesgagn
Joined: 30 Jul 2008 Posts: 3
|
|
Posted: Wed Jul 30, 2008 4:39 pm |
|
|
Thanks a lot PCM Programmer. Me too, I have noticed that the H-Bridge is sending the LSB first and I was reading it backwards so the data didn't make sense at all.
Thank you again for your help, everything is working like I want !!! |
|
|
|
|
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
|