Atxmega128a1 PWM port configuration code review and comment will be appreciated !

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Atxmega128a1 PWM port configuration code review and comment will be appreciated !

 

Drafted PWMInit() to configure PORTC pin[4|5|6|7] for PWM fan control but no wave form could be seen in the scope ?

 

void PWMInit( )

{
  PORTC_DIRSET = 0xf0;//Pot C Fan Sense. 
  
  TCC0.CTRLB |= 0x13; //p164: Set Compare Channel B single slop waveform generation mode.
  TCC0.PER = 0x6400; //p170: Set timer period 25KHz. P9 Fan spec PWM 25KHz.
  TCC0.CCB = 0x2800; //Default value corresponding to 40% duty cycle. 
  AWEXC_OUTOVEN = 0xF0;//Port C 
}

 

Sincerely,

Liu Wang

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not familiar with XMegas, but on a MEGA or Tiny, you must set the port pin to be an output in order to see the pwm signal.

  PORTC_DIRSET = 0xf0;//Pot C Fan Sense. 

 

Seems backwards to me, on an AVR setting the data direction to 1 sets the pin to be an output. 

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

 

Appreciate your comment.

"PORTC_DIRSET =0xf0" configures Port C pin [4|5|6|7] as output as of specified in the attached below.

 

Sincerely,

Liu Wang

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your magic number 0x13 isn't correct. You're enabling channel A instead of B.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Mr. balisong42,

 

Appreciate your comment.

Updated the code to enable all for channels and still not see PWM waveform from Port C pin [4|5|6|7].

 

" TCC0.CTRLB |= 0xf3; //p164: Set Compare Channel A|B|C|D single slop waveform generation mode."

 

Is a pull up / down register needed for the Port C pin to function as PWM control ?

 

Sincerely,

Liu Wang

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For common fan speed control you don't need to use the AWeX. Having that enabled may be overriding the port C outputs.
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It appears you set PER to you desired frequency rather than period. 

The period will be the clock source divided by the desired frequency.

So using the 32MHz clock you need 32M/25k = 1280 =  0x500.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You aren't selecting a clock source for the TC:

TCC0.CTRLA = 1;     // Select DIV1 prescaler

 

Greg Muth

Portland, OR, US

Xplained Boards mostly

Atmel Studio 7.0 on Windows 10

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sir. and / or. Madam Greg and balisong42,

 

Appreciate your review and comment.

Port C pin4 and pin5 connected to channel A and B still are not cranking with the following code updates.

 

Sincerely,

Liu Wang

 

void PWMInit( )
{
  OSC.CTRL |= OSC_RC32MRDY_bm; //enable 32 MHz internal oscillator
  while( ! ( OSC.STATUS & OSC_RC32MRDY_bm ) ); // wait 32 MHz internal oscillator ready
  CCP = CCP_IOREG_gc;
  CLK.CTRL = 0x01; //select 32MHz internal oscillator.
  PORTC_DIRSET = 0xf0;//Pot C Fan Sense. 
  TCC1.PER = 0x500; //p170: Set timer period 25KHz. P9 Fan spec PWM 25KHz.
  TCC1.CTRLB |= 0xf3; //p164: Set Compare Channel A|B|C|D single slop waveform generation mode.
  TCC1.CCB = 0x20c; //Default value corresponding to 40% duty cycle. 
  TCC1.CTRLA = 0x01; //p163 Set Prescaler clk
  TCC1.CTRLC = 0x03; //p165 enalbe channel A and B
  TCC1.CCABUF = 0x500;
  TCC1.CCBBUF = 0x500;
  //AWEXC_OUTOVEN = 0xF0;//Port C 
}

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  TCC1.PER = 0x500; //p170: Set timer period 25KHz. P9 Fan spec PWM 25KHz.
    .
    .
    .
  TCC1.CCABUF = 0x500;
  TCC1.CCBBUF = 0x500;

You might try setting the duty cycle to something less than 100%.

 

Greg Muth

Portland, OR, US

Xplained Boards mostly

Atmel Studio 7.0 on Windows 10

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg,

 

Appreciate the comment.

Modified as follows, PWM still not cranking.

 

  TCC1.CCABUF = 0x20c;
  TCC1.CCBBUF = 0x20c;

 

Sincerely,

Liu Wang

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Rather then a code snippit, can you post a zip of a small complete project that demos the problem?

Perhaps one of the freaks can then test your project to find the trouble.

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

 

Appreciate your review and comment.

It's a small PWM plumbing effort as follows.

 

Sincerely,

Liu Wang

/*-----------------------------------------------------------------------------
 *
 * BPN_SAS3_827HQ, Liu Wang, 201705261205

*-------------------------------------------------------------------------------/

#ifndef PWM_H
#define PWM_H

 

void PWMInit();

 

#endif /* PWM_H */

 

