This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

PWM -- what is special about 0% and 100% duty-cycle?

When use one of the Timer Compare Channels (CCn where n>0) to generate PWM, is it true that you cannot cover both 0% and 100% duty-cycle without special treatments?

For example, you may use:

CCR0 = N-1; // where N is the number of clocks for the period of the PWM
CCRn = M; // this sets (duty-cycle) = 100*M/N %
CCTLn = OUTMOD_7; // Set/Reset mode

But I heard that you must have M>0 and also must have M<N. Thus you cannot get 0% and 100% this way.

I think when M=0, you will get 0%, and when M>=N, you will get 100%. Am I wrong?

  • Hi old_cow_yellow,

    how to distinguish between 12:00 and 0:00 on an analog clock? 

    Rgds
    aBUGSworstnightmare 

  • In the so-called "12 hour system" there is a 12:00, but no 00:00.  In the so-called "24 hour system", there is a 00:00, but no 24:00.

  • aBUGSworstnightmare said:
    how to distinguish between 12:00 and 0:00 on an analog clock? 

    That's a good one. And only too true :)

    The problem with PWM hardware is that it will usually be programmed to set and reset teh output at a certain moment. But what if the moment to set it is the moment to reset it? This is true for 0% and 100%. Like with the clock example: is it the end of the previous hour or the start of the next one? So is it 0% of the next hour of 100% of the last? It is both.
    So per definition, you cannot have both, a 100% and a 0% PWM setting by the circular counting mechanisms used for the PWM generation. The theoretical maximum is only one of them.

    But there's another problem, since the hardware just sets and resets based on the counter value, what is the outcome if both apply at the same time? It's an internal racing condition to the output register? Has one of the two precedence? It is not covered by the datasheet.
    So depending on the implementation, 0% may work, or 100% may work, maybe the same settign will result in 0% on one and 100% on the other MSP. The only sure thing is that it cannot be both.

    After all, neither 0% nor 100% duty cycle form any sort of output frequency (other than 0Hz) and therefore are no PWM at all :) (If you want, you can treat both cases of the duty/idle part of a very low frequency PWM, but then PWM frequency has changed and depends on the duration of these states...)

  • I always have wishful thinking that things work the way I think they should work. Of course, I am often disappointed. However, in this case, and in the case of the HF external ACLK input for F2xx, I am still hopeful. I did some tests. These tests cannot proof that my wishes are granted, But they tell me that there is a good chance that they are.

    Here is a test program and, with an oscilloscope, I can see 0%, 1%, 50%, 99%, and 100% duty for both OUTMOD_7 and OUTMOD_3.

    #include <msp430.h>

    int state=0;
    void main(void)
    {
      WDTCTL = WDTPW | WDTHOLD;
      P1DIR = BIT6 | BIT5;
      P1SEL = BIT6 | BIT5;
      TACCR0 = 100 - 1; // for PWM with period of 100 ACLK
      TACCTL0 = OUTMOD_4; // toggle OUT0
      TACCR1 = 0; // initially 0%
      TACCTL1 = OUTMOD_7; // initially Reset/Set OUT1
      TACTL = TASSEL_1 | ID_0 | MC_1 | TACLR; // ACLK/1 & up-mode
      while (1)
      {
        if ((P1IN & BIT3)==0) // SW2 is pressed
        {
          state++;
          if (state==10) state = 0;
          switch (state)
          {
          case 0:
              TACCR1 = 0; // while TACCR0=100-1=99
              TACCTL1 = OUTMOD_7;
              break;
          case 1:
              TACCR1 = 1;
              TACCTL1 = OUTMOD_7;
              break;
          case 2:
              TACCR1 = 50;
              TACCTL1 = OUTMOD_7;
              break;
          case 3:
              TACCR1 = 99;
              TACCTL1 = OUTMOD_7;
              break;
          case 4:
              TACCR1 = 100; // while TACCR0=100-1=99
              TACCTL1 = OUTMOD_7;
              break;
          case 5:
              TACCR1 = 0; // while TACCR0=100-1=99
              TACCTL1 = OUTMOD_3;
              break;
          case 6:
              TACCR1 = 1;
              TACCTL1 = OUTMOD_3;
              break;
          case 7:
              TACCR1 = 50;
              TACCTL1 = OUTMOD_3;
              break;
          case 8:
              TACCR1 = 99;
              TACCTL1 = OUTMOD_3;
              break;
          case 9:
              TACCR1 = 100; // while TACCR0=100-1=99
              TACCTL1 = OUTMOD_3;
              break;
          } // end of swtch (state)
          __delay_cycles(20000); // let SW2 bounce
          while ((P1IN & BIT3)==0){ /* wait till SW2 is released */}
          __delay_cycles(20000); // let SW2 bounce
        } // end of if ((P1in & BIT3)==0)
      } // end of while (1)
    } // end of main


     

     

  • old_cow_yellow said:
    I always have wishful thinking that things work the way I think they should work.

    I'ts been a long time since I learned that things usually don't work as I thing they should. Maybe because I was born when things were build to no provide maximum usability but to provide maximum income with minimum effort.

    The last time I've seen something that was designed with the 'how one woudl expect it will work' in mind was the GlobalPC in 2000. Where I worked on the core OS. It was a PC designed for people with no computer experience. This concept was proved by the way it greeted a new user right after switching it on (the docs for assembling it were also easy with color-coded connectors and many images). The first you were seeing on the screen was 'Do you know how to handle a mouse? If yes, click on the 'yes' button on the bottom of the screen, if no, press the key labaled 'help' on the keyboard"

    Also, the main menu was impressing with the question 'what do you want to do today?' with the options "write, print or manage documents - browse the internet or read your email - ..."

    Even my grandma could have worked with it (in fact, I presented a beta version to some 65+ aged people and they had no problem doing basic work up to writing a letter, without ever having touched a computer before.

    Well, the company invested some millions in investigating how people expect things to work. Also, much of this concept was already in the used OS, GEOS, which was designed in the used incarnation back in ~1990 (of course updated since).

    The typical things I see todfay is that the programmer was ordered to implement a function, so he placed a button somewhere, whether you expect it there or not and the function was doing things like a programmer would expect it to be done (or even less logical, if it is easier and still fits the order) and not like a user would expect it.

    Partly, things start to become better in some (few) areas but they still become worse in most others.

     

    About your tests: I can confirm that you can do 100% (or 0% depending on polarity) by simply never reaching the second event of the double-action outmode. I must admit I didn't think of this as it is outside the 'operating range'. Indeed it will work and it is covered by the documentation of the CCR modules.

    The opposite side, however, is a problem. Your test may have shown that you caget 0%/100% duty cycle by setting CCRx to 0. But this outcome is NOT covered by the documentation. The documentation just implies that in this case, the set and the reset event happen at the same time (when TxR counts to 0). But in this case there is not specified which one will win.So while you might get 0% on one MSP, you might get 100% (the other event wins the race, or actually loses it as it comes last and persists). Even the next revision of the same MSPs might do differently. Or you might see spikes onteh output (perhaps only if you use an input divider, perhaps always, perhaps never).

    I don't say it cannot work, I only say it is unsafe to trust in it. If you tested it and want to take the rist that the code will no longer work when you use a different device or just different revision, well, that's fine.
    The problem is that when posting that it works this way, and it stops working later, people will come and blame TI for breaking their code, never knowing or caring for the fact that their code was using an undocumented and never warranted or officially proposed 'feature'. So I strongly discourage people relying on this kind of functionality. Unless they accept the risk, document it for those who come after them (if they are working on a project that is later continued by others, or if they want to release teh result to the public) and don't take it for a given or warranted feature.

    Same applies to  the F2xx digital clock input.

**Attention** This is a public forum