using picc on a pic1f627

Discussion in 'C Programming' started by Andre, May 17, 2012.

  1. Andre

    Andre Guest

    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é
    Andre, May 17, 2012
    #1
    1. Advertising

  2. Andre

    Guest

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

    <snip>

    > 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
    , May 17, 2012
    #2
    1. Advertising

  3. Andre

    Willem Guest

    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
    Willem, May 17, 2012
    #3
  4. Andre

    Lanarcam Guest

    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.
    Lanarcam, May 17, 2012
    #4
  5. Andre

    BartC Guest

    "Andre" <> wrote in message
    news:4fb4b7b4$0$3115$...
    > 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).

    --
    Bartc
    BartC, May 17, 2012
    #5
  6. Andre

    Paul Guest

    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?
    >
    > 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
    Paul, May 17, 2012
    #6
  7. Andre

    Andre Guest

    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é
    Andre, May 18, 2012
    #7
  8. Andre

    BartC Guest

    "Andre" <> wrote in message
    news:4fb60737$0$3112$...
    > 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.


    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.

    --
    Bartc
    BartC, May 18, 2012
    #8
  9. Andre

    Andre Guest

    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.
    Andre, May 18, 2012
    #9
  10. Andre

    BartC Guest

    "Andre" <> wrote in message
    news:4fb67a0d$0$3123$...

    > 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.

    --
    Bartc
    BartC, May 18, 2012
    #10
  11. [crosspost to c.a.e. as more appropriate group]

    On 2012-05-17, 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?


    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.

    --
    Andrew Smallshaw
    Andrew Smallshaw, May 18, 2012
    #11
  12. Andre

    Andre Guest

    Le 18/05/2012 18:34, Andre a écrit :
    > 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.


    Before anything else
    I didn't invent it my self I found this on:
    http://www.microchipc.com/HiTechCFAQ/
    André
    Andre, May 19, 2012
    #12
  13. Andre

    Thad Smith Guest

    On 5/18/2012 3:42 PM, Andrew Smallshaw wrote:
    > [crosspost to c.a.e. as more appropriate group]
    >
    > On 2012-05-17, 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?

    >
    > 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.

    --
    Thad
    Thad Smith, May 24, 2012
    #13
  14. 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

    --
    From-address is Spam trap
    Use: wolfgang (dot) mahringer (at) sbg (dot) at
    Wolfgang Mahringer, May 25, 2012
    #14
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. William F. Robertson, Jr.
    Replies:
    1
    Views:
    969
    Kathy Burke
    Jun 25, 2003
  2. pete
    Replies:
    1
    Views:
    2,933
    Jon Yates
    Aug 29, 2003
  3. timmso
    Replies:
    1
    Views:
    477
    Alex Papadimoulis
    Dec 12, 2003
  4. Replies:
    2
    Views:
    543
  5. Andras Tantos

    Are bit-variables in PICC a good idea

    Andras Tantos, Jan 12, 2004, in forum: C Programming
    Replies:
    3
    Views:
    531
    Dave Hansen
    Jan 12, 2004
Loading...

Share This Page