PDA

View Full Version : Bitwise operations and masks: basics, help?



xnihilo
- 18th April 2008, 14:45
Hi,

I know there are the bitwise operators to work at bit level. I'm not familiar with these and logic was never my strong point. That's why I would need some help here.

I'm using a 7 segments led display (plus a dot, which makes 8 leds, and two ground pins, for a total of 10 pins).
Each segment is a led. The 7 sements (plus the dot led) have common cathode.
Each led anode is connected to a pin of a PIC16F684. So to turn on a segment, I just need to output 5V on the appropriate pin. To display a digit, I just have to turn on the appropriate pins/segments/leds.

I'm using RC4 to RC0 for 5 of the 7 segments (segments a to e) and RA1 to RA2 for the 2 last segments (f, g) (while the "dp" dot is on RA0).

I have to set the appropriate pins to display the adequate segments to display a digit.
For example, to display digit "0", I need to turn on the pins that will light the segments a, b, c,d, d, e, f, thus, for my design, the pins RC4 to RC0 and RA1. (a little complicated, yes).
Anyway, I have to set portA and portC to:


porta: xxxx10x, portc: x11111

where the "x" represent bits that must not be changed.

How can I replace the needed bits without changing the "x" bits?

I guess I should use bits mask but what is the magic?

Thanks for any help here.

Regards.

mister_e
- 18th April 2008, 15:29
when you want to clear a bit you use AND, set a bit OR

portc: x11111

PORTC=PORTC | %00011111

<hr>
porta: xxxx10x,

for this one you may also do it simple..
TempVar=PORTA
TempVar.1=0
TempVar.2=1
PORTA=TempVar

OR, in some case, the following will work without much problem
PORTA.1=0
PORTA.2=1

HTH

xnihilo
- 18th April 2008, 15:40
when you want to clear a bit you use AND, set a bit OR

portc: x11111

PORTC=PORTC | %00011111

<hr>
porta: xxxx10x,

for this one you may also do it simple..
TempVar=PORTA
TempVar.1=0
TempVar.2=1
PORTA=TempVar

OR, in some case, the following will work without much problem
PORTA.1=0
PORTA.2=1

HTH

Hello,

Simple?
Not so simple because each digit on the 7segments display needs (in my design) a pair of bytes for porta and portc that are found in a 10 entries array, and I prefer not to use intermediate variable.
Sorry but I didn't understand your example above:

portc: x11111
PORTC=PORTC | %00011111
porta: xxxx10x,



let's say porta value is %00011001 and I need to alter only bits 1 and 2 with the following pattern stored in a BYTE varible called "avar":
variable avar value is %-----10-

???

Can I isolate a chunk of a byte and insert it at a desired position in anoter byte?

mister_e
- 18th April 2008, 15:51
Yes i see some different ways, just paste your pattern here and where to send them, i'll give you something to think about.

xnihilo
- 18th April 2008, 16:50
Example:

The bits I need to set to display the "0" digit on the 7 segments display are:

on porta: %***01* , all other bits are left untouched
on portc: %*11111 , bit 5 is left untouched.

I have two arrays of bytes:
cval VAR BYTE[10] and aval VAR BYTE[10], each index represents a duet of bytes containing the bits configuration to display a digit.
arrays index 0 for digit "0",... up to digit "9" in index 9.

I only need to 'insert' chunks of bits in porta and portc registers.


For a given array index (representing the 7 bits to make a digit):
For porta I will need to replace bits 1 and 2 from porta by bits 1 and 2 from aval variable.
For portc I will need to replace bits 4 to 0 from portc by bits 4 to 0 from cval variable

is this clear ???

mister_e
- 18th April 2008, 16:54
Why not a WORD array instead? Anyways, yes it's clear enough. I'll do something a little bit later.

xnihilo
- 18th April 2008, 16:58
Why not a WORD array instead? Anyways, yes it's clear enough. I'll do something a little bit later.

Yes, I may use a WORD array instead... Anyway, it wont be much different I guess. The principle of bit manipulations will remain the same I beleive...

Anyway, thank you very much for your help.

mister_e
- 18th April 2008, 18:15
'
' Tested on 16F877
' ----------------
@ __CONFIG _XT_OSC & _LVP_OFF & _WDT_OFF

TRISA=0
TRISB=0
TRISC=0
TRISD=0


Aval VAR byte [10]
Cval VAR BYTE [10]
CounterA VAR BYTE
CounterB VAR BYTE

PORTA=0
PORTB=0
PORTC=0
PORTD=0
ADCON1=7

AVAL[0]=%00000000
AVAL[1]=%00000010
AVAL[2]=%00000100
AVAL[3]=%00001010
AVAL[4]=%00010000
AVAL[5]=%00100010
AVAL[6]=%01000100
AVAL[7]=%10000010
AVAL[8]=%10101001
AVAL[9]=%11111111

CVAL[0]=%00000000
Cval[1]=%00000001
CVAL[2]=%00000010
CVAL[3]=%00000100
CVAL[4]=%00001000
CVAL[5]=%00010000
CVAL[6]=%00101000
CVAL[7]=%01000100
CVAL[8]=%10000010
CVAL[9]=%11100001

Start:
for CounterB = 0 to 255
PORTA=CounterB
PORTB=COUNTERB
PORTC=CounterB
PORTD=COUNTERB
fOR CounterA = 0 TO 9
'
' this should be the section you need
PORTA = (PORTA & %11111001) | (AVAL[COUNTERA] & %00000110)
PORTC = (PORTC & %11100000) | (CvAL[CounterA] & %00011111)
'
'
PAUSE 250
NEXT
NEXT
STOP

PS: As you only use 7 bit... you could also us ONLY 1 byte array instead of 2.

falingtrea
- 18th April 2008, 20:41
What I would do is:


PORTC = PORTC & %11100000 / Clear all the bits in PORTC that are segments
PORTC = AVAL[x] | PORTC / sets the bits in PORTC that are '1' in AVAL[x]

PORTA = PORTA & %11111001 / Clear all the bits in PORTA that are segments
PORTA = CVAL[x] | PORTA / sets the bits in PORTA that are '1' in CVAL[x]

if you just want to use one matrix for segment data you can do this:


ORMASK = SEGVAL[x] & %00011111 / makes sure only 5 lsb of SEGVAL[x] '1' bits get set below
PORTC = PORTC & %11100000 / Clear all the bits in PORTC that are segments
PORTC = ORMASK | PORTC / sets the bits in PORTC that are '1' in AVAL[x]

ORMASK = SEGVAL[x] >> 4 / shift data 4 to right to position correct SEGVAL[x] bits for PORTA
ORMASK = ORMASK & %0000110 / makes sure only 2 bits of SEGVAL[x] '1' bits get set below
PORTA = PORTA | %11111001 / Clear all the bits in PORTA that are segments
PORTA = ORMASK | PORTA / sets the bits in PORTC that are '1' in AVAL[x]

mister_e
- 18th April 2008, 21:05
Yup, mine is just in case something is badly define in the array, unless

PORTA = (PORTA & %11111001) | AVAL[COUNTERA]
PORTC = (PORTC & %11100000) | CvAL[CounterA]

Would work anyways.

xnihilo
- 19th April 2008, 00:17
Hello,

Thank you for this information.
Bitwise operations are less simple than I thought but are necessary :)

mister_e
- 19th April 2008, 00:24
Nah not that complicated.. but once you get them they're pretty handy.
http://en.wikipedia.org/wiki/Bitwise_operation