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

NRF24LE1 how to set PWM frequency?

To what values should I set the PWMCON register to so that the PWM0 and PWM1 frequency is output at 20Khz with duty cycle varying between 1 to 2ms. Now specifically I am asking this after reading the data sheet because the tables mentioned are not clearing giving information. How do I decipher the table given here:

Please clearly disclose information in the data sheets. Also give an example to show how to set to particular frequency and pulse width.

Let me tell you how I decipher this as a newbie. Now CCLK is 16,000,000 for 16Mhz clock. I chose PWM0 as output so bit 0 is 1 and bit 1 is 0. Now I need to find out what PWMCON is so the formula for PWMCON for 20Khz PWM freq will be. (16000000/(255 x 20000))-1 = 160/51 -1 which is approximately 2. Hence PWMCON[5:2] will be 0010. There fore PWMCON will be 11001001 which is 0xC9. But this dint work when I put in this value for PWMCON as the servo did not rotate. Here is my code.

#include "reg24le1.h" // I/O header file for NRF24LE1
#include "hal_delay.h" // header file containing delay functions
 
// main function
void main()
{
int i = 0, j = 0; // loop variable
P0DIR = 0; // Port 0 as output
PWMCON = 0xc9; // enable PWM1
 
// infinte loop
while(1)
{
for(i= 180; i--; i > 0)
{
PWMDC0 = i ; // change duty cycle
delay_ms(10); // delay of 10 ms
}
 
 
}
 
}

  • The code you provided above does not work. I found this. Will this code work? (It seemed to work some times).

    #include "reg24le1.h" // I/O header file for NRF24LE1
    #include "hal_delay.h" // header file containing delay functions
    
    
    
    
    #include "reg24le1.h" // I/O header file for NRF24LE1
    #include <stdlib.h> // standard library
    #include <string.h> // library containing string functions
    #include <stdio.h> // standard I/O library
    #include "hal_clk.h"
    //#include <reg51.h>
    #include "hal_rtc.h"
    // PWM_Pin
    sbit PWM_Pin = P0^6;		   // Pin P2.0 is named as PWM_Pin
    
    // Function declarations
    void cct_init(void);
    void InitTimer0(void);
    void InitPWM(void);
    
    // Global variables
    unsigned char PWM = 0;	  // It can have a value from 0 (0% duty cycle) to 255 (100% duty cycle)
    unsigned int temp = 0;    // Used inside Timer0 ISR
    
    // PWM frequency selector
    /* PWM_Freq_Num can have values in between 1 to 257	only
     * When PWM_Freq_Num is equal to 1, then it means highest PWM frequency
     * which is approximately 1000000/(1*255) = 3.9kHz
     * When PWM_Freq_Num is equal to 257, then it means lowest PWM frequency
     * which is approximately 1000000/(257*255) = 15Hz
     *
     * So, in general you can calculate PWM frequency by using the formula
     *     PWM Frequency = 1000000/(PWM_Freq_Num*255)
     */
    /*#define PWM_Freq_Num   78	 // Highest possible PWM Frequency
    
    
    void mcu_init(void)
    {  
    	hal_clk_set_freq(HAL_CLK_1MHZ);// = 4
      hal_clklf_set_source(HAL_CLKLF_XOSC16M_SYNTH);    // Synthesize 32 KHz from 16 MHz clock  
    	//hal_clklf_set_source(HAL_CLKLF_RCOSC32K);
    	hal_clk_set_freq(HAL_CLK_1MHZ);
      hal_rtc_set_compare_mode(HAL_RTC_COMPARE_MODE_0); // Use 32 KHz timer mode 0
      //hal_clk_regret_xosc16m_on(true);                  // Keep XOSC16M on in register retention
      //while (hal_clk_get_16m_source() != HAL_CLK_XOSC16M) {}
    }
    
    // Main Function
    int main(void)
    {
    	 hal_clk_set_freq(HAL_CLK_1MHZ);
       cct_init();   	       // Make all ports zero
       InitPWM();              // Start PWM
     
       PWM = 0;              // Make 50% duty cycle of PWM
    
       while(1)                // Rest is done in Timer0 interrupt
       {
    	 delay_ms(1);
    		 PWM++;
    		 if(PWM>=254)
    			 PWM=0;
    	 }
    }
    
    // Init CCT function
    void cct_init(void)
    {
    	P0 = 0x00;   
    	P1 = 0x00;   
    	P2 = 0x00;   
    	P3 = 0x00;  
    }
    
    // Timer0 initialize
    void InitTimer0(void)
    {
    	TMOD &= 0xF0;    // Clear 4bit field for timer0
    	TMOD |= 0x01;    // Set timer0 in mode 1 = 16bit mode
    	
    	TH0 = 0x00;      // First time value
    	TL0 = 0x00;      // Set arbitrarily zero
    	
    	ET0 = 1;         // Enable Timer0 interrupts
    	EA  = 1;         // Global interrupt enable
    	
    	TR0 = 1;         // Start Timer 0
    }
    
    // PWM initialize
    void InitPWM(void)
    {
    	PWM = 0;         // Initialize with 0% duty cycle
    	InitTimer0();    // Initialize timer0 to start generating interrupts
    					 // PWM generation code is written inside the Timer0 ISR
    }
    
    // Timer0 ISR
    void Timer0_ISR (void) interrupt 1   
    {
    	TR0 = 0;    // Stop Timer 0
    
    	if(PWM_Pin)	// if PWM_Pin is high
    	{
    		PWM_Pin = 0;
    		temp = (255-PWM)*PWM_Freq_Num;
    		TH0  = 0xFF - (temp>>8)&0xFF;
    		TL0  = 0xFF - temp&0xFF;	
    	}
    	else	     // if PWM_Pin is low
    	{
    		PWM_Pin = 1;
    		temp = PWM*PWM_Freq_Num;
    		TH0  = 0xFF - (temp>>8)&0xFF;
    		TL0  = 0xFF - temp&0xFF;
    	}
    
    	TF0 = 0;     // Clear the interrupt flag
    	TR0 = 1;     // Start Timer 0
    }

    Could you tell me what is wrong with my code and the code you gave me?

  • Hi,

     

    Did you scope the correct pin? P1.0 should toggle in the example I posted.

    Here's the logic analyzer trace:

    Kind regards,

    Håkon

  • Yes, I scoped the pin and was able to see the PWM signal. I was also able to adjust to pulse width. But how do I change the frequency of the wave? Like if I want to change from 50Hz to 20Hz what parts of the code do I need to change? Which numbers do I need to change? What I found that the arduino is putting out a PWM signal at much less frequency like around 20Hz. Now how do I change the PWM generated by your code from 50Hz to 20Hz. Please explain the calculation.

    How are you arriving at these numbers (as mentioned in your code)?

     // Timer increments every 2*12 CPU clock cycles    
      // Timer starts counting down from 65535
      // 6666 * 1,5 us = 9999 us

  • Each tick is CPU_CLOCK / 12*2 = 1,5 us per tick. Timer starts decrementing from 0xFFFF and down.

    That gives (for 50 Hz):

    10000 us = x * 1,5, x = 10000/1,5.

    timer_val = 0xFFFF - 6666.

    If you want 20 Hz, you need to adjust the above value to match 1/ 2*(20 Hz), as you want to toggle the GPIO two times to generate the signal.

    Best regards,

    Håkon

  • So for 50 Hz you took 10000us so for 20Hz it would be 25000us. Therefore X will be 25000/1.5 = 16,666. But now how do I get a PWM or 1 to 2milli second pulse width here in 20Hz wave? Please let me know. Again the pulse width of 1ms to 2ms calculation at 20Hz is not clear to me. Please let me know the exact numbers..

Related