using picc on a pic1f627

A

Andre

First, I am retired and doing all this just for fun ;-) and it's a
looong time since I used C language

I need to write 4 bits to PORTB without disturbing the others bit
RB1, RB2 are ( will be ) used by the UART.
If I Mask 4 bits like CC = CC & 0x0F the upper bits are set to 0 but
still there?

I think I could create a structure ( or a type ) with 4 bits such as
BCD { RB3
RB4
RB5
RB6
}

But I keep trying, no luck ( so far )
Can someone give a hand??
Many thanks in advances
André
 
G

Guest

On Thursday, May 17, 2012 9:32:52 AM UTC+1, Andre wrote:

I need to write 4 bits to PORTB without disturbing the others bit
RB1, RB2 are ( will be ) used by the UART.
If I Mask 4 bits like CC = CC & 0x0F the upper bits are set to 0 but
still there?

lost me. You've cleared (set to zero the top 4 bits). You can't actually /destroy/ bits!
I think I could create a structure ( or a type ) with 4 bits such as
BCD { RB3
RB4
RB5
RB6
}

bitfields. Pretty non-portable. Use masks and shifts
But I keep trying, no luck ( so far )
Can someone give a hand??

void setTopBits (unsigned char new_bits)
{
unsigned char value;
value = read_port (PORT_B);
value &= 0xf; /* clear top bits */
value |= (new_bits << 4); /* set new top bits */
write_port (PORT_B, value);
}

uncompiled. Assumes reading and writing bytes. The code could be more compact.

value = (value & 0xf) | (new_bits << 4);

And setTopBits() is a bit ungeneric
 
W

Willem

Andre wrote:
) First, I am retired and doing all this just for fun ;-) and it's a
) looong time since I used C language
)
) I need to write 4 bits to PORTB without disturbing the others bit
) RB1, RB2 are ( will be ) used by the UART.
) If I Mask 4 bits like CC = CC & 0x0F the upper bits are set to 0 but
) still there?

How does the PIC documentation say you should set/clear bits on a port?
IIRC, it's more complicated than simply setting the port register to
a given value.

If you know how to do it in ASM, it should be easy to transfer that to C,
and if not I'm sure there are people willing to help you with that.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
L

Lanarcam

Le 17/05/2012 10:32, Andre a écrit :
First, I am retired and doing all this just for fun ;-) and it's a
looong time since I used C language

I need to write 4 bits to PORTB without disturbing the others bit
RB1, RB2 are ( will be ) used by the UART.
If I Mask 4 bits like CC = CC & 0x0F the upper bits are set to 0 but
still there?

I think I could create a structure ( or a type ) with 4 bits such as
BCD { RB3
RB4
RB5
RB6
}

The usual way is to define macros, for instance :


#define cbi(portb, bit) ((portb) &= ~(1 << (bit)))

#define sbi(portb, bit) ((portb) |= (1 << (bit)))

cbi stands for clear bit and sbi for set bit.

#define RB3 3 // Bit position 3
#define RB4 4 // Bit position 4
#define RB5 5 // Bit position 5
#define RB4 6 // Bit position 7

volatile uint8_t * const portb = (uint8_t *) 0xfffb1234;

To set RB3 and RB5 :

uint8_t temp = *portb;
sbi(temp,RB3);
sbi(temp,RB5);
*portb = temp;

To clear RB4 and RB6

temp = *portb;
cbi(temp,RB4);
cbi(temp,RB6);
*portb = temp;

By reading first portb (temp = *portb;), you make sure
that you leaves the other bits untouched.
 
B

BartC

Andre said:
First, I am retired and doing all this just for fun ;-) and it's a looong
time since I used C language

I need to write 4 bits to PORTB without disturbing the others bit
RB1, RB2 are ( will be ) used by the UART.
If I Mask 4 bits like CC = CC & 0x0F the upper bits are set to 0 but still
there?

I think I could create a structure ( or a type ) with 4 bits such as
BCD { RB3
RB4
RB5
RB6
}

Forget structs. I assume the device allows you to read and then rewrite
exactly the same bits?

