|
|
View previous topic :: View next topic |
Author |
Message |
kerplatz
Joined: 01 Nov 2016 Posts: 18
|
SPI transfer of 14 bits |
Posted: Sun Oct 29, 2017 6:50 pm |
|
|
Hi,
I have a unique problem. Most chips that I have ever written to or read from used a number of bits that was a multiple of 8 until now. I have this chip (PE46130) from Peregrine Semiconductor and it uses 14 bits. I get strange results whenever I send via SPI more than 14 bits. Go figure. If only they had done some thing standard, this would be simpler. Anyway, I have tried using FORCE_SW and the bits=14 in the #USE SPI line, but spi_xfer() still sends 16 bits. I really don't want to bit-bang this. I would rather just have CCS do it all for me, if this is possible. I assume it is since you can specify the # of bits, otherwise they would have used # of BYTES. I will give you the relevant code.
Code: | #use spi(MASTER, SPI2, FORCE_SW, MODE=0, BAUD=2000000, BITS=14, STREAM=SPI_MODE0_SPEC) |
I then initialize the chip which is nothing more than writing all zeros except for the 13th or last bit which is a one. I use the function below to write the init data to the chips. I suspect this is where it all goes wrong. The extra clocks may cause undesired effects.
Here is the SPI write function. It gets called whenever I need to change the state of the chip. There are multiple chips and they all behave the same way when I write to them.
Code: | void write2MPAC(unsigned int data, unsigned int chipSelectPin)
{
// Start the transfer.
output_low(chipSelectPin);
// Write the data to the MPAC.
spi_xfer(SPI_MODE0_SPEC, data << 2, 14);
// Transfer is complete.
output_high(chipSelectPin);
} |
The data gets shifted over 2 because that is how I choose to construct it since I only needed 14 of the 16 bits. It is somewhat difficult to explain what the data is, so suffice it to say that I have thoroughly checked and double checked that I am constructing the data the chip needs.
I really thought this would work, but I get 16 clock cycles and not 14 as I expected. Is what I want to do even possible using the CCS library? Thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Oct 29, 2017 9:16 pm |
|
|
Since it won't work with #use spi(), why not try bit-banging it ?
Example:
Code: | #include <18F46K22.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT
#use delay(clock=32M)
#use rs232(baud=9600, UART1, ERRORS)
#define PE46130_DI PIN_B0
#define PE46130_CLK PIN_B1
#define PE46130_CS PIN_B2
// Call this routine at the start of main().
void PE46130_init(void)
{
output_low(PE46130_DI);
output_low(PE46130_CLK);
output_high(PE46130_CS);
}
// Write 14 bits via SPI by bit-banging.
void write_14_bits(int16 data)
{
int8 i;
data <<= 2; // Left justify the data
output_low(PE46130_CS);
for(i=0; i<14; i++)
{
output_bit(PE46130_DI, shift_left(&data, 2, 0));
output_high(PE46130_CLK);
output_low(PE46130_CLK);
}
output_high(PE46130_CS);
}
//=====================================
void main(void)
{
PE46130_init();
write_14_bits(0x1234); // Data is passed in right-justified format
while(TRUE);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Oct 30, 2017 8:01 am |
|
|
Beg to differ....
Actually it will work with #USE SPI, but not as shown.
You must not use the SPI port number, just pin numbers.
Using a port number _forces_ the hardware to be used. Overrides the FORCE_SW.
So:
(Obviously with the right pins)
Code: |
#use spi(MASTER, DO=PIN_A0, DI=PIN_A1, CLK=PIN_A2, FORCE_SW, MODE=0, BAUD=2000000, STREAM=SPI_MODE0_SPEC)
|
Then using a 14bit transfer as he already does, merrily sends 14 bits (you don't need the bits= in the setup).
data needs to be int16, assume you are using a PIC24/30, so this is the default. |
|
|
kerplatz
Joined: 01 Nov 2016 Posts: 18
|
|
Posted: Mon Oct 30, 2017 9:02 am |
|
|
This is good. Although I was willing to do the bit banging, I had reasons for not wanting to do it. Still not sure I can still use the #USE SPI method, but I am going to give it a try. For those that are curious the chip is PIC24FJ256GA106.
What are the reasons you might ask, and this goes back to the chip manufactures not doing something in a standard way. While SPI was designed to allow for the four modes, CPOL, and CPHA, my wish is every chip maker would pick one and use that as the defacto standard. Then if it is non-standard, we could avoid it, but that could not be in this case. I know it won't happen, but my job would be easier if I did not have to decipher a data sheet for every chip I use.
So, as you might have guessed I have a mixture of SPI modes and data lengths. CCS tech support said that all I have to do is make the number of #USE SPI statements I need using a different stream name for each and then call spi_init() on the stream when I want to use that particular stream. I use a flag to determine if I need to call the spi_init(). No need to call it if I am already using that stream.
I hope this works. Here are the three #USE SPI statements I will be using.
Code: |
#use spi(MASTER, DO=PIN_F3, DI=PIN_D11, CLK=PIN_F2, FORCE_SW, MODE=0, BAUD=2000000, STREAM=SPI_MODE0_SPEC)
#use spi(MASTER, SPI2, FORCE_HW, MODE=0, BAUD=2000000, STREAM=SPI_MODE0)
#use spi(MASTER, SPI2, FORCE_HW, MODE=1, BAUD=2000000, STREAM=SPI_MODE1)
|
Thanks for all the input. |
|
|
kerplatz
Joined: 01 Nov 2016 Posts: 18
|
|
Posted: Mon Oct 30, 2017 9:30 am |
|
|
So I tried this using the #USE SPI and it did not work. Still getting 16 clock cycles. Contacted tech support. If any one knows why, please let me know. In the mean time I will be bit banging this, and I hope it works for me. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Oct 30, 2017 10:08 am |
|
|
Interesting.
Using:
Code: |
#use spi(MASTER, DO=PIN_A0, DI=PIN_A1, CLK=PIN_A2, FORCE_SW, MODE=0, BAUD=2000000, STREAM=SPI_MODE0_SPEC)
//With:
void main()
{
int16 data;
while(TRUE)
{
spi_xfer(SPI_MODE0_SPEC, data, 14);
delay_ms(100);
}
}
|
On a PIC18, I merrily get 14 clocks only being generated.
Looks as if it may be a fault in the PIC24 software library... |
|
|
kerplatz
Joined: 01 Nov 2016 Posts: 18
|
|
Posted: Mon Oct 30, 2017 12:12 pm |
|
|
Problem solved. It was me. I was using three #defines for use in a flag to tell which of the 3 #USE SPI configurations I was using so as to not have to init the SPI hardware if it was already in that state. Well, I inadvertently used the same #define name as the stream name. I had meant to change it when I copied it, but forgot to. My bad. Everything working now. I hate when that happens. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Oct 30, 2017 2:26 pm |
|
|
Unfortunately this is one where the compiler doesn't warn about the duplication.
At least you found it.... |
|
|
|
|
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
|