3 Generating Two PWM Signals in One Ramp Mode

Use case description: The TCD will be initialized and configured to run in One Ramp mode, have the OSCHF as input clock running at 24 MHz, and generate two PWM signals – WOA on the PA4 pin, and WOB on the PA5 pin. The PWM signal on WOA will have a 25% duty cycle and the signal on WOB will have a 30% duty cycle.

Result: The TCD will generate one PWM signal with a 25% duty cycle on WOA (PA4 pin) and one PWM signal with a 30% duty cycle on WOB.

The TCD can be configured to run in One Ramp mode, where the counter’s value increments until it reaches the CMPBCLR value. Then, the TCD cycle is completed and the counter restarts from 0x000, beginning a new TCD cycle. The TCD cycle period is:

T T C D _ c y c l e = ( C M P B C L R + 1 ) f C L K _ T C D _ C N T

In this configuration example, nonoverlapping outputs will be generated, so the case where CMPASET < CMPACLR < CMPBSET < CMPBCLR will be used.

Figure 3-1. One Ramp Mode

Configuring the Main Clock

There are four clock sources for the TCD:

  • OSCHF
  • PLL
  • EXTCLK
  • CLK_PER

In this example of the TCD configuration, the OSCHF clock source will be the input to CLK_MAIN and the TCD. The following configurations must be made to have the CPU and the TCD run at 24 MHz, having OSCHF as input clock.

In the example code available in Appendix, the main clock initialization will be done in the CLK_Init() function.

Setting the Default Clock Source to OSCHF (Optional)

This can be done by using Atmel Studio and following the steps below:

a. Click Tools → Device Programming.

b. Select the attached development board and click Apply.

c. Select the Fuses tab from the left-hand side and select 1-24 MHz internal oscillator OSCHF for OSCCFG.CLKSEL, and then click Program.

Changing the clock source to OSCHF and the configuration for running at 24 MHz are described in the following three steps:

  1. Set OSCHF as clock source for the main clock.
    Figure 3-2. CLKCTRL.MCLKCTRLA Register Configuration

    The Main Clock Control A register is protected by the Configuration Change Protection (CCP) mechanism, requiring a timed-write procedure for changing the register content. To write to the CCP-protected registers, the following API must be used:

    _PROTECTED_WRITE(register, value);

    OSCHF must be selected, which means that the CLKSEL bit field must be set to value 0x0. This translates into the following code:
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCHF_gc);

  2. Wait for the clock switch process to complete.
    Figure 3-3. CLKCTRL.MCLKSTATUS Register

    The clock switching process is indicated by the SOSC bit. The program must halt during an undergoing switch of the clock source, so a wait until the switch is over will be implemented.

    while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm)
        {
            ;
        }

  3. Set the OSCHF to run at 24 MHz.
    Figure 3-4. CLKCTRL.OSCHFCTRLA Register Configuration

    The default Reset value of the FRQSEL bit field in the OSCHFCTRLA register is 0x3, which means that the default frequency value is 4 MHz. To obtain the 24 MHz desired frequency, the content of the FRQSEL bit field must be changed to 0x9. This bit field uses the CCP mechanism, so a protected write must be performed. The following code will select 24 MHz output for OSCHF:

    _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FREQSEL_24M_gc);

Configuring PA4 and PA5 Pins as Output

The PA4 and PA5 pins must be configured as output pins for the WOA and WOB PWM signals. The following code snippet sets the PA4 and PA5 pins as output low.

PORTA.DIRSET |= PIN4_bm | PIN5_bm;
PORTA.OUTSET |= PIN4_bm | PIN5_bm;

In the example code available in Appendix, the pins initialization will be done in the PORT_Init() function.

Configuring the TCD Input Clock and Operation Mode

To generate the two PWM signals using the TCD configured in One Ramp mode and with OSCHF as input clock, the following registers must be changed:
  • TCD0.CTRLA
  • TCD0.CTRLB
  • TCD0.CMPASET
  • TCD0.CMPACLR
  • TCD0.CMPBSET
  • TCD0.CMPBCLR

