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

C515C + PWM

Hi every body, and happy new year to all keil users ;)
I am using the C515C with keil v2.39,
I want to generate a PWM signal using one of the pins 1.0,1.1,1.2 or 1.3,
I read the manual, put I found it difficult, because I have to configure different things.
Like the following parameters:

T2CON |= 0x10; ET2=1; EXEN2=0; CRCL = 0x22; CRCH = 0xFF; EX3=0; CCL1 = 0xFF; CCH1 = 0x22; EX4=0; CCL2 = 0x00; CCH2 = 0x00; EX5=0; CCL3 = 0x000; CCH3 = 0x000; EX6=0; CCEN = 0xAA;

What I know, is that we have to use compare mode 0.

But how can I set T2 to be ready for all things, and how I change the duty cycle while from the program results...

Is there any ready function that has one input which is the duty cycle?

And thank you for your time.

Parents
  • I tried Mr.Chris's program.. and the problem still there,
    If I made the program as:

    while(1) {
        delay(100);         /* delay ~100 msec */
        P1 ^= 0x04;         /* toggle P1.2    */
        }
    


    It will make a delay and toggle P1.2

    And if I made the program as:

        updateDC == 1
        dc = 75;
        while(1) {
        if (updateDC == 1) {
        updateDC = 0;
        SetDC(dc);
        }
      };
    
    


    The result will be a PWM with a duty cycle of 75%

    But when I put the program as:

     while(1) {
        delay(100);         /* delay ~100 msec */
        P1 ^= 0x04;         /* toggle P1.2    */
    
        if (updateDC == 1) {
          updateDC = 0;
          SetDC(dc);
        }
      };
    


    !!!!

    The pin will toggle and no PWM signal !!
    What is the problem?!
    please help

Reply
  • I tried Mr.Chris's program.. and the problem still there,
    If I made the program as:

    while(1) {
        delay(100);         /* delay ~100 msec */
        P1 ^= 0x04;         /* toggle P1.2    */
        }
    


    It will make a delay and toggle P1.2

    And if I made the program as:

        updateDC == 1
        dc = 75;
        while(1) {
        if (updateDC == 1) {
        updateDC = 0;
        SetDC(dc);
        }
      };
    
    


    The result will be a PWM with a duty cycle of 75%

    But when I put the program as:

     while(1) {
        delay(100);         /* delay ~100 msec */
        P1 ^= 0x04;         /* toggle P1.2    */
    
        if (updateDC == 1) {
          updateDC = 0;
          SetDC(dc);
        }
      };
    


    !!!!

    The pin will toggle and no PWM signal !!
    What is the problem?!
    please help

Children
  • you present us with a ton of unknowns such as
    SetDC(dc);
    which nobody (but you) has any idea of what does.

    If you want ANY precision in your PWM get out of main() use the T2 interrupt ISR.

    You are fooling around with delays in main() written in C that a) may change any day (there is no restriction on how C is implemented and it often changes from release to release) and b) 'hangs' your processor and c) if e.g. an UART interrupt happes will change.

    go cure your interruptifobia and then try again.

    The pin will toggle and no PWM signal !!
    if the pin toggles you have a PWM signal, maybe not the frequency or duty cycle you want, but you DO have a PWM signal.

    Erik

  • This is dead simple if you do not try to be fancy here is some pseudocode

    in main() where you find out what the PWM is to be you set two variables: Up and Down, Up being the number of T2 clocks you want the PWM output to be high and Down being the number of T2 clocks you want the PWM output to be low. For a contstant frequency Up plus Down must always be the same.

    Then you have the variables High and Low High being (10000h minus Up) + fiddle and Low being (10000h minus Down) + fiddle. You also need a bit variable, let's call it On

    then in the T2 ISR
    stop the timer
    if ON
    -- clear On
    -- set the timer value (TH and TL) to the value Low
    -- clear the port pin
    else
    -- set On
    -- set the timer value (TH and TL) to the value High
    -- set the port pin
    endif
    start the timer
    exit

    fiddle above is the number of T2 clocks that would occur during ISR execution which you can calculate with "the bible" chapter 2. If you need ultimate precision code the T2 ISR in assembler so the time it takes will be constant.

  • Mr.Erik,

    SetDC(dc); is the function that sets the amount of the duty cycle in % and Mr.Chris explained that before..
    I am not looking for the accuracy of my PWM signal.. (Thanks to this forum) I already generated the PWM signal and its accuracy is accepted for me..

    Now it is working "get out of main()", I made a function called pwm() out of the main and I call it when I need to change the duty cycle..
    The program is the same as of Mr. Chris Wunderlich , but with making a call outside the main()

    This happens with me,, and I wrote this to help others "if they are beginner as much as me"

    Thank you all..thanks alot

    your student,Ashraf

  • Now it is working "get out of main()", I made a function called pwm() out of the main and I call it when I need to change the duty cycle..

    read the whole thing!!!!!

    get out of main() use the T2 interrupt ISR

    you will lose all precision etc the moment you start going beyond your simple "test code"

    Erik

  • T0 and T2 are running from interrupts

  • fine, but that is not the issue

    if the change of state of a PWM output is handled in the main erratic performance WILL (eventually) happen.

    Erik

    'eventually' because it may not happen in a small 'demo' that does nothing but PWM, but such a 'demo' will not be the final code.