This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

GPIO pullups and direction

If I write a zero to the output register, and enable the pullup on the same pin, can I switch between driven low output and input with pullup simply by settting/clearing the DIR bit? Will the pullup still be in circuit when the output is enabled? I have studied the datasheet and the associated schematic, but this is still not clear to me.

  • I have tried the both ,

    NRF_GPIO->DIRSET |= (1UL << LED_1);
    NRF_GPIO->PIN_CNF[LED_1] |=  GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos;	
    
    NRF_GPIO->DIRSET &= ~(1UL << LED_1);
    

    NRF_GPIO->DIRSET &= ~(1UL << LED_1);
    NRF_GPIO->PIN_CNF[LED_1] |=  GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos;	
    
    NRF_GPIO->DIRSET |= (1UL << LED_1);
    while(1);
    

    and the pullup wasn't there. So i am concluding that it will be reset to no_pull everytime we change pin direction

  • Thanks for the answer, but I have to say that sounds like a crazy system to me! Some things about the nRF51822 are great, others, like this and the compromised PWM capability, are not so great.

  • I think this came as a side effect of being able to set direction either from DIR register or in PIN_CNF register. i will bring this to notice of right people.

  • I think you are using the wrong register. It should be DIR, rather than DIRSET. I just wrote the following snippet of code:

    NRF_GPIO->DIR &= ~(1UL << BUTTON_NORTH);		// Set as ip
    NRF_GPIO->PIN_CNF[BUTTON_NORTH] |= GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos; // Set pullup
    
    SEGGER_RTT_printf(0, "PIN_CNF = %08x\n\r", NRF_GPIO->PIN_CNF[BUTTON_NORTH]);
    NRF_GPIO->DIR |= (1UL << BUTTON_NORTH);		// Set as op
    SEGGER_RTT_printf(0, "PIN_CNF = %08x\n\r", NRF_GPIO->PIN_CNF[BUTTON_NORTH]);
    NRF_GPIO->DIR &= ~(1UL << BUTTON_NORTH);		// Set as ip
    SEGGER_RTT_printf(0, "PIN_CNF = %08x\n\r", NRF_GPIO->PIN_CNF[BUTTON_NORTH]);
    

    and the output on the Segger RTT shows the PIN_CNF rgister to be: 0x0000000e 0x0000000f 0x0000000e

    So I believe the pullup does persist if you use the DIR register to chage direction.

    I will re-write this to use the DIRSET and DIRCLR registers...

    while(1);
    
  • NRF_GPIO->DIRCLR = (1UL << BUTTON_NORTH); // Set as ip NRF_GPIO->PIN_CNF[BUTTON_NORTH] |= GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos; // Set pullup

    SEGGER_RTT_printf(0, "PIN_CNF = %08x\n\r", NRF_GPIO->PIN_CNF[BUTTON_NORTH]);
    NRF_GPIO->DIRSET = (1UL << BUTTON_NORTH);		// Set as op
    SEGGER_RTT_printf(0, "PIN_CNF = %08x\n\r", NRF_GPIO->PIN_CNF[BUTTON_NORTH]);
    NRF_GPIO->DIRCLR = (1UL << BUTTON_NORTH);		// Set as ip
    SEGGER_RTT_printf(0, "PIN_CNF = %08x\n\r", NRF_GPIO->PIN_CNF[BUTTON_NORTH]);
    
    while(1);
    

    0> PIN_CNF = 0000000E 0>
    PIN_CNF = 0000000F 0>
    PIN_CNF = 0000000E 0>

Related