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

Accessing only 1 byte of a SRF

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



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

Accessing only 1 byte of a SRF
PostPosted: Fri Oct 11, 2013 12:02 am     Reply with quote

Hi All.

How do I access only one byte of a SFR in a 16 bit PIC?

Code:
#word __P1DTCON1 = getenv("SFR:P1DTCON1") //PWM1 Dead time register1

For example I want to update only the high byte of P1DTCON1.

For normal RAM I just use a struct and union.

Regards
Ttelmah



Joined: 11 Mar 2010
Posts: 19346

View user's profile Send private message

PostPosted: Fri Oct 11, 2013 12:57 am     Reply with quote

Look at #BIT and #BYTE

You can just use the struct and union though. If you 'pre-declare' a variable, then #byte can be used to locate _that variable_ at a location.
The variable can be a structure, just as easily as any other variable type.
So declare the structure and union as you would for RAM, then use:

#byte variable_name = getenv("SFR:P1DTCON1") //PWM1 Dead time register1

Which will then locate the variable called 'variable_name' at the specified location.

Best Wishes
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Fri Oct 11, 2013 1:47 am     Reply with quote

Thanks Ttelmah,

Didn't know you could do it that way.

I started doing it as you suggested and the code are now shorter, however I still seem to misunderstand something as shown in the following code.
Code:
.................... typedef union {
....................  uint16_t WRD;
....................  struct {
....................    uint8_t High;
....................    uint8_t Low;
....................  }BTY;
.................... } __DEADTIME;
.................... __DEADTIME __DeadTimeREG;

.................... void SetDeadTimeRegA(DutyCycle) { \
....................   __DeadTimeREG.BTY.Low &= (uint8_t)(0xC0);  /*Clr values*/ \
*
09B2:  MOV     81A,W4
09B4:  LSR     W4,#8,W4
09B6:  AND.B   #C0,W4L
09B8:  MOV.B   W4L,W0L
09BA:  MOV.B   W0L,81B

Why does the compiler do a LSR and then do the AND in W4 move it W0 and then back to the byte?

I don't think you would need more than this.
Code:
  #asm MOV.B     __DeadTimeREG.BTY.Low,W0
       AND.B   0xC0,W0
       MOV.B   W0,__DeadTimeREG.BTY.Low
  #endasm
Doesn't compile Embarassed but hopefully you get the drift.

Probably doesn't make much difference the 2 extra instructions as it is a dsPIC33EP64FJ12MC202, but I like to understand for when I am in a jam regarding speed.

Regards
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Fri Oct 11, 2013 6:18 am     Reply with quote

To avoid any overhead, define #BYTE registers

Code:
#byte __P1DTCON1L = getenv("SFR:P1DTCON1")
#byte __P1DTCON1H = getenv("SFR:P1DTCON1")+1
Ttelmah



Joined: 11 Mar 2010
Posts: 19346

View user's profile Send private message

PostPosted: Fri Oct 11, 2013 6:34 am     Reply with quote

Second guessing why the assembler does things is often quite 'fun'....

As an experiment, I tried changing the union to use a two char array, instead of the separate high/low defines.

Code changes to:
Code:

union splitter {
  unsigned int16 word;
  char bytes[2];
};

union splitter __using_array;
#byte __using_array = getenv("SFR:PMDOUT2") //PWM1 Dead time register1

....................    __using_array.bytes[1] &= (0xC0); 
0254:  MOV.B   PMDOUT2.7,W0L
0256:  SE      W0,W0
0258:  AND     #C0,W0
025A:  MOV.B   W0L,PMDOUT2.7H


If however the char is changed to 'unsigned', then using this or direct #byte defines, or the named array, then it always performs the 16bit access.

It looks as if this is it's default way of accessing a 'byte' to give an empty top byte in the case of unsigned types....

Best Wishes
Ttelmah



Joined: 11 Mar 2010
Posts: 19346

View user's profile Send private message

PostPosted: Fri Oct 11, 2013 12:39 pm     Reply with quote

FvM wrote:
To avoid any overhead, define #BYTE registers

Code:
#byte __P1DTCON1L = getenv("SFR:P1DTCON1")
#byte __P1DTCON1H = getenv("SFR:P1DTCON1")+1


Actually this does the same.....

It appears it is CCS's default way of accessing a 'byte', if it is unsigned. It uses the rotation to clear the top byte, even if the result only uses the low byte. If signed, it uses SE instead.

Best Wishes
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