1. This forum section is a read-only archive which contains old newsgroup posts. If you wish to post a query, please do so in one of our main forum sections (here). This way you will get a faster, better response from the members on Motherboard Point.

convert 16 bit port to Char

Discussion in 'Embedded' started by Thomas Magma, Jul 3, 2008.

  1. Thomas Magma

    Thomas Magma Guest

    Hello,

    I'm programming in C on a dsPIC33F and I'm trying to find the most efficient
    way to save a 8-bit signed value found on the LSByte of PORTD to a CHAR.
    That is, the lower byte of PORTD contains a signed integer that is 8-bits
    wide and I need to save it to a CHAR data type. I don't care what is on the
    upper byte of PORTD.

    What would be the most efficient way to do this?

    Thanks.

    Thomas
     
    Thomas Magma, Jul 3, 2008
    #1
    1. Advertisements

  2. Just read the value and assign it to a char variable. Assuming you do
    not need to do anything special to access the port:

    #define INT16 [put right type here]

    INT16 * port_d = [put address of PORTD here];
    char c;

    ....
    c = *port_d;
    ....
     
    Roberto Waltman, Jul 3, 2008
    #2
    1. Advertisements

  3. Thomas Magma

    Frank Buss Guest

    You should use typedef instead of #define
    You should add a cast to avoid compiler warnings for C compilers:

    INT16* port_d = (INT16*) [put address of PORTD here];

    In C++ not adding a cast would be an error.
     
    Frank Buss, Jul 3, 2008
    #3
  4. Thomas Magma

    Thomas Magma Guest

    ... I'm trying to find the most efficient
    Thanks Roberto, I guess this would make sense if the data representation of
    the dsPIC33 using the C30 compiler was stored in little endian format. Do
    you know if it is for sure?

    Thomas
     
    Thomas Magma, Jul 3, 2008
    #4
  5. Thomas Magma

    Frank Buss Guest

    This would be a problem, if you access a union or cast the int* to char*,
    but if you first read the int* and then assign it to an char, endian
    doesn't matter, the lower 8 bits are used all the time, which is what you
    asked for. Of course, if you read the 16 bit value from PORTD, endian could
    be a problem.
     
    Frank Buss, Jul 3, 2008
    #5
  6. Thomas Magma

    Frank Buss Guest

    This depends on the compiler. E.g. with GCC 3.4.4 it is a warning, but with
    ICC08 6.11 it is an error.
     
    Frank Buss, Jul 4, 2008
    #6
  7. Thomas Magma

    ChrisQ Guest

    Better still: c = (char) *port_d;

    It may work, but you may get a warning. Always using a cast sends
    a hint to the compiler and makes it clear when reading the code what is
    actually being done. To be absolutely correct you should have a (const
    *) when loading the absolute address and cast this to the pointer type
    as well.

    This is the sort of construct I usually use:

    volatile U16 *pu16RegisterPtr = (U16 * const) REGISTER_ADDRESS;

    Got this originally from Harbison & Steele and it seems to be correct.
    The volatile keyword is telling the compiler that no part of the
    expression should be changed or optimised in any way, while the const
    keyword tells the compiler that this is, as expected a fixed value.

    Chris
     
    ChrisQ, Jul 4, 2008
    #7
  8. I'll call. Show why exactly this would be an error. And no, examples
    of compilers that refuse to accept this don't count as evidence.
     
    Hans-Bernhard Bröker, Jul 4, 2008
    #8
  9. Thomas Magma

    CBFalconer Guest

    Because the 'address of PORTD' isn't a valid pointer in standard
    C. An address or pointer can involve all sorts of things, such as
    disks, tapes, segments, whatever. If your system has provisions to
    accept such things and convert them to 'pointers' then that
    provision is peculiar to that system. It is NOT portable.
     
    CBFalconer, Jul 5, 2008
    #9
  10. Yes. But C does have implicit conversions from integers to pointers.
    So, while it's not certainly not portable, it's not strictly an error
    either.
     
    Hans-Bernhard Bröker, Jul 5, 2008
    #10
  11. Thomas Magma

    Rich Webb Guest

    I don't have the text of C99 here but from the earlier C89 standard:

    6.3.4
    Conversions that involve pointers (other than as permitted by the
    constraints of 6.3.16.1) shall be specified by means of an explicit cast

    and in 6.3.16.1 Simple Assignment
    Constraints
    One of the following shall hold:
    ....
    - both operands are pointers to qualified or unqualified versions of
    compatible types
    - one operand is a pointer to an object or incomplete type and the other
    is a pointer to a qualified or unqualified version of void ...
    - the left operand is a pointer and the right is a null pointer constant

    The Rationale from both C89 and C99 state that:

    "Since pointers and integers are now considered incommensurate, the only
    integer value that can be safely converted to a pointer is a constant
    expression with the value 0. The result of converting any other integer
    value, including a non-constant expression with the value 0, to a
    pointer is implementation-defined."

    So it sounds like a conforming implementation is not required to accept
    an assignment expression where the left-hand side is a pointer type and
    the right-hand side is an integer type without an explicit cast.
     
    Rich Webb, Jul 5, 2008
    #11
  12. Thomas Magma

    CBFalconer Guest

    Which is what I said, in one form or another, and which you
    snipped. I have restored the 2nd, 3rd, and 4th sentences of my
    message above.
     
    CBFalconer, Jul 5, 2008
    #12
  13. Now the question is: do these constraints apply before, or after the
    semantics of 6.3.16.1 (C99: 6.5.16.1) have been taken care of? These
    semantics are:

    In simple assignment (=), the value of the right operand is converted to
    the type of the assignment expression and replaces the value stored in
    the object designated by the left operand.

    The conversion of an integer to a pointer is explicitly allowed earlier
    (C99: 6.3.2.3p5). So once that's happened, we're looking at an
    assignment among pointers to compatible types, and all's fine.
    It's implementation-defined, and thus not "safe". But that's not the
    same as being an error. It means that the program isn't fully
    compliant, i.e. it won't be portable.
    I don't see how that follows from the quoted definitions. Please note
    that "implementation-defined result" does _not_ include a compiler
    refusing to translate the source.
     
    Hans-Bernhard Bröker, Jul 6, 2008
    #13
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.