Then, it you want to write bits 5,4,3,2, and leave alone bits 1,0 (ie.
RB6,5,4,3, and leave RB2,1), try:

bcdvalue=7; /* say you want to write binary 0111 to the 'bcd' bits */

CC = (CC&3) | (bcdvalue<<2);

This reads all six bits, clears all except the bottom two, then writes your
pattern into the next 4 bits (bcdvalue has to be shifted up a couple of
bits).

It also clears the top two bits of a presumably 8-bit value. To leave those
top two bits alone, use instead:

CC = (CC&0xC3) | (bcdvalue<<2);

Then maybe put the whole thing into a macro or function called
setbcd(bcdvalue).
 
P

Paul

Andre said:
First, I am retired and doing all this just for fun ;-) and it's a
looong time since I used C language

I need to write 4 bits to PORTB without disturbing the others bit
RB1, RB2 are ( will be ) used by the UART.
If I Mask 4 bits like CC = CC & 0x0F the upper bits are set to 0 but
still there?

I think I could create a structure ( or a type ) with 4 bits such as
BCD { RB3
RB4
RB5
RB6
}

But I keep trying, no luck ( so far )
Can someone give a hand??
Many thanks in advances
André

From a digital logic point of view, you do things
like this with bitwise "AND" and "OR".

You "mask" fields with a bitmask and the "AND" function.
So the "& 0x0F" thing you did, is an example of selecting
the four lowest bits.

Now, imagine you kept a temporary variable, where the upper bits
were a valid copy of the register in question. Or, you were allowed
to do a read on the register right now. To "not disturb the bits",
you could mask with "& 0xF0" , which makes a copy of the upper
four bits of the byte. Next, "OR" together the desired value
for the lower bits, with the output of the "& 0xF0" step.
When written back, the upper bits will not be disturbed, in the
sense that when the register in the UART is written, you'll be
writing back the identical values for the upper bits.

http://cboard.cprogramming.com/c-programming/83723-logical-operation-functions-c;-xor-not-etc.html

"In C you can achieve this by using '&&' for AND, '||' for OR,
'!' for NOT, '^' for XOR, '&' bitwise AND,'|' Bitwise OR ."

http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/BitOp/bitwise.html

Typically, hardware doesn't allow writing to individual bits.
Usually, the hardware has "registers" or groups of bits, and
the registers are a common width. If you have an eight bit
wide register, and you need to write four bits of it,
you simply write identical values to what are already
stored in the other bits.

If the register contains 0x34 right now, and you want to
write a "5" into the lower bits, you mask and make a copy
of the upper bits (giving 0x30) and bitwise OR that with
the 0x05, giving 0x35 as the result. Then write that to
the UART. The "3" part is then undisturbed. It means,
somehow, you have to keep track of the value of the "undisturbed"
section of the register, in order to know it is 0x30 and
the upper part already holds a "3". That could be done with
a temporary variable, or if the hardware allows it, by doing
a read cycle on the register.

HTH,
Paul
 
A

Andre

Le 17/05/2012 10:32, Andre a écrit :
First, I am retired and doing all this just for fun ;-) and it's a
looong time since I used C language

I need to write 4 bits to PORTB without disturbing the others bit
RB1, RB2 are ( will be ) used by the UART.
If I Mask 4 bits like CC = CC & 0x0F the upper bits are set to 0 but
still there?

I think I could create a structure ( or a type ) with 4 bits such as
BCD { RB3
RB4
RB5
RB6
}

But I keep trying, no luck ( so far )
Can someone give a hand??
Many thanks in advances
André


Many thanks to who responded, but
the pic16f627 has a UART and RB1 (RXD ) and RB2 ( TXD ) are the serial
in/out bits. So reading the 'register' is not a very good option has
between the read and the write back the status of TXD and / or RXD may
have changed ( UART is running in interrupt mode) .
For the moment I am more loking into something like:
if ( registerAB0 ) { RB3 = 1 } else { RB3 = 0 }
if ( registerAB1 ) { RB4 = 1 } else { RB4 = 0 }
and so on.
But seems to me, it's only a temporary solution, a better should be found.
André
 
