|
|
View previous topic :: View next topic |
Author |
Message |
pyrodigy
Joined: 27 Nov 2017 Posts: 3
|
Flag bit definition question |
Posted: Wed Jan 24, 2018 5:58 pm |
|
|
Hello All,
I am new to ccs and this is my first topic in here. First of all i would like to say something that i have been following this forum for a while and would like to Thank you guys. I have found out lots of things, learned more than many books thanks to all of you. i am very happy to be here.
Now i am a little bit confused abouth bit definition between the following definitions examples,
Def.Example -1
Code: |
unsigned int16 AdresFlags; //Flag Bits
#bit Adres1 = AdresFlags.0
#bit Adres2 = AdresFlags.1
#bit Adres3 = AdresFlags.2
#bit Adres4 = AdresFlags.3
#bit Adres5 = AdresFlags.4
#bit Adres6 = AdresFlags.5
#bit Adres7 = AdresFlags.6
#bit Adres8 = AdresFlags.7
#bit Adres9 = AdresFlags.8
#bit Adres10 = AdresFlags.9
|
And
Def.Example - 2
Code: |
struct {
unsigned int8 Adres1:1;
unsigned int8 Adres2:1;
unsigned int8 Adres3:1;
unsigned int8 Adres4:1;
unsigned int8 Adres5:1;
unsigned int8 Adres6:1;
unsigned int8 Adres7:1;
unsigned int8 Adres8:1;
unsigned int8 Adres9:1;
unsigned int8 Adres10:1;
}AdresFlags={0,0}; // Flag Bits
|
Could you please let me know what is main difference between these definition examples?
What compiler behave whenever it see these definitions ?
and also
I am currently having a problem for the following operation. Whenever i use definition example-1 everything looks OK. but whenever i defined as example-2 i am having an '' A numeric expression must appear here '' Error.
Why ? Where am i wrong ?
Code: |
void TEST(void)
{
static unsigned int16 ADRESDATA_READ=0; // ADRESS BUTON DATA
// HERE READ 10 BIT FROM SERIAL PORT
AdresFlags ^= ADRESDATA_READ; // TOGGLE FLAG BITS (OR OPERATOR)
}
|
Note: PIC16F1526
CCS VERSION=5.074
Best Regards |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jan 24, 2018 6:27 pm |
|
|
You should post a complete test program so we don't have to do any work
to make one. Then we can just copy and paste it into our IDE and test it.
I made one below.
I was able to make it compile by casting AdresFlags to an int16 as shown
below:
Code: |
#include <16F1526.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)
struct {
unsigned int8 Adres1:1;
unsigned int8 Adres2:1;
unsigned int8 Adres3:1;
unsigned int8 Adres4:1;
unsigned int8 Adres5:1;
unsigned int8 Adres6:1;
unsigned int8 Adres7:1;
unsigned int8 Adres8:1;
unsigned int8 Adres9:1;
unsigned int8 Adres10:1;
}AdresFlags={0,0}; // Flag Bits
void TEST(void)
{
static unsigned int16 ADRESDATA_READ=0;
(int16)AdresFlags ^= ADRESDATA_READ; // *** cast to int16
}
//=================================
void main(void)
{
TEST();
while(TRUE);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19561
|
|
Posted: Thu Jan 25, 2018 2:00 am |
|
|
In terms of differences, none really....
'Bit fields' (the : syntax), is standard C. Advantage comes where you are perhaps wanting to work with several bits together. So (for instance), the register AD1CON1 on a PIC24, can be defined like:
Code: |
struct __attribute__((packed)) {
uint done:1;
uint samp:1;
uint asam:1;
uint na:1;
uint ssrc:4;
uint form:2;
uint mode12:1;
uint dmaen:1;
uint dmabm:1;
uint adsidl:1;
uint na1:1;
uint adon:1;
} AD1CON1;
|
And you can talk to AD1CON1.ssrc, as an entity occupying 4 bits.
For single bit use no real difference.
However the #BIT directive, was specifically an optimisation. The PIC itself has a single instruction bit set/clear operation, and the #bit directive automatically accesses this. It was a way to offer the programmer access to this specific machine instruction. There are other (swap for example).
That being said, the current optimiser is quite smart, and for a single bit access into the bit fields form, will substitute the optimised machine instruction.
Remember if using bit fields, that you have to think what order the processor actually allocates bits, and (for the PIC 12/16/18), the 'wrapper' type is a single int8 only - hence the two byte initialisation you show, while with the #bit directive, you can initialise the larger type.
The problem you are having with bitfields, is that with this 'AdresFlags', is not an int16. It is a structure containing the bits. What you have to do is tell the compiler to treat this structure 'as' an int16. This is what PCM_Programmer is showing (the cast is the vital thing here).
You can also take advantage of a union here:
Code: |
struct bits {
unsigned int8 Adres1:1;
unsigned int8 Adres2:1;
unsigned int8 Adres3:1;
unsigned int8 Adres4:1;
unsigned int8 Adres5:1;
unsigned int8 Adres6:1;
unsigned int8 Adres7:1;
unsigned int8 Adres8:1;
unsigned int8 Adres9:1;
unsigned int8 Adres10:1;
}; // Flag Bits
union {
struct bits b;
unsigned int16 whole;
} AdresFlags;
static unsigned int16 ADRESDATA_READ=0; // ADRESS BUTON DATA
//You can then talk to single bits:
AdresFlags.b.Adres9 =1; //for example
//Or the whole word as
AdresFlags.whole ^= ADRESDATA_READ;
|
|
|
|
pyrodigy
Joined: 27 Nov 2017 Posts: 3
|
|
Posted: Thu Jan 25, 2018 4:04 am |
|
|
PCM programmer wrote: | You should post a complete test program so we don't have to do any work
to make one. Then we can just copy and paste it into our IDE and test it.
I made one below. |
My main program contains 68 push button and 100 led indicator over spi, 2 x usart, i2c, lcd...ext so in my opinion if i post complete program it will be hard to focus main question. I only say my main flow control related to these Flag bits test.
About the test functions;
I defined a dummy test program, i test the codes where i stuck and look at the mplab simulator to see what is going on.
This test dedicated to bit definitions to understand difference between bit definitions.
Code: |
void TEST(void)
{
static unsigned int16 ADRESDATA_READ=0; //ADRESS BUTTON DATA READ from 2 x 165
while(TRUE){
read_ADRES_inputs(&ADRESDATA_READ); // READ 10 Bit from 2 x 74HC165
// same function as read_expanded_inputs() in 74165.c driver
ADRESDATA_READ = ADRESDATA_READ & 0x3FF; // MASK High 6 bits (00000011 111111111)
if(ADRESDATA_READ) //Zero Test
{
if(MultiCue) //If MC button pressed
AdresFlags ^= ADRESDATA_READ; //Toogle bits
else //If Not
AdresFlags = ADRESDATA_READ; // assign whole
}
}
|
My main aim is, as i stated in my previous i am not getting error when i defined as #BYTE and its Flag #bits method. I just would like to know struct type bit definition method. C programming language book explained shallow for the struct type bit definitions.
Code: |
(int16)AdresFlags ^= ADRESDATA_READ; // *** cast to int16
|
Thank you for your code, i am glad to see CCS sort out easily with redefine as 16 bit (int16) AdresFlags register.
Ttelmah wrote: | In terms of differences, none really....
'Bit fields' (the : syntax), is standard C. Advantage comes where you are perhaps wanting to work with several bits together. So (for instance), the register AD1CON1 on a PIC24, can be defined like:
Code: |
struct __attribute__((packed)) {
uint done:1;
uint samp:1;
uint asam:1;
uint na:1;
uint ssrc:4;
uint form:2;
uint mode12:1;
uint dmaen:1;
uint dmabm:1;
uint adsidl:1;
uint na1:1;
uint adon:1;
} AD1CON1;
|
And you can talk to AD1CON1.ssrc, as an entity occupying 4 bits.
For single bit use no real difference.
However the #BIT directive, was specifically an optimisation. The PIC itself has a single instruction bit set/clear operation, and the #bit directive automatically accesses this. It was a way to offer the programmer access to this specific machine instruction. There are other (swap for example).
That being said, the current optimiser is quite smart, and for a single bit access into the bit fields form, will substitute the optimised machine instruction.
Remember if using bit fields, that you have to think what order the processor actually allocates bits, and (for the PIC 12/16/18), the 'wrapper' type is a single int8 only - hence the two byte initialisation you show, while with the #bit directive, you can initialise the larger type.
The problem you are having with bitfields, is that with this 'AdresFlags', is not an int16. It is a structure containing the bits. What you have to do is tell the compiler to treat this structure 'as' an int16. This is what PCM_Programmer is showing (the cast is the vital thing here).
You can also take advantage of a union here:
Code: |
struct bits {
unsigned int8 Adres1:1;
unsigned int8 Adres2:1;
unsigned int8 Adres3:1;
unsigned int8 Adres4:1;
unsigned int8 Adres5:1;
unsigned int8 Adres6:1;
unsigned int8 Adres7:1;
unsigned int8 Adres8:1;
unsigned int8 Adres9:1;
unsigned int8 Adres10:1;
}; // Flag Bits
union {
struct bits b;
unsigned int16 whole;
} AdresFlags;
static unsigned int16 ADRESDATA_READ=0; // ADRESS BUTON DATA
//You can then talk to single bits:
AdresFlags.b.Adres9 =1; //for example
//Or the whole word as
AdresFlags.whole ^= ADRESDATA_READ;
|
|
Honestly this is the exactly answer what i am looking for. Your lesson should be the duration of the bit-fields topic in the Dennis Ritchie's book
I will read again and again Thank you very much. I appreciated. |
|
|
|
|
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
|