Regarding Input Capture on TCH0 of MC68HC908QY4 Microcontroller

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

Regarding Input Capture on TCH0 of MC68HC908QY4 Microcontroller

495 Views
rakeshc4
Contributor I

Hello There,

 

While configuring the timer channel 0 of MC68HC908QY4 Microcontroller, i am getting a strange problem of not been able to set the TSC0_ELS0A and TSC0_ELS0B bits to enable "Capture on rising or falling edge" mode. I am using cyclone pro debugger and while stepping on the respective instructions, the cyclone pro throws an error "Error: Unable to go into background mode".

Even if i set the breakpoint after the instructions, it never reaches the breakpoint and hangs. I have tried setting the ELS0A & ELS0B bits by bit-wise addressing mode and also by addressing TSC0 register. Both ways i am encountering the same problem. While addressing the other bits of TSC0 register, i do not get any error.

 

Kindly suggest if the input capture functionality in the code below is imlemented in a correct way.

 

The code is as follows. Please see the function Input_Capture_Init (). The error JPEG file is also attached.

 

/*************************************** Code ******************************************/

 

#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

/* Input capture */
#define CAPTUR_ON_RISING_EDG                 0x04
#define CAPTUR_ON_FALLING_EDG                0x08
#define CAPTUR_ON_RISING_OR_FALLING_EDG      0x0C

/* Configuration settings for MSxA - Mode Select Bit A */
#define ENBL_INPUT_CAPTR                     0x00
#define ENBL_UNBUFRD_PWM                     0x10
#define ENBL_UNBUFRD_OUTPUT_CMPR             0x10

typedef unsigned short uint16;
typedef unsigned char uint8;


void Set_PWM_out_Param (void);
void SystemInit(void);
void PWM_out_Init (void);
void MCU_init(void); /* Device initialization function declaration */
void delay (void);
void Input_Capture_Init (void);
void Read_Freq (void);
uint16 Read_TIM_Cntr (void);


void main(void)
{
  /* include your code here */
  SystemInit();
  PWM_out_Init();
  Input_Capture_Init();
  Set_PWM_out_Param();

  for(;:smileywink:
  {
     
     
  }
}

void SystemInit(void)
{
     char *Trim_Val;
     Trim_Val = (char*)0xFFC0;
     OSCTRIM = *Trim_Val;
           
     // 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
               );                     
}

void PWM_out_Init (void)
{
  DDRA = 0x02;        /* Configuring PTA1 pin as output */
  PTA = 0x02;          /* Driving high */
 
  DDRB = 0x02;
  PTB = 0x02;
}

void Set_PWM_out_Param (void)
{
     /********** PWM signal Frequency Settings **********/
     
     /* Loading the values in appropriate registers */
      TMODH = 0;
      TMODL = 39;       /* Frequency 160 * (1/800 KHz) = 5KHz*/

      TCH1L = 0;
      TCH1L = 20;       /* 50% Duty Cycle */
      
      TSC1 = 0x16;
      
      /* Setting the pre-scalar value as ÷ 4, i.e. 3.2MHz÷4 = 800KHz and starting the counter*/
      TSC = 0x02;
      
      
}

void Input_Capture_Init (void)
{
     TSC = 0x30;       /* Stop and Reset the TIM counter */
     /* Clear the TIM channel registers */
     TCH0H = 0;
     TCH0L  = 0;
     /* Enabling input capture at TCH0 channel with rising/falling edge capture */
     
     
     /* The instruction below is causing the problem */
     TSC0  = 0x0C;
     
     //TSC0 = ENBL_INPUT_CAPTR | CAPTUR_ON_RISING_OR_FALLING_EDG;
      
}

/* Function to read the frequency of captured signal */
void Read_Freq (void)
{
     uint16 Time_Stamp1;
     uint16 Time_Stamp2;
     uint16 Time_Stamp3;
     float Time_Period;
     uint16 TIM_Count;
     uint16 Freq;
          
     Time_Stamp1 = Read_TIM_Cntr();
     Time_Stamp2 = Read_TIM_Cntr();
     Time_Stamp3 = Read_TIM_Cntr();
     
     /* Calculate the time */
     TIM_Count = (Time_Stamp2 - Time_Stamp1) + (Time_Stamp3 - Time_Stamp2);
     /* With pre-scalar value of ÷ 4, i.e. 3.2MHz÷4 = 800KHz, Time period  = 1.25 uS */
     Time_Period = (1/800000)* TIM_Count;
     Freq = 1/Time_Period;
}

/* Function to capture the TIM counter value of the input capture function */
uint16 Read_TIM_Cntr (void)
{
     uint8 Byte_TCH0H;
     uint8 Byte_TCH0L;
     uint16 Time_Stamp;
     /* Wait till active edge occurs on the channel 0 pin */
     while (TSC0_CH0F != 1);
     
     /* Read the TIM channel 0 status and control register */
     Byte_TCH0H = TCH0H;
     Byte_TCH0L = TCH0L;
     
     /* Clear the CH0F bit for next capture */
     TSC0_CH0F = 0;
     
     /* Store the counter value */
     Time_Stamp = (Byte_TCH0H<<8) | Byte_TCH0L;
     
     return (Time_Stamp);
}

Labels (1)
0 Kudos
2 Replies

308 Views
bigmac
Specialist III

Hello,

 

There are some basic problems with your approach.

 

  1. Different channels of the same timer module cannot be used for both PWM and input capture operation.  This is because PWM operation requires a reduced modulo setting, whereas input capture requires a free-running timer.  You will need to choose a device with two separate timer modules.
  2. Your code will need to detect whether the timer module has over-run, when the period between input capture edges exceeds 65536 timer clock periods.  Over-run will occur when there is no input sigal applied, or for very low input frequencies.  The detection may involve the use of another channel on the same timer module as the input capture.
  3. Your code appears to have the COP timer enabled, but you are not clearing the COP at any point within your code.  Your code, as presented, actually does nothing since your main loop is empty, and you do not appear to be using any interrupts.  Input capture operation would normally make use of interrupts so that there is no need to enter a wait loop for a capture event.
  4. The device you have selected is very basic, and will likely not have sufficient resources, flash or RAM, to handle floating point operations.  It is very likely that the floating point operations would cause stack overflow.  You will need to use integer calculations for determination of the input frequency.  You may need to suitably scale the integer frequency result, depending on the frequency range of interest.
  5. Your code seems to have a plethora of unnecessary local variables.  The input capture result is best handled as a direct 16-bit value, rather than as two 8-bit values.  The use of a couple of 16-bit global variables may simplify your code, which would also be needed should you decide to utilise interrupts.
// Global variables:volatile uint16 old_val, new_val;

 

   uint16 period;        while (!TSC0_CH0F);          // Wait for input capture event   TSC0_CH0F = 0;               // Clear flag   old_val = new_val;           // Transfer previous capture value   new_val = TCH0;              // Current capture value   period = new_val - old_val;

 

Regards,

Mac

 

0 Kudos

308 Views
rakeshc4
Contributor I

Thanks Mac. I am polling the port pin instead of input capture and it is working fine now.

0 Kudos