Regarding PWM generation on MC68HC908QY4A Microcontroller

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Regarding PWM generation on MC68HC908QY4A Microcontroller

Jump to solution
545 Views
rakeshc4
Contributor I

Hi,

 

I using MC68HC908QY4A Microcontroller for motor control application using PWM. As per the data sheet of the device, I am writing the values in respective hardware registers but we are not getting the desired output. Following are the steps:

1. Internal clock is selected, since there is no external crystal connected on the board.

2. Prescalar value is selected for Internal bus clock/ 4.

3.To generate 5KHz PWM signal with 50% duty cycle on TCH1 in unbuffered mode, registers TMODL = 159 and TCH1L = 128 are loaded.

4. Toggle on overflow is enabled and Clear on output compare is selected.

All the settings has been taken care of as mentioned in reference manual page 125. I am also attaching the code file for your reference.

Also, if I clear the TOV1 bit and select toggle on compare, i am able to see PWM signal of close to 5.5Hz with PS[010](prescalar). At PS[000] PWM signal frequency is 22.7Hz (multiplied by 4).

Please provide your valuable suggestions to help us in this regard. Also, if there is any sample code available for PWM generation for this microcontroller family, kindly share.  

Regards,
Rakesh

 

/********************************* Code Begin **************************************/

 

#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */


#define COP_ENABLE 0                    // Enable Watchdog
#define STOP_INSTRUCTION_DISABLE 0        // Disable Stop instruction
#define STOP_RECOVERY_LONG 0            // Stop Mode Recovery after 4096 cycles
#define LVI_3V 0                        // 3V operating voltage of LVI module
#define LVIPWR_ENABLE 0                 // Enable LVI Module Power
#define LVIRST_ENABLE 0                // Enable LVI Module Reset
#define LVISTOP_DISABLE 0            // Disable LVI during STOP-Mode
#define COP_LONG_RESETTIME 0              // Watchdog resets after 262128* BUSCLK*4

#define RSTEN_ACTIVE 0x01               // Reset function active in pin
#define INTERNAL_OSC 0                  // Internal oscillator
#define IRQ_ACTIVE 0x40                 // Interrupt request function active
#define IRQ_PULLUP_CONNECT 0            // IRQ pin pullup connected between IRQ pin and VDD


void Set_PWM_out_Param (void);
void SystemInit(void);
void PWM_out_Init (void);
void MCU_init(void); /* Device initialization function declaration */

