This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

passing a port/pin to a function

hi,

i have a question regarding passing a port/pin to a function.

i have written a piece of code as below

#define LED_PIN P1_0 // bit LED_PIN = P1_0 also does not work

void blink(bit pin, int delayTime, int blinkCount)
{ while( --blinkCount ) { pin = !pin ; delay(delayTime) ; // function to generate delay...this works fine }
}

void main()
{ blink( LED_PIN, 1000, 10 ) ;
}

this also does not work if i code the blink function as a macro.

is there any way i can pass the address/pin name to the function? i am using keil compiler for 89C51 MCU.

Parents Reply Children
  • is there any way i can pass the address/pin name to the function?
    no, but you cn pass a mask

    you want void setpin(port, bit) setpin(2,1)
    which you can't do

    what you can do is
    void setpin(port, mask) setpin(2,0x02)
    switch port
    case 2:
    orl p2,mask

  • Tut - you slipping into textspeak there, Erik...?

    You could also use a bit index in place of a mask:

    void setpin( port_num, bit_index )
    {
      switch port_num
      {
        case 2:
           P2 |= ( 1 << bit_index );
    

  • you slipping into textspeak there, Erik
    yes, when showing the principle with "textspeak" rather than "usable code" insignificant misses are a non-issue. Once posting code I forgot a ';' and the rest of the thread was about that. Anyhow IMHO showing the principle is more important than reply format. Now we can, of course, expect a post discussing that you forgot () around port_num
    at the switch :)

  • And Andy didn't specify the data types for the parameters...

    Anyway - I haven't really seen an issue with posting "real" code. I don't think any thread where I have posted code have ended up debating any spelling errors - and spelling errors are likely since I normally code suggestions on-the-fly in the text box in a "best-effort" way.

    The only time I think it's important to be exact, is when people posts code and asks why the compiler protests, or why the program does the wrong thing. Then it's important that the code we read is 100% the same as the code the compiler got to work on, since a minor typo might be the whole reason for the incorrect outcome. And not all spelling errors gets caught by the compiler - lots of C expressions are valid even if meaningless.

  • The only time I think it's important to be exact ...

    I'm sure we're all immensely glad that you have given your diktat on the matter.

  • hi andrew,

    thanks for your reply. i should have gone to the basics. i was just a little lazy :)...sorry

    i will go through the rest of the documents as well...

    But i guess the compiler could've taken care of this issue? Or is this a problem with all compilers for the 8051 architecture?

    My knowledge of compilers is limited but i just thought that the compiler could check which pin should be set(for example) and generate appropriate code using the OR instruction?

    for example if i write a function to set a particular bit

    void set(bit Pin)
    { Pin = 1 ;
    }

    void main()
    {

    set(P1_0) ;
    }

    then the instruction for this would be ORL P1, #01H

    Just a thought...i may be getting away from my original question.

  • hi Erik,

    Thanks for your reply.

    i like your solution and i will use it.

    Just a thought instead of passing the mask value I will calculate the mask in the function itself.

    something like

    #define LED_PIN 2,3 //similar to P2_3

    void setpin(int port, int pin)
    { switch( port ) { case 2 : P2 |= (0x01 << pin) ; break ; }
    }

    void main()
    { setpin(LED_PIN) ;
    }

    i havent compiled and tested this code yet but i think it will work.

    thanks!

  • But let's say you extend your code into:

    void set(bit Pin) {
        Pin = 1;
    }
    
    void main() {
        set(P1_0);
        set(P1_7);
        set(P3_4);
    }
    

    What code would the compiler then have generated inside te set() function?

    Note that set() is a function - but it isn't an inline function. So the compiler will call a same single function implementation to perform the task. So the compiler would then have to speculatively generate code where you don't send a bit but the integer representing the address of a bit. And it would then have to use conditional code that translate this address into fixed byte-sized operations on all bit-addressable bytes to fake an indirect access. This would require large and slow code. But that would then still have required that set() had taken a pointer to a bit as parameter - because call-by-value doesn't allow you to modify the original parameter. Without call-by-value, set(P1_1) does not mean "set the pin P1:1" but only means "send the current value of P1:1 into the function set()". Only the caller would known that the address of a specific port bit was actually involved.

    If you had instead created a #define macro, then the compiler would have been able to directly expand that macro on every use and so directly insert the address of the individual bits.

    Note another thing - since the processor can't do indexed accesses to bit variables, the compiler can't implement stack-relative bit parameters or auto bit variables. So the compiler will have to fake things with global bit variables - this would work as long as you don't try recursion. And "passing a bit" means copying the source bit value into the hard-coded global bit "parameter" that the function then knows how to address.

    So while the native atomic bit operations are magnificent, they do come with the limitation that the developer must understand the processor limitations and develop the software around these limitations. The alternative would have to be to strictly follow the C language standard - and totally miss out on the best feature of the 8051 chips. Keil is "an ARM company", but it took ARM half a lifetime to give us ARM chips with a decent alternative to the single-bit functionality the 8051 chips have had since day one.

  • But fixing the port & pin like that at compile time rather defeats the object of having a function - doesn't it?

    You might just as well have

    #define LED_PORT P2
    #define LED_PIN  3
    
    #define SET_LED LED_PORT |= ( 1 << LED_PIN )
    

  • very true...i didnt give it much thought earlier...i understand it perfectly now.

    thanks for your detailed explanation.

    But i had coded the function as a macro and in that case it did not work either...that had me wondering for a while...i will try again later ofcourse and let you know if it works as a macro.

  • @Erik

    yes! i can code it as a macro then...no need for a function...

    thanks!!!

  • Refer some good book on embedded C and/or C coding for 8051