B

BartC

Andre said:
Le 17/05/2012 10:32, Andre a écrit :


Many thanks to who responded, but
the pic16f627 has a UART and RB1 (RXD ) and RB2 ( TXD ) are the serial
in/out bits. So reading the 'register' is not a very good option has
between the read and the write back the status of TXD and / or RXD may
have changed ( UART is running in interrupt mode) .
For the moment I am more loking into something like:
if ( registerAB0 ) { RB3 = 1 } else { RB3 = 0 }
if ( registerAB1 ) { RB4 = 1 } else { RB4 = 0 }
and so on.
But seems to me, it's only a temporary solution, a better should be found.

You might need to read the datasheet for the device more carefully, for
example 5.3 I/O Programming Considerations (on p. 42 of the Microchip docs;
other sources may be different): "Caution must be used when these
instructions are applied to a port with both inputs and
outputs defined."

I don't think this is a C coding problem any more, unless your C compiler
provides more facilities than simply reading or writing a byte from a
memory-mapped port.

Perhaps ask in comp.arch or comp.arch.embedded.
 
A

Andre

Le 17/05/2012 10:32, Andre a écrit :
First, I am retired and doing all this just for fun ;-) and it's a
looong time since I used C language

I need to write 4 bits to PORTB without disturbing the others bit
RB1, RB2 are ( will be ) used by the UART.
If I Mask 4 bits like CC = CC & 0x0F the upper bits are set to 0 but
still there?

I think I could create a structure ( or a type ) with 4 bits such as
BCD { RB3
RB4
RB5
RB6
}

But I keep trying, no luck ( so far )
Can someone give a hand??
Many thanks in advances
André
FYI

I found somthing, not perfect but OK for the moment

unsigned char counter;
#define bit_set(var,bitno) ((var) |= 1 << (bitno))
#define bit_clr(var,bitno) ((var) &= ~(1 << (bitno)))
#define testbit_on(data,bitno) ((data>>bitno)&0x01)

