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

Adjusting PWM freq from example code

Hi guys,

Recently, I've been trying to use the sample codes of C8051F120 DK: ADC and PCA (for PWM) in attempt to 1) produce a 100kHz, 28% duty cycle 3.3V PWM & 2) read an analog voltage signal in the range of 0-2.43V and display it on Hyperterminal via UART1.

Had realised that in order to create a 100kHz PWM, the CLK divider should be 0x20 and CLK multiplier should be about 0x21 to get that 100kHz, but if I change PLL0DIV = 0x20 and PLL0MUL = 0x21 accordingly, the display at the hyperterminal could not display the sensed mV properly. And if I used the default settings for PLL0DIV & PLL0MUL, the PWM will be 194kHz instead of 100kHz. So, it is really a chicken or egg problem.

Could anyone know how to do it in order for me to achieve both 1) 100kHz PWM and 2) displaying the sensed voltage correctly?

My partial codes are as below (since it is too long to be posted).

Recently, I've been trying to use the sample codes: ADC and PCA (for PWM) in attempt to 1) produce a 100kHz, 28% duty cycle 3.3V PWM & 2) read an analog voltage signal in the range of 0-2.43V and display it on Hyperterminal via UART1.

Had realised that in order to create a 100kHz PWM, the CLK divider should be 0x20 and CLK multiplier should be about 0x21 to get that 100kHz, but if I change PLL0DIV = 0x20 and PLL0MUL = 0x21 accordingly, the display at the hyperterminal could not display the sensed mV properly. And if I used the default settings for PLL0DIV & PLL0MUL, the PWM will be 194kHz instead of 100kHz. So, it is really a chicken or egg problem.

Could anyone know how to do it in order for me to achieve both 1) 100kHz PWM and 2) displaying the sensed voltage correctly?

My codes are as below.