void main(void)
{

  /* Uncomment this function call after using Device Initialization
     to use the generated code */
  /* MCU_init(); */

  //EnableInterrupts; /* enable interrupts */

  /* include your code here */
  SystemInit();
  PWM_out_Init();
  Set_PWM_out_Param();


  for(;:smileywink: {
   }//__RESET_WATCHDOG(); /* feeds the dog */
     /* loop forever */
     /* please make sure that you never leave this function */
}

void SystemInit(void)
{
     // Write CONFIG1-Register (Write-Once-Register)
    CONFIG1 = (    COP_ENABLE |                 // Enable Watchdog
                STOP_INSTRUCTION_DISABLE |    // Disable Stop instruction
                STOP_RECOVERY_LONG |         // Stop Mode Recovery after 4096 cycles
                LVI_3V |                      // 5V operating voltage of LVI module
                LVIPWR_ENABLE |               // Enable LVI Module Power
                LVIRST_ENABLE |               // Enable LVI Module Reset
                LVISTOP_DISABLE |             // Disable LVI during STOP-Mode
                    COP_LONG_RESETTIME            // Watchdog resets after 262128* BUSCLK*4
               );

    // Write CONFIG2-Register (Write-Once-Register)
     CONFIG2 = (    RSTEN_ACTIVE |                   // Reset function active in pin
                    INTERNAL_OSC |                  // Inernal Crystal oscillator
                    IRQ_ACTIVE   |                   // Interrupt request function active
                    IRQ_PULLUP_CONNECT            // IRQ pin pullup connected between IRQ pin and VDD
               );
     //OSCTRIM = 0x19;                     
}

void PWM_out_Init (void)
{
  TSC_TSTOP = 1;      /* Stop the TIM counter */
  TSC_TRST = 1;       /* Reset TIM counter. */
 
  DDRA_DDRA1 = 1;        /* Configuring PTA1 pin as output */
  PTA_PTA1 = 1;          /* Driving high */
 
  /* Setting the pre-scalar value as ÷ 4, i.e. 3.2MHz÷4 = 800KHz*/
  TSC_PS0 = 0;
  TSC_PS1 = 1;
  TSC_PS2 = 0;
 
}

void Set_PWM_out_Param (void)
{
     /********** PWM signal Frequency Settings **********/
     /* Loading the values in appropriate registers */
      TMODL = 159;       /* Frequency 160 * (1/800 KHz) = 5KHz*/
      //TMODH = 10;
      TCH1L = 128;       /* 50% Duty Cycle */
      
      TSC1_MS1A = 1;     /* for unbuffered output compare or PWM signals */
      
      TSC1_TOV1 = 1;     /* toggle-on-overflow */
            
      TSC1_ELS1B = 1;
      TSC1_ELS1A = 0;    /* Clear the TCH1 on output compare */      
            
      TSC_TSTOP = 0;
}

 

/********************************* Code End **************************************/

Labels (1)
0 Kudos
1 Solution
347 Views
bigmac
Specialist III

Hello, and welcome to the forum.

 

The TMOD and TCH1 registers are both 16-bits.  However, I notice that you are not setting the high byte value in either case.  For the modulo register, the high byte will have value 0xFF, and for TCH1 the high byte has indeterminate value after a reset.  Additionally, a value of 128 for TCH1 does not represent 50 percent duty - rather a duty of 128/160, or 80 percent.

 

Since there is a coherency mechanism for both registers, the high byte value requires to be written first, followed by the low byte.  Alternatively, if using the CW compiler, the following should also work correctly:

TMOD = 159;

TCH1 = 80;   // 50% duty

 

Note that, unless you trim the internal oscillator frequency, the tolerance for the PWM frequency may be up to +/-25 percent.  The internal oscillator frequency needs to be calibrated as part of the programming procedure, with the trim value normally programmed to flash address 0xFFC0.  Your code will then need to transfer this value to the trim register.

 

For the initialisation of TSC and TSC0 registers, it is much more efficient to simultaneously write all bits, rather than sequentially writing individual bits.

TSC  = 0x32;  // Stop and clear timer, prescale 4

TSC0 = 0x1A;  // Unbuffered PWM mode

 

Regards,

Mac

View solution in original post

0 Kudos
2 Replies
348 Views
bigmac
Specialist III

Hello, and welcome to the forum.

 

The TMOD and TCH1 registers are both 16-bits.  However, I notice that you are not setting the high byte value in either case.  For the modulo register, the high byte will have value 0xFF, and for TCH1 the high byte has indeterminate value after a reset.  Additionally, a value of 128 for TCH1 does not represent 50 percent duty - rather a duty of 128/160, or 80 percent.

 

Since there is a coherency mechanism for both registers, the high byte value requires to be written first, followed by the low byte.  Alternatively, if using the CW compiler, the following should also work correctly:

TMOD = 159;

TCH1 = 80;   // 50% duty

 

Note that, unless you trim the internal oscillator frequency, the tolerance for the PWM frequency may be up to +/-25 percent.  The internal oscillator frequency needs to be calibrated as part of the programming procedure, with the trim value normally programmed to flash address 0xFFC0.  Your code will then need to transfer this value to the trim register.

 

For the initialisation of TSC and TSC0 registers, it is much more efficient to simultaneously write all bits, rather than sequentially writing individual bits.

TSC  = 0x32;  // Stop and clear timer, prescale 4

TSC0 = 0x1A;  // Unbuffered PWM mode

 

Regards,

Mac

0 Kudos
347 Views
rakeshc4
Contributor I

Dear Mac,

 

Thank you very much for your suggestions. It is working fine now.

 

Regards,

Rakesh

0 Kudos