• AVR Freaks

Hot!Assigning a PORT pin to pointer or variable: How can that be done?

Page: 1234 > Showing page 1 of 4
Author
user2x
Super Member
  • Total Posts : 352
  • Reward points : 0
  • Joined: 2011/02/10 20:43:36
  • Location: 0
  • Status: offline
2019/10/28 14:54:54 (permalink)
0

Assigning a PORT pin to pointer or variable: How can that be done?

Hello
 
I have led output pins that depend on the system configuration.
 
for example:
 
 
These 2 pins are are defined as: 

#define   LED_RED_PIN       LATAbits.LATA1
#define   LED_WHITE_PIN    LATBbits.LATB4

 
Only one LED gets used, depending on the system configuration. 
So for system config A, it needs to use the LED_RED_PIN   and for config B it needs LED_WHITE_PIN
 
Is there a way to assign the pin definition, in this case LATBbits.xx, to some sort of pointer or variable so I can just assign tit once and the resst of the code can just se the variable?
 
Such as:
This outline the principle of what I want to do but it obviously can't work like that. 

void test(void)
{
    ????type pMainLed;
 
    pMainLed = &LED_RED_PIN;     //assign desired led to ??type pointer or something
    while(1)
    {
        //toggle the led
 
        *pMainLed  = 1;  //led on 
        *pMainLed  = 0;  //led off
    }
}

 
 
 
 
 
post edited by user2x - 2019/10/28 14:59:03
#1