void main (void)
{
 long measurement; // Measured voltage in mV
 unsigned int delay_count; // Used to implement a delay
 bit duty_direction = 0; // 0 = Decrease; 1 = Increase

 // Disable watchdog timer
 WDTCN = 0xde;
 WDTCN = 0xad;

 PORT_Init (); // Initialize crossbar and GPIO
 OSCILLATOR_Init (); // Initialize oscillator
 PCA0_Init (); // Initialize PCA0
 UART1_Init (); // Initialize UART1
 TIMER3_Init (SYSCLK/SAMPLE_RATE); // Initialize Timer3 to overflow at sample rate

 ADC0_Init (); // Init ADC

 SFRPAGE = ADC0_PAGE;
 AD0EN = 1; // Enable ADC

 EA = 1; // Enable global interrupts

 while (1)
 {
 EA = 0; // Disable interrupts

 // The 12-bit ADC value is averaged across INT_DEC measurements. The result is
// then stored in Result, and is right-justified
// The measured voltage applied to AIN 0.1 is then:
 //
 // Vref (mV)
 // measurement (mV) = --------------- * Result (bits)
// (2^12)-1 (bits)

 measurement = Result * 2430 / 4095;

 EA = 1; // Re-enable interrupts

 SFRPAGE = UART1_PAGE;

 printf("AIN0.1 voltage: %ld mV\n",measurement);

 SFRPAGE = CONFIG_PAGE;
 LED = ~SW1; // LED reflects state of switch

 Wait_MS(SAMPLE_DELAY); // Wait 50 milliseconds before taking another sample
 Set_PCA0_Duty_Cycle(74);
 }

void OSCILLATOR_Init (void)
{
 int loop; // Software timer

 char SFRPAGE_save = SFRPAGE; // Save Current SFR page

 SFRPAGE = CONFIG_PAGE; // Set SFR page

 OSCICN = 0x83; // Set internal oscillator to run
 // at its maximum frequency

 CLKSEL = 0x00; // Select the internal osc. as
 // the SYSCLK source

 //Turn on the PLL and increase the system clock by a factor of M/N = 2
 SFRPAGE = CONFIG_PAGE;

 PLL0CN = 0x00; // Set internal osc. as PLL source
 SFRPAGE = LEGACY_PAGE;
 FLSCL = 0x10; // Set FLASH read time for 50MHz clk
 // or less
 SFRPAGE = CONFIG_PAGE;
 PLL0CN |= 0x01; // Enable Power to PLL
 PLL0DIV = 0x01; // Set Pre-divide value to N (N = 1)
 PLL0FLT = 0x01; // Set the PLL filter register for
 // a reference clock from 19 - 30 MHz
 // and an output clock from 45 - 80 MHz
 PLL0MUL = 0x02; // Multiply SYSCLK by M (M = 2)

 for (loop=0; loop < 256; loop++); // Wait at least 5us
 PLL0CN |= 0x02; // Enable the PLL
 while(!(PLL0CN & 0x10)); // Wait until PLL frequency is locked
 CLKSEL = 0x02; // Select PLL as SYSCLK source

 SFRPAGE = SFRPAGE_save; // Restore SFR page
}

void PCA0_Init (void)
{
 char SFRPAGE_save = SFRPAGE; // Save current SFR Page

 SFRPAGE = PCA0_PAGE;
 // configure PCA time base; overflow interrupt disabled
 PCA0CN = 0x00; // Stop counter; clear all flags
 PCA0MD = 0x08; // Use SYSCLK as time base

 PCA0CPM0 = 0x42; // Module 0 = 8-bit PWM mode

 // Configure initial PWM duty cycle = 50%
 PCA0CPH0 = 256 - (256 * 0.5);

 // Start PCA counter
 CR = 1;
 SFRPAGE = SFRPAGE_save;
}

void Set_PCA0_Duty_Cycle(unsigned short l_us_duty_cycle)
{
 //Save current SFR Page
 char SFRPAGE_SAVE = SFRPAGE;

 SFRPAGE = PCA0_PAGE;

 if (l_us_duty_cycle == 0)
 {
 //For 0% duty cycle, clear ECOM0
 //PCA0CPM0 &= 0xBF;

 //lsl : 02 Jun 2011 : 1744hrs
 //For 0% duty cycle, clear ECOM0 (bit 6) & PWM0 (bit 1)
 PCA0CPM0 &= 0xBD;
 }
 else if (l_us_duty_cycle > 255)
 {
 //For 100% duty cycle
 //a. Set ECOM0 (bit 6) & PWM0 (bit 1)
 //b. Load 0x00 into PCA0CPH0

 PCA0CPM0 |= 0x42; //0x40;

 PCA0CPH0 = 0;
 }
 else
 {
 PCA0CPM0 |= 0x42; //0x40;

 PCA0CPH0 = 256 - (unsigned char)(l_us_duty_cycle & 0xFF);
 }

 //Restore the SFRPAGE
 SFRPAGE = SFRPAGE_SAVE;
}

void ADC0_Init (void)
{
 char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page

 SFRPAGE = ADC0_PAGE;

 ADC0CN = 0x04; // ADC0 disabled; normal tracking
 // mode; ADC0 conversions are initiated
 // on overflow of Timer3; ADC0 data is
 // right-justified

 REF0CN = 0x07; // Enable temp sensor, on-chip VREF,
 // and VREF output buffer

 AMX0CF = 0x00; // AIN inputs are single-ended (default)

 AMX0SL = 0x01; // Select AIN0.1 pin as ADC mux input

 ADC0CF = (SYSCLK/SAR_CLK) << 3; // ADC conversion clock = 2.5MHz
 ADC0CF |= 0x00; // PGA gain = 1 (default)

 EIE2 |= 0x02; // enable ADC interrupts

 SFRPAGE = SFRPAGE_SAVE; // Restore SFR page
}

  • Had realised that in order to create a 100kHz PWM, the CLK divider should be 0x20 and CLK multiplier should be about 0x21 to get that 100kHz, but if I change PLL0DIV = 0x20 and PLL0MUL = 0x21 accordingly
    you do not change SYSCLK to change PWM frequency.

    but if I change PLL0DIV = 0x20 and PLL0MUL = 0x21 accordingly, the display at the hyperterminal could not display the sensed mV properly
    of course not.

    as said often before "if you can not code it yourself, sample code is worthless"

    Erik

  • Then what should I change if I am not supposed to touch the SYSCLK?

    Could I know what are the purpose of sample codes then?

  • I don't work with your chip, so I'm off little use with specific help.

    But have you read through the relevant sections in the user manual/datasheet/application notes about the PWM, and about the clocking section of your processor? Sample code is fine. But the documentation should (and would normally) contain everything you need to know to correctly configure your processor and the peripherials.

    There should be formulas or tables for the relevant parameters.

  • Then what should I change if I am not supposed to touch the SYSCLK?
    that is described in the PCA section of the datasheet.

    Could I know what are the purpose of sample codes then?
    to demonstrate that the chip works, not to "help you avoid understanding"

    Erik

  • .... you need to tackle several simple programs before you dive into this AND that you need to spend some time reading the datasheet.

    1) realize that SYSCLK affects everything
    2) read the datasheet several times.
    3 do some simple stuff
    4) after doing some simple stuff, REALLY read up on the PCA section in the datasheet
    5) come back when you know (at least a bit about) how it works.

    Erik

  • Thanks, I got your intention. I've read both the datasheet and some online tutorials posted by some universities. The information on the step-by-step tutorial from the latter source really gives me the idea behind the operation for a timer in 8051. Had also realised that I should use timer0 as my clk input for my PCA rather than the sysclk. I'm ready to try out my new codes but is there any soft simulator that could allow me to test the output pwm? It is a weekend and I could not access my hardware in school but also eager to test it out.

  • Have you looked into the capabilities of the simulator in the Keil tools? There is also a virtual oscilloscope/logic analyzer for tracking output pins.

  • Thanks for your heads up.

    But when I visited: http://www.keil.com/dd/chip/3469.htm, I could not locate the correct program to download. Do you have any clue which is the one should I download that I could simulate the C8051F120 DK with checks on all the I/O pins.

  • I'm ready to try out my new codes but is there any soft simulator that could allow me to test the output pwm?

    probably not, and if there were, I would not pay much for the results.

    the '51 simulators that exist usually simulate the core and the traditional peripherals UART (for the '120 only UART0) T0 and T1, maybe T2) quite well, for the rest you usuallly run into something like "the developer made it for Atmel, the NXP is slightly different, thus the results are incorrect". The '51 core is fully standard the peripherels are very much derivative dependent.

    Erik

  • The C51 version of uVision, so the tool you are probably already using :)

    The link you posted shows a big list of simulated hardware.

  • the '51 simulators that exist usually simulate the core and the traditional peripherals UART (for the '120 only UART0) T0 and T1, maybe T2) quite well, for the rest you usuallly run into something like "the developer made it for Atmel, the NXP is slightly different, thus the results are incorrect".

    You're doing Keil some injustice there. The simulator integrated into uVision is a lot better than that. It manages to simulates an enormously wide array of peripherals and cores perfectly, up to and including even integrated CAN controllers. It has the occasional limitation, too, but nowhere near as bad as you make it out to be.

    Maybe you did yourself a misfavour with your long-standing vow not to use IDEs...

  • I did maybe 80% of one project only using the simulator, while I waited for the first prototype hardware. I could probably have managed 100% if I had had enough time. The simulator wasn't a problem - I just wrote external scripts to produce the required feedback and used the scope/logic analyzer to see what happened.

  • You're doing Keil some injustice there. The simulator integrated into uVision is a lot better than that. It manages to simulates an enormously wide array of peripherals and cores perfectly, up to and including even integrated CAN controllers. It has the occasional limitation, too, but nowhere near as bad as you make it out to be.
    take the case in point: PCA
    I know of for sure 3, maybe more, implementations of the "Intel flavor PCA. All I know have subtle differences. Would I want to use a simulator and think "Is this that the simulator does nor account for a subtle difference or is it my code?
    I have, for at least a decade not developed anything without a full emulator. And thus the use of a simulator has no interest. I have ventured there on rare occasions when hardware was being overhauled and been greatly disappointed every time.

    Maybe you did yourself a misfavour with your long-standing vow not to use IDEs...
    maybe i did, but maintaining making the same change in 47 projects and not missing one is not my cup of tea. Actually right now (at this place only 3 active jobs) I am using the IDE and, as previously observed, what they call an editor is pitiful. WHY ON EARTH do they not allow intergrating CodeWright?, That, at least would gratly increase the value of using the IDE.

    Erik

  • take the case in point: PCA
    I know of for sure 3, maybe more, implementations of the "Intel flavor PCA. All I know have subtle differences. Would I want to use a simulator and think "Is this that the simulator does nor account for a subtle difference or is it my code?

    And do you actually know the Keil simulator to fail to represent those subtleties, or do you just summarily accuse without knowing the facts?

  • And do you actually know the Keil simulator to fail to represent those subtleties, or do you just summarily accuse without knowing the facts?
    no, I do not, and, if you actually read my post, you would see that my concern is the uncertainty from NOT knowing.

    Erik