while (1){

if ( testbit_on(counter,3) ) { RB7 = 1; } else { RB7 = 0; }
if ( testbit_on(counter,2) ) { RB6 = 1; } else { RB6 = 0; }
if ( testbit_on(counter,1) ) { RB5 = 1; } else { RB5 = 0; }
if ( testbit_on(counter,0) ) { RB4 = 1; } else { RB4 = 0; }
_delay(10000);
counter++;
if ( counter == 10 ) { counter = 0; }

..
So that seems to work ( At lease with MPLab ;-//
Many thanks
André

BTW: I will bring update on this if there is such interest.
 
B

BartC

I found somthing, not perfect but OK for the moment

unsigned char counter;
#define bit_set(var,bitno) ((var) |= 1 << (bitno))
#define bit_clr(var,bitno) ((var) &= ~(1 << (bitno)))
#define testbit_on(data,bitno) ((data>>bitno)&0x01)

while (1){

if ( testbit_on(counter,3) ) { RB7 = 1; } else { RB7 = 0; }
if ( testbit_on(counter,2) ) { RB6 = 1; } else { RB6 = 0; }
if ( testbit_on(counter,1) ) { RB5 = 1; } else { RB5 = 0; }
if ( testbit_on(counter,0) ) { RB4 = 1; } else { RB4 = 0; }

What are RB4, RB5, RB6 and RB7? Special compiler variables?

Anyway, you can probably simplify:

if ( testbit_on(counter,3) ) { RB7 = 1; } else { RB7 = 0; }

to:

RB7 = testbit_on(counter,3)

etc. Probably there is a way of doing all four bits at once; it depends on
how RB7 etc are implemented.
 
A

Andrew Smallshaw

[crosspost to c.a.e. as more appropriate group]

First, I am retired and doing all this just for fun ;-) and it's a
looong time since I used C language

I need to write 4 bits to PORTB without disturbing the others bit
RB1, RB2 are ( will be ) used by the UART.
If I Mask 4 bits like CC = CC & 0x0F the upper bits are set to 0 but
still there?

By default the I/O ports all default to input mode until pins are
configured as outputs. I don't use C on the smaller PICs, but in
PIC assembler you'd do that by configuring the TRISB register (for
port B) so I would start by looking that up in your compiler
documentation (alternatively it may be down as TRISIO for historical
reasons).

Although I suspect that is your actual problem, there is another
potential issue to catch out the unwary. Regardless of whether
the pin in question is configured as an input or an output any
reads will always refer to the signal on the pin itself - if a
given pin is configured as an output and you write a 0 to it, if
external circuitry drives the pin high you'll get a 1 back when
you read the port.

Finally, you don't need to worry about treating the pins with
special peripherals on them with kid gloves - if the peripheral in
question is in use the peripheral will over-ride the corresponding
slot in PORTB - any changes to the value in PORTB have no effect.
 
A

Andre

Le 18/05/2012 18:34, Andre a écrit :
Le 17/05/2012 10:32, Andre a écrit :
FYI

I found somthing, not perfect but OK for the moment

unsigned char counter;
#define bit_set(var,bitno) ((var) |= 1 << (bitno))
#define bit_clr(var,bitno) ((var) &= ~(1 << (bitno)))
#define testbit_on(data,bitno) ((data>>bitno)&0x01)

while (1){

if ( testbit_on(counter,3) ) { RB7 = 1; } else { RB7 = 0; }
if ( testbit_on(counter,2) ) { RB6 = 1; } else { RB6 = 0; }
if ( testbit_on(counter,1) ) { RB5 = 1; } else { RB5 = 0; }
if ( testbit_on(counter,0) ) { RB4 = 1; } else { RB4 = 0; }
_delay(10000);
counter++;
if ( counter == 10 ) { counter = 0; }

.
So that seems to work ( At lease with MPLab ;-//
Many thanks
André

BTW: I will bring update on this if there is such interest.

Before anything else
I didn't invent it my self I found this on:
http://www.microchipc.com/HiTechCFAQ/
André
 
T

Thad Smith

[crosspost to c.a.e. as more appropriate group]

First, I am retired and doing all this just for fun ;-) and it's a
looong time since I used C language

I need to write 4 bits to PORTB without disturbing the others bit
RB1, RB2 are ( will be ) used by the UART.
If I Mask 4 bits like CC = CC& 0x0F the upper bits are set to 0 but
still there?

By default the I/O ports all default to input mode until pins are
configured as outputs. I don't use C on the smaller PICs, but in
PIC assembler you'd do that by configuring the TRISB register (for
port B) so I would start by looking that up in your compiler
documentation (alternatively it may be down as TRISIO for historical
reasons).

Although I suspect that is your actual problem, there is another
potential issue to catch out the unwary. Regardless of whether
the pin in question is configured as an input or an output any
reads will always refer to the signal on the pin itself - if a
given pin is configured as an output and you write a 0 to it, if
external circuitry drives the pin high you'll get a 1 back when
you read the port.

That's true. The correct way is to modify the LATB, rather than PORTB, to avoid
this problem.
Finally, you don't need to worry about treating the pins with
special peripherals on them with kid gloves - if the peripheral in
question is in use the peripheral will over-ride the corresponding
slot in PORTB - any changes to the value in PORTB have no effect.

An interesting note on this: I was getting a spurious output character on the
TXD line when the RXD line was sampling the input character in autobaud sampling
mode on a PIC16F1938. It turns out that the PIC was disabling the transmit
circuit for the duration of the sample period and the corresponding output latch
(for when the pin wasn't configured as TXD) had a zero bit, causing an
8-bit-time low pulse. The fix? Set the port bit to 1.
 
W

Wolfgang Mahringer

Hi,

Am 24.05.2012 05:22, schrieb Thad Smith:
That's true. The correct way is to modify the LATB, rather than PORTB,
to avoid this problem.

Unfortunately, there is no such thing like a "LATB" register on a
16F627...

If the OP really needs to know the latch value, he needs to keep a
copy of it in a file register.

Cheers,
Wolfgang
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top