/*-----------------------------------------------------------------------------
 *
 * BPN_SAS3_827HQ, Liu Wang, 201705261205

*-------------------------------------------------------------------------------/

void PWMInit( )
{
  OSC.CTRL |= OSC_RC32MRDY_bm; //enable 32 MHz internal oscillator
  while( ! ( OSC.STATUS & OSC_RC32MRDY_bm ) ); // wait 32 MHz internal oscillator ready
  CCP = CCP_IOREG_gc;
  CLK.CTRL = 0x01; //select 32MHz internal oscillator.
  PORTC_DIRSET = 0xf0;//Pot C Fan Sense. 
  TCC1.PER = 0x500; //p170: Set timer period 25KHz. P9 Fan spec PWM 25KHz.
  TCC1.CTRLB |= 0xf3; //p164: Set Compare Channel A|B|C|D single slop waveform generation mode.
  TCC1.CCB = 0x20c; //Default value corresponding to 40% duty cycle. 
  TCC1.CTRLA = 0x01; //p163 Set Prescaler clk
  TCC1.CTRLC = 0x03; //p165 enalbe channel A and B
  TCC1.CCABUF = 0x20c;
  TCC1.CCBBUF = 0x20c;
  AWEXC_OUTOVEN = 0xF0;//Port C 
}

 

 

/*-----------------------------------------------------------------------------
 *
 * BPN_SAS3_827HQ, Liu Wang, 2017051205

*-------------------------------------------------------------------------------/

#include <avr/io.h>
#include "PWM.h"

 

main()

{

  PWMInit( );

  while (1) 
  {
  }

}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When I run the following in the simulator it appears to work as evidenced by PORTC.PIN bits 4 and 5 toggling at different times as the code executes:

#include <avr/io.h>
#include <avr/cpufunc.h>


void PWMInit(void);


int main(void)
{
    PWMInit();
    while (1)
    {
        _NOP();
        _NOP();
    }
}


void PWMInit(void)
{
    OSC.CTRL |= OSC_RC32MRDY_bm;
    while( ! ( OSC.STATUS & OSC_RC32MRDY_bm ) );
    CCP = CCP_IOREG_gc;
    CLK.CTRL = 0x01;
    PORTC_DIRSET = 0xf0;
    TCC1.PER = 0x0020;
    TCC1.CTRLB = 0x33; // changed from TCC1.CTRLB = 0xf3
    TCC1.CCA = 0x0010;
    TCC1.CCB = 0x0018;
    TCC1.CTRLA = 0x01;
// the following DOES NOT enable A & B, it forces a compare on both channels
//	TCC1.CTRLC = 0x03; //p165 enalbe channel A and B
    TCC1.CCABUF = 0x0010;
    TCC1.CCBBUF = 0x0018;
// Why are you using AWeX???
//	AWEXC_OUTOVEN = 0xF0;//Port C
}

 

Greg Muth

Portland, OR, US

Xplained Boards mostly

Atmel Studio 7.0 on Windows 10

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg,

 

Appreciate your review and comments.

It works.

 

You saved my Memorial day !

May I invite you a dinner someday anytime in my town San Jose ?

liuw@supermicro.com

 

Sincerely,

Liu Wang

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Liu,

 

Glad I could help!  In the unlikely event I find myself in San Jose, I'll look you up.

 

Greg Muth

Portland, OR, US

Xplained Boards mostly

Atmel Studio 7.0 on Windows 10

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dir Sir/Madam,

 

Please help me in reviewing the following PWM control init code !

 

To adjust TCC1.PER value doesn't generate the period of my PWM output pin 4 at port C.

 

Sincerely,

Liu Wang

 

 

"TCC1.PER = 0x0020;" generates waveform of 1MHz as following:

==================================================

void PWMInit( )
{
  OSC.CTRL |= OSC_RC32MRDY_bm; //enable 32 MHz internal oscillator
  while( ! ( OSC.STATUS & OSC_RC32MRDY_bm ) ); // wait 32 MHz internal oscillator ready
  CCP = CCP_IOREG_gc;
  CLK.CTRL = 0x01; //select 32MHz internal oscillator.
  TCC1.CTRLA = 0x01; //p163 Set Prescaler clk
  TCC1.CTRLB = 0x33; //p164: Set Compare Channel A|B| single slop waveform generation mode.
  //TCC1.CTRLC = 0x03; //p165 enalbe channel A and B
  //TCC1.CTRLD = 0x80; //
  PORTC_DIRSET = 0xf0;//Pot C Fan PWM control. 
  TCC1.PER = 0x0020; //p170: Set timer period 25KHz. P9 Fan spec PWM 25KHz.
  TCC1.CCABUF = 0x0010;
  TCC1.CCBBUF = 0x0010;
  TCC1.CCA = 0x0010;
  TCC1.CCB = 0x0010; //Default value corresponding to 40% duty cycle. 
  //AWEXC_OUTOVEN = 0xF0;//Port C 
}

 

 

"TCC1.PER = 0x0010;" doesn't generate the 1MHz period waveform as expected per spec of XMega128A1. It generates the same period waveform and doubles the voltage of the wave form as follows:

====================================================

void PWMInit( )
{
  OSC.CTRL |= OSC_RC32MRDY_bm; //enable 32 MHz internal oscillator
  while( ! ( OSC.STATUS & OSC_RC32MRDY_bm ) ); // wait 32 MHz internal oscillator ready
  CCP = CCP_IOREG_gc;
  CLK.CTRL = 0x01; //select 32MHz internal oscillator.
  TCC1.CTRLA = 0x01; //p163 Set Prescaler clk
  TCC1.CTRLB = 0x33; //p164: Set Compare Channel A|B| single slop waveform generation mode.
  //TCC1.CTRLC = 0x03; //p165 enalbe channel A and B
  //TCC1.CTRLD = 0x80; //
  PORTC_DIRSET = 0xf0;//Pot C Fan PWM control. 
  TCC1.PER = 0x010; //p170: Set timer period 25KHz. P9 Fan spec PWM 25KHz.
  TCC1.CCABUF = 0x0010;
  TCC1.CCBBUF = 0x0010;
  TCC1.CCA = 0x0010;
  TCC1.CCB = 0x0010; //Default value corresponding to 40% duty cycle. 
  //AWEXC_OUTOVEN = 0xF0;//Port C 
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Madam / Sirs,

 

The above is resolved.

Duty cycle was forgotten to be adjusted accordingly.

 

Sorry for the inconvenience and appreciate your time in reviewing my PWM code.

 

Sincerely,

Liu Wang