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

Constructing a 32-bit word

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



Joined: 23 Apr 2009
Posts: 32

View user's profile Send private message

Constructing a 32-bit word
PostPosted: Wed Aug 24, 2016 9:31 am     Reply with quote

I need to build up a 32-bit word to be sent out via SPI, and I am looking for the best way to do it.

It needs to be built up via several pieces, an 8-bit label, 2-bit identifier, 19-bit value, 2-bit status, and 1 bit parity.

I am by far no expert programmer, and this seems like it should be easy, like maybe just shifting the values in to a variable or something like that...

So would this work?

word32 = (label<<23) | (ident<<21) | (value<<3) | (status<<1) | parity
temtronic



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

View user's profile Send private message

PostPosted: Wed Aug 24, 2016 12:33 pm     Reply with quote

try 'struct'... !

from the CCS manual



For example:
Code:
struct data_record {

           int   a[2];

           int  b : 2; /*2 bits */

           int    c : 3; /*3 bits*/

           int d;

       } data_var;                 //data_record is a structure type

//data _var is a variable

If you press F11 while your project is open, the manual 'magically' appears ! search for struct... and it's in the 'data definitions' area...

Though not a great example, you can probably figure it out, just remember the ORDER you store the stuff !!

Hay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 24, 2016 1:56 pm     Reply with quote

temtronic wrote:
try 'struct'... !

He wants a 19-bit wide bitfield. The compiler won't accept it.
It gives this error:
Quote:
Number of bits is out of range

Therefore your proposed method won't work.
temtronic



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

View user's profile Send private message

PostPosted: Wed Aug 24, 2016 2:12 pm     Reply with quote

well thats just 'silly'... maybe split the 19 into 16 and 3 ?
there HAS to be a way .....

I'm just too beat from changing a tractor tire in 90*F heat..

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Aug 25, 2016 4:20 am     Reply with quote

It depends what you actually want to do.

You can assemble the 32bit word as you show with rotations. Only 'caveats', make sure that you are limiting the values involved to their actual maximum sizes 'first', or you risk extra bits in 'value' for example, interfering with the ident etc..

However if you want to read the data 'back' or do other manipulations with them, and alternative may be worthwhile. Everything except 'value', can be done with a structure, and then a union with this, gives access to these parts very easily.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Thu Aug 25, 2016 7:08 am     Reply with quote

If you insist on sending it as a one 32 bit word then yes, your suggested technique will work, with some mods for practicality.

The union and bit field methods both have limitations and restrictions relating to the PIC hardware. There is no guaranty that arbitrarily complex data formats can be mapped by C code on the PIC. Sometimes it works, sometimes it can't. In this case it's the 19 bit value field that's causing trouble :-(

Personally, I tend to treat all SPI data as 8 bit, and send 32 bits as four bytes. In any case, that's what #use_spi() and xfer_spi() will do for you with a hardware SPI as the native mode of the hardware is bytes. The way I'd tread this is to send four bytes, the first is the label. The second is the ID shifted into the top bits, with the upper six bits of the value or'ed in. Then comes the mid eight bits of the value. The last byte is the lower bits of the value, the status and the parity. Yes, it can get unweildy, but that's the way I tend to play it, having been burnt by both unions (which suffer from alignment issues) and bit fields (which suffer from alignment and field size restrictions.

I use the same method for formatting CAN messages. Instead of sending the bytes directly, I put them in to the data bytes of a CAN message structure ready for sending.

Code:

// Byte by byte method.
output_low(DEVICE_CS);
// This assumes the data is sent in the order in the original post. This can easily be altered for other byte orders.
spi_xfer(label)
spi_xfer((value & 0x03F800)>> 11);
spi_xfer((value & 0x0007F8)>> 3);
spi_xfer((value & 0x000007) << 5 | (status & 0x03) << 1 | (parity & 0x01));
output_high(DEVICE_CS);


You can use your code with a little modification. You need to a) limit the values to sensible ranges and b) cast some of the values so that they can shift correctly. Casting is required in the label as, presumably, its an int8. If so, when you shift it more than seven bits ithe result will be zero. It needs to be cast to the final size, int32, before shifting:

Code:

// More practical shift version, with masking,  casting and corrected shifts. Assuming label, ident and status are int8, parity is int1.
word32 = ((int32)label<<24) | ((int32)(ident & 0x03)<<22) | (value<<3) | ((status & 0x02)<<1) | parity;


Parity doesn't get shifted, so there's no problem there, and the status stays within a int8 after shifting, so also has no problem. The value has to be int32 already. Its the label and ident that need to be cast.
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