Creating clock signal for another IC using PWM

Hi

I attempted to create a 32.768 kHz signal from the nRF52840. When I use the HF external clock: NRF_CLOCK->TASKS_HFCLKSTART = 1; the generated clock signal looks great using a oscilloscope. The mean is correct and a std. deviation of slightly less than 1 Hz. The receiving chip requires the clock value with an interval of +- 3 Hz.

The reasoning behind creating the signal from the nRF is that the receiving chip doesn't support a crystal, which means it needs a crystal oscillator which is expensive both with regard to cost and real estate.

However, I don't really know the implications of doing this. Will this be usable in a production?

I am not using Bluetooth on the chip, and the increase in current consumption is not an issue wrt to the power supply.

  • Hello,

    How do you generate the clock signal that you output?

    Depending on what else you intend to do, you may want to offload the CPU by using something called PPI. By doing this, you can connect the clock events to GPIO tasks, so after you set it up and start the timer, you can generate this clock signal without the need of the CPU to toggle the pins.

    This may reduce the current consumption further, and it offloads the CPU, in case you have other timing sensitive tasks you need to perform. Let me know if that is of interrest, and I can provide some samples. (then also let me know what SDK version you are using)

    Other than that, if it works the way you are doing it now, I guess there is no reason to change anything. 

    Best regards,

    Edvin

  • Hi Edvin,

    I'm currently using Zephyr v2.6.0-ncs1-rc3.

    #include <zephyr.h>
    #include <sys/printk.h>
    #include <device.h>
    #include <drivers/pwm.h>
    
    #define PWM_LED0_NODE	DT_ALIAS(pwm_led0)
    
    #if DT_NODE_HAS_STATUS(PWM_LED0_NODE, okay)
    #define PWM_CTLR	DT_PWMS_CTLR(PWM_LED0_NODE)
    #define PWM_CHANNEL	DT_PWMS_CHANNEL(PWM_LED0_NODE)
    #define PWM_FLAGS	DT_PWMS_FLAGS(PWM_LED0_NODE)
    #else
    #error "Unsupported board: pwm-led0 devicetree alias is not defined"
    #define PWM_CTLR	DT_INVALID_NODE
    #define PWM_CHANNEL	0
    #define PWM_FLAGS	0
    #endif
    
    #define MIN_PERIOD_USEC	(USEC_PER_SEC / 64U)
    #define MAX_PERIOD_USEC	USEC_PER_SEC
    
    void main(void)
    {
    	// Start clock for accurate frequencies
    	NRF_CLOCK->TASKS_HFCLKSTART = 1; 
    	// Wait for clock to start
    	while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) ;
    
    	const struct device *pwm;
    	int ret;
    
    	printk("PWM-based blinky\n");
    
    	pwm = DEVICE_DT_GET(PWM_CTLR);
    	if (!device_is_ready(pwm)) {
    		printk("Error: PWM device %s is not ready\n", pwm->name);
    		return;
    	}
    
    	while (1) {
    		// ret = pwm_pin_set_usec(pwm, PWM_CHANNEL,
    		// 		       30, 30 / 2U, PWM_FLAGS);
    		ret = pwm_pin_set_nsec(pwm, PWM_CHANNEL, 30518, 30518/2U, PWM_FLAGS);
    		printk("Value of ret: %u \n", ret);
    
    		k_sleep(K_SECONDS(4U));
    	}
    }

    I have modified a sample program.

    The nrf tag currently in use is v1.6.1.

    The program above is just for checking that it's possible to get accurate 32.768 kHz clock signal out on a GPIO pin. As mentioned this clock signal would then be fed onto another IC.

  • Ok, so you are using the PWM peripheral. In that case, you are not dependent on the CPU to toggle the PWM signal, so this should be just fine in my opinion.

    Best regards,

    Edvin

Related