73 Replies Related Threads

    Ian.M
    Super Member
    • Total Posts : 13268
    • Reward points : 0
    • Joined: 2009/07/23 07:02:40
    • Location: UK
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/10/28 15:03:02 (permalink)
    +1 (1)
    No.  A C pointer cant point to anything with finer granularity than a byte, and not even that on systems that have char type larger than than eight bits.
     
    http://www.xargs.com/pic/c-faq.html#pinarray
    (Although the Xargs PIC C FAQ targets 8 bit PICs, you've asked a question where it applies to any processor without special hardware provision for one address per bit access.)
     
    post edited by Ian.M - 2019/10/28 15:08:25

    --
    NEW USERS: Posting images, links and code - workaround for restrictions.
    I also support http://picforum.ric323.com because this forum is sometimes too broken to use!
    #2
    ric
    Super Member
    • Total Posts : 24638
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/10/28 15:07:09 (permalink)
    0
    user2x
    ...
    Is there a way to assign the pin definition, in this case LATBbits.xx, to some sort of pointer or variable so I can just assign tit once and the resst of the code can just se the variable?

    No.
    XC16 has no bit type, and certainly no way to have a pointer to one.
    Your two choices are
    [1] Use a function to set/clear/test the bit, which checks which version to use.
     
    [2] Save both a pointer to the PORT, and a mask for the selected bit, and always access using these.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #3
    NorthGuy
    Super Member
    • Total Posts : 5817
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/10/28 15:20:53 (permalink)
    +1 (1)
    You can use a structural type if you wish. This is going to be terribly inefficient though. A la:
     
    typedef struct {
      volatile unsigned char *port;
      volatile unsigned char *lat;
      volatile unsigned char *tris;
      volatile unsigned char *ansel;
      volatile unsigned char *wpu;
    } port_t, *pport_t;

    typedef struct {
      pport_t port;
      unsigned char mask;
    } pin_t, *ppin_t;

    port_t portA = {&PORTA, &LATA, &TRISA, &ANSELA, &WPUA};
    port_t portB = {&PORTB, &LATB, &TRISB, &ANSELB, &WPUB};
    port_t portC = {&PORTC, &LATC, &TRISC, &ANSELC, &WPUC};
    port_t portD = {&PORTD, &LATD, &TRISD, &ANSELD, &WPUD};
    port_t portE = {&PORTE, &LATE, &TRISE, &ANSELE, &WPUE};
    port_t portF = {&PORTF, &LATF, &TRISF, &ANSELF, &WPUF};
    port_t portG = {&PORTG, &LATG, &TRISG, &ANSELG, &WPUG};
     
    pin_t LED = {&portB, 1 << 0};

    void pset(ppin_t p) {
      *p->port->lat |= p->mask;   
    }

    void pclear(ppin_t p) {
      *p->port->lat &= ~p->mask;
    }

    uint8_t pread(ppin_t p) {
      return !!(*p->port->port & p->mask);
    }

    void pout(ppin_t p) {
      *p->port->tris &= ~p->mask;   
    }

    void pin(ppin_t p) {
      *p->port->tris |= p->mask;   
    }

     
    #4
    user2x
    Super Member
    • Total Posts : 352
    • Reward points : 0
    • Joined: 2011/02/10 20:43:36
    • Location: 0
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/10/28 15:34:51 (permalink)
    0
    Ok, I was afraid of that.
    I will try a port and mask then.
     
    That type do I declare a SFR pointer  such as LATA?
     
    Is it just a memory address and the type is uint16_t since the registers are 16 bits wide?
     
    I need it to be efficient as I have to bitbang PWM out of these LED pins as well and there are 9 of them.
     
     
     
    #5
    ric
    Super Member
    • Total Posts : 24638
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/10/28 15:45:54 (permalink)
    0
    Most efficient way would be to totally duplicate the PWM routines, one for each version.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #6
    DuaneH
    New Member
    • Total Posts : 13
    • Reward points : 0
    • Joined: 2009/10/15 11:49:22
    • Location: Sandy, UT
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/10/28 15:57:06 (permalink)
    0
    Try this:  Declare a macro (in my example, TYPE) which defines what version you're building for, then:
    #if TYPE==1
    #define LED_PIN LATAbits.LATA1
    #endif
    #if TYPE==2
    #define LED_PIN LATBbits.LATB4
    #endif
    Notice that there's no color associated with LED_PIN, so you use it everywhere, and it changes depending on TYPE
    Declare TYPE at the top of your main header file.

    duaneh
    #7
    ric
    Super Member
    • Total Posts : 24638
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/10/28 16:00:17 (permalink)
    0
    I assumed the one build had to support both configurations.
    Of course, if you can recompile the code for each configuration, it's trivial.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #8
    NorthGuy
    Super Member
    • Total Posts : 5817
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/10/28 16:05:37 (permalink)
    0
    If you want efficiency, put all the LEDs on the same port. Then it's only the mask which is different. Moreover, you can set all the LEDs in one instruction.
     
    LEDs are slow so you don't need too much efficiency. If you switch at 100 Hz and need 256 bit resolution, it's only 25 kHz. You'll have plenty of time in the interrupt to set all your LEDs.
    #9
    user2x
    Super Member
    • Total Posts : 352
    • Reward points : 0
    • Joined: 2011/02/10 20:43:36
    • Location: 0
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/10/28 16:14:23 (permalink)
    0
    ric
    Most efficient way would be to totally duplicate the PWM routines, one for each version.
     

     
    I kind of agree but I have 7 configurations with 9 leds to drive.
    You assumed correctly in that the config can change on the fly.
     
    Currently they work like this (there is only one config at the moment) but it is very inefficient.

      LED_SW2_WHITE_PIN = (Timer2_GetCount() <= led_duty_cycle[LED_SW2_WHITE_BIT_IDX]) ? 1 : 0;
      LED_SW3_BLUE_PIN = (Timer2_GetCount() <= led_duty_cycle[LED_SW3_BLUE_BIT_IDX]) ? 1 : 0;
      ....
     

     
    There is other time critical stuff happening so I can't waste much CPU time on doing led stuff.
    #10
    DuaneH
    New Member
    • Total Posts : 13
    • Reward points : 0
    • Joined: 2009/10/15 11:49:22
    • Location: Sandy, UT
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/11/14 13:52:33 (permalink)
    0
    You have a whole lot of de-referencing going on!  Is there any way you could assign the LED output to a PWM function and then just write the PWM value to (for example using Output compare 2) OC2R? The PWM percentage will be OC2R / PR2.
     
    From that point on, the hardware takes over and no processor time is involved at all.  If you need to change the brightness, you can periodically change the value.  It's only 1 write to change the value, so almost no overhead.
     
    Sample:
    //*******************************************************************
    //t2init:
    void t2init (void)
    /* This is the PWM timer */
    {
    T2CON = 0; // 1:1 prescale; off by default
    TMR2 = 0;
    PR2 = _32000; // sets cycle time (16000 = 1 ms)
    IPC1bits.T2IP = 0; // no ints
    T2CON |= 0x8000;
    _t2ie = 0;
    _t2if = 0;
    }
     
    Then once OC2R is set to the needed value invoke PWM mode (OC2CON1 = 6) and you're up and running.

    duaneh
    #11
    Sandra232
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/11/12 17:27:16
    • Location: 0
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/11/14 14:59:21 (permalink)
    +1 (1)
     A C pointer cant point to anything with finer granularity than a byte
    #12
    user2x
    Super Member
    • Total Posts : 352
    • Reward points : 0
    • Joined: 2011/02/10 20:43:36
    • Location: 0
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/11/15 13:15:15 (permalink)
    0
    Sandra232
     A C pointer cant point to anything with finer granularity than a byte


    There are controllers (PICs?) with bit addressabe ports. Each bit has a register address.
    I guess this is not one of them. 
     
    I have never fully understood why
    LATAbits.LA5 not be assigned to something such as
    Pseudo code...
     

    LATAbits_t  portbits = LATAbits
    uint16_t pin = 5
     
    portbits.pin = 1

     
     
    post edited by user2x - 2019/11/15 13:22:38
    #13
    ric
    Super Member
    • Total Posts : 24638
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/11/15 13:42:49 (permalink)
    0

    There are controllers (PICs?) with bit addressabe ports. Each bit has a register address.
    I guess this is not one of them.

    No PIC device can do it.
    There may be some (non PIC device) that can. Can you specify one you know of?
    More likely there are some compiler shenanigans going on in the background to simulate the behaviour.
     

    I have never fully understood why
    LATAbits.LA5 not be assigned to something such as

    Because the hardware cannot do it.
    i.e. it cannot do a BCF or BSF instruction on a variable address, only an address that is known at compile time, because that is how the hardware works.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #14
    _fragment_
    Super Member
    • Total Posts : 406
    • Reward points : 0
    • Joined: 2008/10/08 09:17:55
    • Location: Idaho
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/11/15 13:48:04 (permalink)
    0
    Then you've never studied how data structures and pointers work in C.
    #15
    user2x
    Super Member
    • Total Posts : 352
    • Reward points : 0
    • Joined: 2011/02/10 20:43:36
    • Location: 0
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/11/15 14:17:26 (permalink)
    0
    _fragment_
    Then you've never studied how data structures and pointers work in C.

    Don't be so harsh. Why not present an explanation or a solution?
     
    @ric   They definitely exist and I have used them. Perhaps it was 8051? Or AVR.
    I have worked with so many CPUs over the years.
    Atmel has clear and set registers for most registers which is also a major improvement as one can just use a mask to control bits without affecring other bits.
    #16
    user2x
    Super Member
    • Total Posts : 352
    • Reward points : 0
    • Joined: 2011/02/10 20:43:36
    • Location: 0
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/11/15 14:21:33 (permalink)
    +1 (1)
    @ric
    8051. I just ckecked.
    #17
    ric
    Super Member
    • Total Posts : 24638
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/11/15 14:24:24 (permalink)
    0
    user2x
    Atmel has clear and set registers for most registers which is also a major improvement as one can just use a mask to control bits without affecring other bits.

    You can use masks on registers on almost any PIC. That requires converting a bit number to a mask though.
    The only limitation there is manipulating PORT bits on old PIC16F parts which lack LAT registers.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #18
    user2x
    Super Member
    • Total Posts : 352
    • Reward points : 0
    • Joined: 2011/02/10 20:43:36
    • Location: 0
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/11/15 14:30:06 (permalink)
    0
    ric
    user2x
    Atmel has clear and set registers for most registers which is also a major improvement as one can just use a mask to control bits without affecring other bits.

    You can use masks on registers on almost any PIC. That requires converting a bit number to a mask though.
    The only limitation there is manipulating PORT bits on old PIC16F parts which lack LAT registers.
     




    Yes but you have to read, modify write.
    On Atmel all you do is PORTASET= 0x0012 and bit 8 and 1 will set with nothing else affected. Likewise PORTACLR = 0x0012 will clear the 2 bits nothing else affected.
    But we digress..
     
     
    #19
    _fragment_
    Super Member
    • Total Posts : 406
    • Reward points : 0
    • Joined: 2008/10/08 09:17:55
    • Location: Idaho
    • Status: offline
    Re: Assigning a PORT pin to pointer or variable: How can that be done? 2019/11/15 14:38:24 (permalink)
    0
     
    user2x
    Yes but you have to read, modify write.
    On Atmel all you do is PORTASET= 0x0012 and bit 8 and 1 will set with nothing else affected. Likewise PORTACLR = 0x0012 will clear the 2 bits nothing else affected.
    But we digress..

     
    PIC32 has a similar feature. I miss it when programming PIC24.
    #20
    Page: 1234 > Showing page 1 of 4
    Jump to:
    © 2019 APG vNext Commercial Version 4.5