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

change DCCH to 3.3V uart not work

Hello,

SDK17.2, Keil5, nRF21540-DK,

        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}

        NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) |
                            (UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos);

        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}

        // System reset is needed to update UICR registers.
        NVIC_SystemReset();

when change DCCH to 3.3V as above codes in main first,

(1). the uart will can not work ,

(2). change pin to high voltage as follow two lines not working;

nrf_gpio_cfg_output(0x24); 
nrf_gpio_pin_set(0x24);

     

Did I write change to 3V3 codes wrong?

           

Best regards

Parents
  • Hi,

    Can you explain what you mean by "uart will can not work"? What device are you communication with through the UART peripheral?

    change pin to high voltage as follow two lines not working;

    nrf_gpio_cfg_output(0x24); 
    nrf_gpio_pin_set(0x24);

    What is not working? Do the pin not get set as you expect? Did you measure the GPIO/VDD voltage using a voltmeter?

    Have you made sure that the UICR->REGOUT0 register is erased before writing the UICR_REGOUT0_VOUT_3V3 value? The UICR registers works like flash, which means that bits can only be written from 1 to 0, not from 0 to 1. Changing a bit from 0 to 1 requires you to erase the full UICR. If REGOUT0 already contains another value, you may end up in a situation where you write the register to an unsupported value.

    Note that the nRF21540 DK will work in normal voltage mode when powered through the J2 USB connector. In this mode, the nRF52840 chip will be powered by a 3V regulator, and the REGOUT0 register config will not have any effect. See nRF21540 and nRF52840 power source for more details.

    Best regards,
    Jørgen

Reply
  • Hi,

    Can you explain what you mean by "uart will can not work"? What device are you communication with through the UART peripheral?

    change pin to high voltage as follow two lines not working;

    nrf_gpio_cfg_output(0x24); 
    nrf_gpio_pin_set(0x24);

    What is not working? Do the pin not get set as you expect? Did you measure the GPIO/VDD voltage using a voltmeter?

    Have you made sure that the UICR->REGOUT0 register is erased before writing the UICR_REGOUT0_VOUT_3V3 value? The UICR registers works like flash, which means that bits can only be written from 1 to 0, not from 0 to 1. Changing a bit from 0 to 1 requires you to erase the full UICR. If REGOUT0 already contains another value, you may end up in a situation where you write the register to an unsupported value.

    Note that the nRF21540 DK will work in normal voltage mode when powered through the J2 USB connector. In this mode, the nRF52840 chip will be powered by a 3V regulator, and the REGOUT0 register config will not have any effect. See nRF21540 and nRF52840 power source for more details.

    Best regards,
    Jørgen

Children
  • Hi,

    thanks for reply,

    full project code:

    void gpio_output_voltage_3v3()
    {
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
        NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) |
                            (UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos);
    
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
        // System reset is needed to update UICR registers.
        NVIC_SystemReset();
    }
    int main(void)
    {
    	gpio_output_voltage_3v3(); //1V8 change to 3V3
    	
    	nrf_gpio_cfg_output(0x24);
    	nrf_gpio_pin_set(0x24); //pull high
    	
    	uint32_t err_code=0;
    	const app_uart_comm_params_t comm_params =
    	{
    			RX_PIN_NUMBER,
    			TX_PIN_NUMBER,
    			NULL,NULL,
    			APP_UART_FLOW_CONTROL_DISABLED,
    			false,
    			NRF_UART_BAUDRATE_115200
    	};
    	APP_UART_FIFO_INIT(&comm_params,
    											 UART_RX_BUF_SIZE, UART_TX_BUF_SIZE,
    											 uart_error_handle, APP_IRQ_PRIORITY_LOWEST,
    											 err_code);
    	APP_ERROR_CHECK(err_code);
    
    	printf("Btest start......\r\n");
    
    	while(1)
    	{
    		app_uart_put('s');
    		nrf_delay_ms(1500);
    	}
    	return 0;
    }
    

    uart device is usb serial port for windows, it work well when default DCCH 1.8V vlotage.

    windows can recive logs:

    nrf_gpio_pin_set(0x24);  the pin 0x24 voltage is 3.25V.

      -------------------------------------------------------------------------------------------------

    Did you measure the GPIO/VDD voltage using a voltmeter? yes

    when change DCCH to 3.3V as above codes in main first,

    (1). the uart will can not recive logs ,

    (2). nrf_gpio_pin_set(0x24);  the pin 0x24 voltage is 0V.

       

    Have you made sure that the UICR->REGOUT0 register is erased before writing the UICR_REGOUT0_VOUT_3V3 value? i don't konw how to make sure it,please see full code above.

        

    Best regards

  • It looks like you do not have any checks for what value the REGOUT0 register contains in your code, you are just writing it in gpio_output_voltage_3v3(), then doing a system reset. With this code, you will never get past this function, as it will always be executed at the start of the code, and do a reset, which will lead to the function being called once more. To resolve this, you need to read out the value of REGOUT0 register, compare it to your wanted value, and only write/reset if the value is not what you want it to be. This is implemented in the SDK for the nRF52840 Dongle:

    #if defined(BOARD_PCA10059)
    /**
     * Function for configuring UICR_REGOUT0 register
     * to set GPIO output voltage to 3.0V.
     */
    static void gpio_output_voltage_setup(void)
    {
        // Configure UICR_REGOUT0 register only if it is set to default value.
        if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) ==
            (UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos))
        {
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
            NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) |
                                (UICR_REGOUT0_VOUT_3V0 << UICR_REGOUT0_VOUT_Pos);
    
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
            // System reset is needed to update UICR registers.
            NVIC_SystemReset();
        }
    }
    #endif

    You can read out the value of the REGOUT0 register using nrfjprog:

    $ nrfjprog --memrd 0x10001304
    0x10001304: FFFFFFFF                              |....|

  • Hi,

    thanks for reply

    your mean as follow?

    i'm sorry, i made a low-level mistake.

      

    Best regards

  • You should check that is is not equal to the value you want to write (or preferably check if it is the default, and report an error if it is not the default or your expected value, as this indicates some problem with erasing board or something similar).

Related