In the example code available in Appendix, the TCD initialization will be done in the TCD_Init() function.

  1. Select the Waveform Generation mode and configure the TCD.
    Figure 3-5. TCD0.CTRLB Register Configuration

    To use TCD0 in One Ramp mode, the WGMODE bit field in the TCD0.CTRLB register must be set to 0x0. The following code snippet configures TCD0 in One Ramp mode:

    TCD0.CTRLB |= TCD_WGMODE_ONERAMP_gc;

    In One Ramp mode, the TCD0.CMPASET and TCD0.CMPACLR registers are used for setting the ‘Dead time A’ and ‘On time A’ for the WOA signal; in addition, the TCD0.CMPBSET and TCD0.CMPBCLR registers are used for setting ‘Dead time B’ and ‘On time B’ for the WOB signal.

    As the TCD0 counter continuously increases and overflows, setting CMPASET < CMPACLR < CMPBSET < CMPBCLR will result in nonoverlapping outputs during the on time.

    Since the TCD is a 12-bit timer/counter, it ranges from 0 to 4095 (4096 steps), corresponding to 0x000 to 0xFFF. For a 25% PWM duty cycle, WOA must have an on time of 1024 clock cycles (defined below by the ON_TIME_CYCLES_WOA macro), corresponding to 0x400 in hexadecimal format:

    O N _ T I M E _ C Y C L E S _ W O A = 25 100 × 4096 = 1024 = 0 x 400

    This means that the difference between the value of TCD0.CMPACLR and TCD0.CMPASET must be 1024. For the purpose of this use case exemplification, the start of the on time for WOA will be 1023 (defined below by the ON_TIME_START_WOA macro).

    T C D 0. C M P A S E T = O N _ T I M E _ S T A R T _ W O A = 1023 = 0 x 3 F F
    T C D 0. C M P A C L R = O N _ T I M E _ S T A R T _ W O A + O N _ T I M E _ C Y C L E S _ W O A = 1023 + 1024 = 2047 = 0 x 7 F F

    For a 30% PWM duty cycle, WOB must have an on time of 1228 clock cycles (defined below by the ON_TIME_CYCLES_WOB macro), corresponding to 0x508 in hexadecimal format:

    O N _ T I M E _ C Y C L E S _ W O B = 30 100 × 4096 = 1288 = 0 x 508

    This means the difference between the value of TCD0.CMPBCLR and TCD0.CMPBSET must be 1288. For the purpose of this use case exemplification, the start of the on time for WOB will be 2457 (defined below by the ON_TIME_START_WOB macro).

    T C D 0. C M P B S E T = O N _ T I M E _ S T A R T _ W O B = 2457 = 0 x 999
    T C D 0. C M P B C L R = O N _ T I M E _ S T A R T _ W O B + O N _ T I M E _ C Y C L E S _ W O B = 2457 + 1288 = 3745 = 0 x E A 1

    The following code snippet initializes TCD0.CMPASET, TCD0.CMPACLR, TCD0.CMPBSET, and TCD0.CMPBCLR with the corresponding values for generating the PWM signals with 25% and 30% duty cycles.

    #define ON_TIME_START_WOA   0x3FF
    #define ON_TIME_CYCLES_WOA  0x400
    #define ON_TIME_START_WOB   0x999
    #define ON_TIME_CYCLES_WOB  0x508
    
    TCD0.CMPASET = ON_TIME_START_WOA;
    TCD0.CMPACLR = ON_TIME_START_WOA + ON_TIME_CYCLES_WOA;
    TCD0.CMPBSET = ON_TIME_START_WOB;
    TCD0.CMPBCLR = ON_TIME_START_WOB + ON_TIME_CYCLES_WOB;
    

  2. Enable the waveform channels as output.
    Figure 3-6. TCD0.FAULTCTRL Register Configuration

    For generating the PWM signals, the two output channels, WOA and WOB, must be enabled. Additionally, to exemplify this use case, the Default state of the two waveform outputs will be high. Since the TCD0.FAULTCTRL register is under Configuration Change Protection, the CMPAEN, CMPBEN, CMPB and CMPA bits must be written using the _PROTECTED_WRITE API.

    The following code snippet enables the output channels and sets the waveform output to high:

    _PROTECTED_WRITE(TCD0.FAULTCTRL, TCD_CMPAEN_bm | TCD_CMPA_bm 
                                   | TCD_CMPBEN_bm | TCD_CMPB_bm);

  3. Check if the TCD is ready for enabling.
    Figure 3-7. TCD0.STATUS Register

    To enable the TCD, first, it must be checked if it is ready. The following code snippet implements a wait until the TCD is ready to be enabled:

    while (!(TCD0.STATUS & TCD_ENRDY_bm))
        {
            ;
        }

  4. Select the input clock source and enable the TCD.
    Figure 3-8. TCD0.CTRLA Register Configuration

    The following code snippet will select OSCHF for the input frequency and will enable the TCD:

    TCD0.CTRLA |= TCD_CLKSEL_OSCHF_gc | TCD_ENABLE_bm;

    Tip: The full code example is also available in Appendix.