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

SPI transfer of 14 bits

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kerplatz



Joined: 01 Nov 2016
Posts: 18

View user's profile Send private message

SPI transfer of 14 bits
PostPosted: Sun Oct 29, 2017 6:50 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Oct 29, 2017 9:16 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Oct 30, 2017 8:01 am     Reply with quote

Beg to differ.... Smile

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

View user's profile Send private message

PostPosted: Mon Oct 30, 2017 9:02 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Oct 30, 2017 9:30 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Oct 30, 2017 10:08 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Oct 30, 2017 12:12 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Oct 30, 2017 2:26 pm     Reply with quote

Unfortunately this is one where the compiler doesn't warn about the duplication.
At least you found it.... Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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