Support Requests item #2897090, was opened at 2009-11-13 01:21
Message generated for change (Settings changed) made by maartenbrock
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=200599&aid=2897090&group_id=599
Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: None
Group: None
>Status: Closed
Priority: 5
Private: No
Submitted By: z-control (z-control)
>Assigned to: Raphael Neider (tecodev)
Summary: PIC14-PIC16 bitwise manipulation of registers and variables
Initial Comment:
Hi
I am comming from CCS and GNUAVR, and I am missing some background about how to manipulate bit-level registers or variables.
Typically, the pic has the ASM functions such as BCF, BSF, BTFSC, BTFSS.
I currently only see a solution to read a full byte (register or variable) to set or clear or test a bit, for set or clear write it back to the right place.
Also I would like to not only set or clear a given bit, ie RA1 or RA2, but make this variable.
Ie, I want to have a routine that sets or clears a bit 1,2,3,4... in a raw.
In GNUAVR, I know the _BV function, in CCS, you find BIT_SET(reg+var/reg,bit), BIT_CLEAR(reg+var,bit), BIT_TEST(reg+var,bit).
is this a missing function in SDCC ?
Thanks for any help.
----------------------------------------------------------------------
>Comment By: Maarten Brock (maartenbrock)
Date: 2011-11-05 02:28
Message:
Looks like a closed discussion.
----------------------------------------------------------------------
Comment By: Raphael Neider (tecodev)
Date: 2010-01-27 04:24
Message:
if ((!test_bPousAck)&( test_bPous==0)) {set_bAck; return 1;}
You use bitwise AND '&', which is (in this case) pretty inefficient. Using
logical AND '&&' yields much better results for me:
_test_poussoir ;Function start
; 2 exit points
; .line 20; "bit-cond.c" if ((!test_bPousAck) &&
(test_bPous == 0)) {
BANKSEL _PousAck
BTFSC _PousAck,0
GOTO _00108_DS_
BANKSEL _PORTC
BTFSC _PORTC,2
GOTO _00108_DS_
; .line 21; "bit-cond.c" set_bAck; return 1;
BANKSEL _PousAck
BSF _PousAck,0
MOVLW 0x01
GOTO _00111_DS_
_00108_DS_
; .line 27; "bit-cond.c" if (test_bPous)
BANKSEL _PORTC
BTFSS _PORTC,2
GOTO _00109_DS_
; .line 28; "bit-cond.c" clear_bAck;
BANKSEL _PousAck
BCF _PousAck,0
_00109_DS_
; .line 31; "bit-cond.c" return 0;
MOVLW 0x00
_00111_DS_
RETURN
Best regards
Raphael
----------------------------------------------------------------------
Comment By: z-control (z-control)
Date: 2010-01-27 02:27
Message:
Compiler efficiency or missing optimizer flag?
Hi I discovered that the compiler is handling the bit code in different
ways, is this a mistake from my side of using them or a bug/enhancement in
the compiler optimizer ?
example using the following definitions:
#define BIT_SET(VAR, BIT) VAR |= (1 << (BIT))
#define BIT_CLR(VAR, BIT) VAR &= ~(1 << (BIT))
#define BIT_TEST(VAR, BIT) ((VAR) & (1 << (BIT)))
// fonctions specifics a notre example
#define test_bPousAck BIT_TEST(PousAck,0)
#define set_bAck BIT_SET(PousAck,0)
#define clear_bAck BIT_CLR(PousAck,0)
#define test_bPous BIT_TEST(PORTC,2)
char test_poussoir(void)
{
// on a pressé
if(!test_bPousAck) {if( test_bPous==0) {set_bAck; return 1;}}
// si non, toujours pressé on ne fait
rien
// état pas pressé
else
if(test_bPous) clear_bAck;
// si non on ne fait rien
return 0;
}
generates:
_test_poussoir ;Function start
; 2 exit points
; .line 74; "test_bouton.c" if(!test_bPousAck) {if( test_bPous==0)
{set_bAck; return 1;}}
BTFSC _PousAck,0
GOTO _00147_DS_
BANKSEL _GPIO
BTFSC _GPIO,2
GOTO _00148_DS_
BSF _PousAck,0
MOVLW 0x01
GOTO _00149_DS_
_00147_DS_
; .line 79; "test_bouton.c" if(test_bPous) clear_bAck;
BANKSEL _GPIO
BTFSS _GPIO,2
GOTO _00148_DS_
BCF _PousAck,0
_00148_DS_
; .line 81; "test_bouton.c" return 0;
MOVLW 0x00
_00149_DS_
RETURN
which is ok/perfect, but I only found this after many tests, I would
prefere to write
char test_poussoir(void)
{
// on a pressé
if((!test_bPousAck)&( test_bPous==0)) {set_bAck; return 1;}
// si non, toujours pressé on ne fait
rien
// état pas pressé
else
if(test_bPous) clear_bAck;
// si non on ne fait rien
return 0;
}
but this code which in my mind is equivalent generates much more code
;; Starting pCode block
_test_poussoir ;Function start
; 2 exit points
; .line 74; "test_bouton.c" if((!test_bPousAck)&( test_bPous==0))
{set_bAck; return 1;}
MOVLW 0x01
ANDWF _PousAck,W
MOVWF r0x1001
MOVF r0x1001,W
MOVLW 0x00
BTFSC STATUS,2
MOVLW 0x01
MOVWF r0x1002
MOVLW 0x04
BANKSEL _GPIO
ANDWF _GPIO,W
MOVWF r0x1001
MOVF r0x1001,W
MOVLW 0x00
BTFSC STATUS,2
MOVLW 0x01
;;1 MOVWF r0x1003
ANDWF r0x1002,F
MOVF r0x1002,W
BTFSC STATUS,2
GOTO _00145_DS_
BSF _PousAck,0
MOVLW 0x01
GOTO _00147_DS_
_00145_DS_
; .line 79; "test_bouton.c" if(test_bPous) clear_bAck;
BANKSEL _GPIO
BTFSS _GPIO,2
GOTO _00146_DS_
BCF _PousAck,0
_00146_DS_
; .line 81; "test_bouton.c" return 0;
MOVLW 0x00
_00147_DS_
RETURN
; exit point of _test_poussoir
ignoring the bit maniplulation.
Is there any trick, or am I doing any mistake using SDCC ?
Thanks for any advice
Rolf
----------------------------------------------------------------------
Comment By: Raphael Neider (tecodev)
Date: 2009-11-13 06:59
Message:
What does "does not work" mean?
If all the PORTB-pins are 0, you might not have set them up as digital
pins. Try
ANSEL=ANSELH=0;
before modifying the register (ANSELH is the important one for PORTB, see
datasheet):
If you assign tmp to PORTB, the hardware overwrites all bits and you are
fine.
If you clear individual bits, the hardware executes read-modify-write and
-- unfortunately -- all pins read as 0 when configured as analog inputs
(the power-on default, ANSEL=ANSELH=0xff).
BTW: If you want to specify the bit to modify at runtime, the hardware
cannot use BCF/BSF/BTF/... because these require a literal (compile-time
constant) bit index. The compiler will generate a loop for (1 << (BIT)) and
modify the PORT via IORWF or ANDWF instead.
----------------------------------------------------------------------
Comment By: z-control (z-control)
Date: 2009-11-13 04:00
Message:
thank you for the input, I must make something wrong as I tried your code
couple of days ago. I just checked again and copied the 2 options I had out
of an interrupt routine:
...
#define BIT_SET(VAR, BIT) VAR |= (1 << (BIT))
#define BIT_CLR(VAR, BIT) VAR &= ~(1 << (BIT))
#define BIT_TST(VAR, BIT) ((VAR) & (1 << (BIT)))
....
if(++raw==8)raw=0;
tmp=0xff;
tmp=tmp ^ (1 << raw); // enable led raw (active low)
PORTB=tmp;
//the above code works, each bit of PORTB gets 0 in a raw.
// but with your macro it would be simpler but that does not work !
// is it only limited to variables and not to registers ?
PORTB=0xff;
BIT_CLR(PORTB,raw);
// should do the same, but does not work
// I am using a 16f887
P.S. with VAR/REG I ment applicable to variables and PIC registers within
SDCC.
----------------------------------------------------------------------
Comment By: Raphael Neider (tecodev)
Date: 2009-11-13 02:31
Message:
Hi,
you can use
#define BIT_SET(VAR, BIT) VAR |= (1 << (BIT))
#define BIT_CLR(VAR, BIT) VAR &= ~(1 << (BIT))
#define BIT_TEST(VAR, BIT) ((VAR) & (1 << (BIT)))
SDCC will automatically replace single-bit accesses with the
bit-manipulation instructions offered by the target architecture.
I do not know what 'reg+var' is supposed to mean, but the above should get
you started.
Best regards
Raphael
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=200599&aid=2897090&group_id=599
|