Day 9: Infineon’s Embedded Systems Summer Course (2024)

Tabrez Ahmed
16 min readJun 2, 2024

--

25/05/24: Todays Class was filled with fun little experiments and a demo!

Prakash sir went through last weeks assignment and we learnt about the LED pin being an active low pin and how to identify it using the schematic diagram.

Todays class was taken up by Akanksha Garodia, she has 5 years experience working at infineon as an Application Engineer. She talked about timers and PWM in PSoC.

Akanksha Garodia delved into the intricacies of Timers and PWM (Pulse Width Modulation). With a blend of technical know-how and practical insights, she guided the participants through the crucial aspects of timing and signal control in embedded systems, ensuring everyone left ready to tackle their next hardware project with newfound confidence.

Timers and counters help measure elapsed time or count specific events in an embedded system. By counting clock pulses and knowing the period of each pulse, you can accurately determine the duration of time that has passed. This capability is essential for tasks such as creating time delays, generating periodic interrupts, and measuring the duration of events.

A hardware timer consists of registers to track and manage time-related events. The period register sets the duration of the counting cycle, the compare register triggers specific actions when matched, and the counter register tracks the clock pulses. This architecture allows precise control over timing and event generation in embedded systems.

By setting the Period Register to 4000 and starting the timer, the Counter Register increments with each clock pulse. When it reaches the value of 4000, an event is generated, and if configured, an interrupt signals to the CPU that the 2-second interval is complete. This simple timer setup allows precise delays, essential for timed operations in embedded systems.

  • Counter Clock: This is the clock signal that drives the timer. Each rising edge of this clock signal increments the counter value.
  • Period: This is the duration of one complete cycle of the timer counting from 0 to its terminal count.
  • Counter: This is the actual value of the timer that increments with each clock pulse until it reaches its terminal count.
  • The counter starts at 0x0000.
  • With each pulse of the counter clock, the counter increments by 1.
  • When the counter reaches the terminal count (0xFFFF), it resets back to 0x0000 and starts counting up again.
  • Counter Clock: The clock signal that drives the timer. Each rising edge of this clock signal decrements the counter value.
  • Period: The duration of one complete cycle of the timer counting down from its terminal count to 0.
  • Counter: The actual value of the timer that decrements with each clock pulse until it reaches 0.
  • The counter starts at the terminal count (0xFFFF).
  • With each pulse of the counter clock, the counter decrements by 1.
  • When the counter reaches 0, it resets back to the terminal count and starts counting down again.

This code is designed to profile the execution time of an FFT algorithm using a hardware timer on an embedded system. The FFT implementation, based on the Cooley-Tukey algorithm, is straightforward and processes a small array of complex numbers.

By setting the hardware timer to measure the duration of the FFT computation, the system can accurately determine the time taken for execution, which is essential for optimizing and analyzing performance-critical sections of code. This approach replaces a simple delay function, demonstrating how profiling can provide valuable insights into code efficiency on resource-constrained devices.

#include "user_cfg.h"
#include <math.h>
#define N 8 // FFT size, should be a power of 2
#define M_PI 3.14159265358979323846
typedef struct {
double real;
double imag;
} Complex;
void fft(Complex *X, int n) {
if (n <= 1) return;
// Divide
Complex even[n/2];
Complex odd[n/2];
for (int i = 0; i < n/2; i++) {
even[i] = X[i*2];
odd[i] = X[i*2 + 1];
}
// Conquer
fft(even, n/2);
fft(odd, n/2);
// Combine
for (int k = 0; k < n/2; k++) {
double t = -2 * M_PI * k / n;
Complex exp = {cos(t), sin(t)};
Complex temp = {exp.real * odd[k].real - exp.imag * odd[k].imag, exp.real * odd[k].imag + exp.imag * odd[k].real};
X[k].real = even[k].real + temp.real;
X[k].imag = even[k].imag + temp.imag;
X[k + n/2].real = even[k].real - temp.real;
X[k + n/2].imag = even[k].imag - temp.imag;
}
}
/* Timer period in milliseconds */
#define TIMER_PERIOD_MSEC 1000U
uint8_t app_heap[512] __attribute__((section (".heap")));
uint8_t app_stack[1024] __attribute__((section (".stack")));
volatile uint8_t invertFLAG = 0;
uint8_t toggleFLAG = 0;
volatile uint32_t Time_CodeProfile = 0;
int main()
{
/* HF CLOCK divider init*/
Cy_SysClk_ClkHfSetDivider(0u); //0 - No Divider, 1 - DIV by 2, 2 = DIV by 4, 3 = DIV by 8
/*GPIO pin init*/
GPIO_Pin_Init((GPIO_PRT_Type *)CYREG_GPIO_PRT2_DR, 1u, &MT1_P2_1_config, HSIOM_SEL_GPIO);
GPIO_Pin_Init((GPIO_PRT_Type *)CYREG_GPIO_PRT3_DR, 7u, &SW2_P3_7_config, HSIOM_SEL_GPIO);
GPIO_Pin_Init((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 5u, &MT2_P1_5_config, HSIOM_SEL_GPIO);
GPIO_Pin_Init((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 6u, &LED8_P1_6_config, HSIOM_SEL_GPIO);
GPIO_Pin_Init((GPIO_PRT_Type *)CYREG_GPIO_PRT3_DR, 4u, &USERLED_P3_4_config, HSIOM_SEL_GPIO);
GPIO_Pin_Init((GPIO_PRT_Type *)CYREG_GPIO_PRT5_DR, 7u, &LED13_P5_7_config, HSIOM_SEL_GPIO);
GPIO_Pin_Init((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 2u, &PWM_P1_2_config, HSIOM_SEL_PWM); //PWM Init
NVIC_SetPriority(3u, 1u);
/* Clearing and enabling the GPIO interrupt in NVIC */
NVIC_ClearPendingIRQ(3u);
NVIC_EnableIRQ(3u);
/* Configure SYSTICK to generate an interrupt once every 0.5 Sec */
/* Remember, Clock frequency is 24MHz */
SysTick_Config(0xB71B00);
/* Peripheral clock initializatio*/
init_peri_Clock_Config();
/*TIMER 2 - INTERRUPT*/
NVIC_SetPriority(19, 1u); //timer 2 IRQn = 19, priority 1
/* Clearing and enabling the GPIO interrupt in NVIC */
NVIC_ClearPendingIRQ(19u);
NVIC_EnableIRQ(19u);
/*TIMER 2 - INIT*/
TCPWM_Counter_Init(TCPWM, 2U, &TIMER2_config);
TCPWM_Counter_Enable(TCPWM, 2u);
TCPWM_SetInterrupt(TCPWM, 2u, 1u); //1- TC, 2 - CC, 3 - TC/CC
TCPWM_Counter_SetPeriod(TCPWM, 2u, TIMER_PERIOD_MSEC-1 );
TCPWM_TriggerStart(TCPWM, (1UL << 2u));
/*TIMER 0 - INIT*/
TCPWM_Counter_Init(TCPWM, 0U, &TIMER0_config);
TCPWM_Counter_Enable(TCPWM, 0u);
/*TIMER 3 - PWM - INIT*/
TCPWM_PWM_Init(TCPWM, 3U, &USER_PWM_config);
TCPWM_Counter_Enable(TCPWM, 3U);
TCPWM_TriggerReloadOrIndex(TCPWM, 1UL << 3u);
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 5u, 1u);
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT2_DR, 1u, 0u);
TCPWM_PWM_SetCompare0(TCPWM, 3U, 5000);

enable_irq();
for(;;)
{
/*Code profiling Code - measures the time required for execution */
TCPWM_Counter_SetCounter(TCPWM, 0u, 0);
TCPWM_TriggerStart(TCPWM, (1UL << 0u));
//Processing time to be measured
//Delay(5000);
Complex x[N];
// Initialize x with some sample data
for (int i = 0; i < N; i++) {
x[i].real = i;
x[i].imag = 0;
}

// Perform FFT
fft(x, N);

TCPWM_TriggerStopOrKill(TCPWM, (1UL << 0));
Time_CodeProfile = TCPWM_Counter_GetCounter(TCPWM, 0u);
/*Pricise delay generation example with TIMER block*/
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 5u, 1u);
timer_Delay_uS(6000u);
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 5u, 0u);
} return 0;
}
/*Delay with simple for loops*/
void Delay(int32_t delayNumber)
{
for(int32_t i=0; i<delayNumber; i++);
for(int32_t i=0; i<delayNumber; i++);
}
/*Delay with timer block*/
void timer_Delay_uS(uint32_t delay_uS)
{
TCPWM_Counter_SetCounter(TCPWM, 0u, 0);
TCPWM_TriggerStart(TCPWM, (1UL << 0u));
while (delay_uS > TCPWM_Counter_GetCounter(TCPWM, 0u));
}
/*Switch interrupt*/
void ioss_interrupts_gpio_3_IRQHandler(void)
{
GPIO_ClearInterrupt((GPIO_PRT_Type *)CYREG_GPIO_PRT3_DR, 7u);
NVIC_DisableIRQ(3u);

Delay(10000);

if((GPIO_Read((GPIO_PRT_Type *)CYREG_GPIO_PRT3_DR, 7u) == 0u))
{
if(invertFLAG == 1u)
{
//LED TURN-OFF
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 6u, 1u);

//Motor Controls for Clock wise/anti Clock wise direction
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 5u, 1u);
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT2_DR, 1u, 0u);
//PWM speed control
TCPWM_PWM_SetCompare0(TCPWM, 3U, 5000);
invertFLAG = 0u;
}
else if(invertFLAG == 0u)
{
//LED TURN-ON
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 6u, 0u);
//Motor Controls for Clock wise/anti Clock wise direction
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 5u, 0u);
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT2_DR, 1u, 1u);
//PWM speed control
TCPWM_PWM_SetCompare0(TCPWM, 3U, 1000u);
invertFLAG = 1u;
}
}
NVIC_ClearPendingIRQ(3u);
NVIC_EnableIRQ(3u);
}/*Timer 2 interrupt*/
void tcpwm_interrupts_2_IRQHandler(void)
{
/* Clear the terminal count interrupt */
TCPWM_ClearInterrupt(TCPWM, 2U, CY_TCPWM_INT_ON_TC);
/* Toggle the LED */
GPIO_Inv((GPIO_PRT_Type *)CYREG_GPIO_PRT3_DR, 4U);
}
/*Sys Tick interrupt handler*/
void __attribute__((section(".user_irq_hdlr"))) SysTick_Handler (void)
{
/* Clear the interrupt flag */
SysTick_Acknowledge_Interrupt();
/* Toggle the LED */
GPIO_Inv((GPIO_PRT_Type *)CYREG_GPIO_PRT5_DR, 7U);
}
/*Peripheral clock initilizations*/
void init_peri_Clock_Config()
{
//TIMER 2 TIMER- CLOCK
SysClk_PeriphDisableDivider(CY_SYSCLK_DIV_16_BIT, 3U);
SysClk_PeriphSetDivider(CY_SYSCLK_DIV_16_BIT, 3U, 24000 - 1);
SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_16_BIT, 3U);
SysClk_PeriphAssignDivider(PCLK_TCPWM_CLOCKS2, CY_SYSCLK_DIV_16_BIT, 3U);
//TIMER 0 for Code profiling
SysClk_PeriphDisableDivider(CY_SYSCLK_DIV_16_BIT, 1U);
SysClk_PeriphSetDivider(CY_SYSCLK_DIV_16_BIT, 1U, 24 - 1);
SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_16_BIT, 1U);
SysClk_PeriphAssignDivider(PCLK_TCPWM_CLOCKS0, CY_SYSCLK_DIV_16_BIT, 1U);
//TIMER 3 PWM- CLOCK
SysClk_PeriphDisableDivider(CY_SYSCLK_DIV_16_BIT, 0U);
SysClk_PeriphSetDivider(CY_SYSCLK_DIV_16_BIT, 0U, 240U - 1);
SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_16_BIT, 0U);
SysClk_PeriphAssignDivider(PCLK_TCPWM_CLOCKS3, CY_SYSCLK_DIV_16_BIT, 0U);
}

The code initializes various peripherals and timers on a microcontroller, configures GPIO pins, and sets up an FFT algorithm for profiling. It configures Timer-2 to profile the time taken to execute the FFT algorithm by measuring the start and stop times. Additionally, it sets up a PWM timer (Timer-3) for motor speed control and uses GPIO pins to control motor direction. The code also includes interrupt handlers for GPIO and system tick events, allowing the microcontroller to respond to button presses and toggle LEDs. The `Delay` function creates a simple delay using loops, and `timer_Delay_uS` generates a precise delay using Timer-0. The peripheral clocks are configured to provide the necessary clock signals for the timers. Overall, the code sets up and manages peripherals to perform and profile specific tasks, including motor control and FFT computation, on the microcontroller.

The FFT algorithm works by recursively breaking down a problem of size n into smaller subproblems of size n/2, solving the subproblems using the FFT, and then combining the results to get the final solution. The fft function performs these steps: dividing the input array into even and odd parts, recursively applying the FFT to these parts, and then combining the results using complex arithmetic and the twiddle factors. formal name: Cooley-Tukey FFT algorithm, specifically the radix-2 decimation-in-time (DIT) FFT.

Practical Implications

  • Motor Control: PWM is commonly used for controlling the speed of motors. A higher duty cycle results in a higher speed.
  • LED Dimming: PWM can control the brightness of LEDs. A higher duty cycle means brighter light.
  • Signal Generation: PWM is used in digital signal generation and communication systems.

The image illustrates how a hardware timer can be used as a Pulse Width Modulator (PWM). Let’s break down the key elements and concepts shown in the image:

  1. Pulse Width Modulation (PWM): This technique involves varying the width of the pulse, hence modulating the duty cycle of the signal.
  2. Duty Cycle: Defined as the ratio of the ON period (Ton) to the total period (T) of the pulse. It is expressed as:
  3. Period T: The total duration of one cycle of the PWM signal, consisting of both the ON and OFF periods.
  4. ON Period (Ton): The duration for which the signal remains high within one period.
  5. Examples of Different Duty Cycles:
  • 50% Duty Cycle: The ON and OFF periods are equal, each taking up half of the total period T.
  • 75% Duty Cycle: The ON period is 75% of the total period, meaning the signal is high for three-quarters of the period and low for the remaining quarter.
  • 25% Duty Cycle: The ON period is 25% of the total period, meaning the signal is high for one-quarter of the period and low for the remaining three-quarters.

Modulation of ON Time: The image shows how varying the ON time (Ton) changes the duty cycle of the PWM signal, effectively modulating the signal’s power delivery.

This diagram demonstrates how a hardware timer generating a PWM (Pulse Width Modulation) signal can control the fuel valve in an engine system.

The PWM signal’s duty cycle determines how long the valve remains open, thus controlling the amount of fuel delivered from the fuel tank to the engine.

Practical implications of this include optimizing fuel injection for better engine efficiency, reducing emissions, and improving performance by adjusting fuel delivery precisely for different driving conditions.

This method is widely used in modern automotive fuel injection systems to ensure optimal engine operation and fuel economy.

This diagram illustrates how a hardware timer generating a PWM (Pulse Width Modulation) signal can control the brightness of a lamp.

The PWM signal’s duty cycle determines the lamp’s brightness by adjusting the proportion of time the lamp is on.

For instance, an 80% duty cycle results in a bright light, a 40% duty cycle produces normal brightness, and a 15% duty cycle results in a dim light.

This practical application of PWM is widely used in lighting control systems to provide adjustable brightness, leading to energy savings and enhanced user comfort.

This diagram illustrates configuring a hardware timer to generate a 1 kHz square wave with a 40% duty cycle using PWM. By setting the period register to 100 (corresponding to 1 ms) and the compare register to 40, the timer outputs a signal that stays low for the first 40% of the cycle and high for the remaining 60%. This configuration allows precise control of the PWM signal, crucial for applications like motor speed control and LED dimming, ensuring efficient real-time control in embedded systems.

This diagram shows how to perform operations on a hardware timer using control signals generated by other peripherals on the chip. Signals (S1, S2, S4) from sources like ADC or GPIO pins are used to generate control signals (START, STOP, RELOAD) for the timer. START begins the timer without resetting the counter, RELOAD resets the counter to zero and starts the timer, and STOP halts the timer. This setup allows external events or software triggers to manage the timer’s operation, providing flexibility in timing control for various applications in embedded systems.

This diagram explains the difference between single-shot and continuous modes for a hardware timer, applicable to both Timer and PWM modes. In continuous mode, the timer counts up to the PERIOD register value and then either resets to 0 to start counting again (up-counting) or reloads and starts decrementing (down-counting). In single-shot mode, the timer stops once it reaches the PERIOD value. Continuous mode is typically used for generating PWM signals to ensure a continuous output without interruptions.

This diagram explains how to change the PERIOD and COMPARE registers in a hardware timer.

If the timer is stopped, you can directly program these registers.

If the timer is running, you should use the PERIOD SHADOW and COMPARE SHADOW registers.

These shadow (or buffer) registers hold the new values and automatically transfer them to the actual registers once the current period completes.

This approach ensures seamless operation, particularly in continuous mode, by allowing register updates without interrupting the timer’s ongoing process.

This diagram lists the timer registers for a PSoC (Programmable System-on-Chip) device. The registers are divided into common timer registers and specific registers for each timer (Timer-0 through Timer-7).

Common Timer Registers:

  1. TCPWM_CTRL: Control register.
  2. TCPWM_CMD: Command register.
  3. TCPWM_INTR_CAUSE: Interrupt cause register.

Example: Registers of Timer-7:

  1. TCPWM_CNT7_CTRL: Control register for Timer-7.
  2. TCPWM_CNT7_STATUS: Status register for Timer-7.
  3. TCPWM_CNT7_COUNTER: Counter register for Timer-7.
  4. TCPWM_CNT7_CC: Compare/Capture register for Timer-7.
  5. TCPWM_CNT7_CC_BUFF: Compare/Capture buffer register for Timer-7.
  6. TCPWM_CNT7_PERIOD: Period register for Timer-7.
  7. TCPWM_CNT7_PERIOD_BUFF: Period buffer register for Timer-7.
  8. TCPWM_CNT7_TR_CTRL0: Trigger control register 0 for Timer-7.
  9. TCPWM_CNT7_TR_CTRL1: Trigger control register 1 for Timer-7.
  10. TCPWM_CNT7_TR_CTRL2: Trigger control register 2 for Timer-7.
  11. TCPWM_CNT7_INTR: Interrupt register for Timer-7.
  12. TCPWM_CNT7_INTR_SET: Interrupt set register for Timer-7.
  13. TCPWM_CNT7_INTR_MASK: Interrupt mask register for Timer-7.

Each register has a specific address in memory, allowing precise control and configuration of the timer functionality. These registers facilitate various operations such as starting, stopping, configuring the timer, setting the period, comparing values, and handling interrupts, essential for implementing timer-based features in embedded applications.

  • TCPWM_CTRL: Enable the specific timer needed for an application, ensuring it is active for tasks like PWM generation.(ENABLE TIMER BEFORE USE)
    - TCPWM_CMD: Issue software commands to start, stop, or reload the timer for operations like motor control or signal timing adjustments.
    - TCPWM_INTR_CAUSE: Monitor and respond to timer events (e.g., overflow, compare match) by generating interrupts for tasks such as precise event handling or real-time processing.
  • TCPWM_CNTx_CTRL: Set the operational mode (e.g., Timer/PWM, single-shot/continuous) for applications requiring specific timing behaviors.
  • TCPWM_CNTx_STATUS: Check if the timer is running, useful for debugging and real-time status monitoring.
  • TCPWM_CNTx_CC, TCPWM_CNTx_PERIOD, TCPWM_CNTx_COUNTER: Configure compare, period, and counter values for precise timing and control in PWM or timer applications.
  • TCPWM_CNTx_TR_CTRL0: Select and configure control signals (START, STOP, RELOAD) from peripherals for integrated system control.
  • TCPWM_CNTx_TR_CTRL1: Set the edge type for control signals (rising, falling, both) to customize signal generation for events.
  • TCPWM_CNTx_TR_CTRL2: Define actions for Line_Output on events like compare match or period match, enabling specific output responses.
  • TCPWM_CNTx_INTRyy: Manage interrupts by enabling, disabling, or masking events to control application flow and respond to timer conditions efficiently.
#include "user_cfg.h"

// Function to set motor speed using PWM
void setMotorSpeed(uint16_t speed) {
// Set PWM duty cycle (speed value should be between 0 and the period value)
TCPWM_PWM_SetCompare0(TCPWM, 3U, speed);
}

// Function to set motor direction using GPIO pins
void setMotorDirection(uint8_t direction) {
if (direction == 1) {
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 5u, 1u); // Forward
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT2_DR, 1u, 0u);
} else {
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT1_DR, 5u, 0u); // Reverse
GPIO_write((GPIO_PRT_Type *)CYREG_GPIO_PRT2_DR, 1u, 1u);
}
}

// Main function
int main() {
// Initialization code for Timer-2
TCPWM_CTRL &= ~(1 << 2); // Disable Timer-2
TCPWM_CNT2_CTRL &= ~(7 << 24); // Timer Mode
TCPWM_CNT2_CTRL |= (1 << 18); // One-Shot Mode
TCPWM_CNT2_CTRL &= ~(3 << 16); // Count-Up Mode
TCPWM_CNT2_COUNTER = 0; // Clear Counter
TCPWM_CNT2_PERIOD = 0xFFFF; // Set period to highest value
TCPWM_CNT2_INTR = 0x3; // Clear spurious interrupts
TCPWM_CNT2_TR_INTR_MASK = 0x3; // Mask unwanted timer events
TCPWM_CTRL |= (1 << 2); // Enable Timer-2

// Start profiling
TCPWM_Counter_SetCounter(TCPWM, 0u, 0);
TCPWM_TriggerStart(TCPWM, (1UL << 0u));
Delay(5000); // Function to profile
TCPWM_TriggerStopOrKill(TCPWM, (1UL << 0));
uint32_t Time_CodeProfile = TCPWM_Counter_GetCounter(TCPWM, 0u);

// Print or store the profiling result
printf("Delay(5000) Execution Time: %lu ticks\n", Time_CodeProfile);

// Example usage of motor control functions
setMotorDirection(1); // Set motor direction to forward
setMotorSpeed(5000); // Set motor speed (duty cycle)

return 0;
}

// Simple delay function
void Delay(int32_t delayNumber) {
for (int32_t i = 0; i < delayNumber; i++);
for (int32_t i = 0; i < delayNumber; i++);
}

Bit manipulation that is used here si explained below:

// Disable Timer-2
TCPWM_CTRL &= ~(1 << 2);
  • This line clears the bit 2 of the TCPWM_CTRL register. The &= operator performs a bitwise AND operation between TCPWM_CTRL and the inverse of (1 << 2). This effectively disables Timer-2. i.e shift 1 ,2 times
// Enable Timer Mode of operation
TCPWM_CNT2_CTRL &= ~(7 << 24);
  • This line clears bits 26:24 of the TCPWM_CNT2_CTRL register. The ~(7 << 24) creates a mask that has 0s in positions 24, 25, and 26, and 1s elsewhere. This ensures that any previous mode settings in these bits are cleared.
// Enable One-Shot mode
TCPWM_CNT2_CTRL |= (1 << 18);
  • This line sets bit 18 of the TCPWM_CNT2_CTRL register. The |= operator performs a bitwise OR operation, which sets the specific bit to 1, enabling one-shot mode.
// Enable Count-Up mode
TCPWM_CNT2_CTRL &= ~(3 << 16);
  • This line clears bits 17 and 16 of the TCPWM_CNT2_CTRL register. The ~(3 << 16) creates a mask that has 0s in positions 16 and 17, and 1s elsewhere. This sets the timer to count-up mode by clearing any previous settings in these bits.
// Clear the Counter register
TCPWM_CNT2_COUNTER = 0;
  • This line simply sets the TCPWM_CNT2_COUNTER register to 0, effectively clearing it.
// Set the period register to the highest value
TCPWM_CNT2_PERIOD = 0xFFFF;
  • This line sets the TCPWM_CNT2_PERIOD register to 0xFFFF, the highest value for a 16-bit register, setting the period to its maximum value.
// Clear spurious interrupts
TCPWM_CNT2_INTR = 0x3;
  • This line writes 0x3 to the TCPWM_CNT2_INTR register, which is often used to clear interrupt flags. It likely clears bits for both the terminal count (TC) and compare match (CC) events.
// Mask unwanted timer events
TCPWM_CNT2_TR_INTR_MASK = 0x3;
  • This line writes 0x3 to the TCPWM_CNT2_TR_INTR_MASK register to mask unwanted interrupt events, ensuring that only specific events trigger an interrupt.
// Enable Timer-2
TCPWM_CTRL |= (1 << 2);
  • This line sets bit 2 of the TCPWM_CTRL register. The |= operator performs a bitwise OR operation, enabling Timer-2 by setting this bit to 1.
#include "user_cfg.h"

// Function to configure Timer-2 for an accurate delay
void configureTimer2ForDelay(uint32_t delay_value) {
// Disable Timer-2
TCPWM_CTRL &= ~(1 << 2);

// Enable Timer Mode of operation
TCPWM_CNT2_CTRL &= ~(7 << 24); // Bits 26:24 = 000

// Enable One-Shot mode
TCPWM_CNT2_CTRL |= (1 << 18);

// Enable Count-Up mode
TCPWM_CNT2_CTRL &= ~(3 << 16); // Bits 17:16 = 00

// Clear the Counter register
TCPWM_CNT2_COUNTER = 0;

// Set the period register to the delay value
TCPWM_CNT2_PERIOD = delay_value;

// Clear spurious interrupts
TCPWM_CNT2_INTR = 0x3;

// Mask unwanted timer events
TCPWM_CNT2_TR_INTR_MASK = 0x3;

// Enable Timer-2
TCPWM_CTRL |= (1 << 2);

// Reload the timer
TCPWM_CMD |= (1 << 10);

// Wait until the TC event is set
while ((TCPWM_CNT2_INTR & 0x1) == 0);

// Stop the timer
TCPWM_CMD &= ~(1 << 18);
}

int main() {
// Example delay value calculation for 0.5 second delay at 100 kHz timer frequency
uint32_t delay_value = 50000; // 0.5 second delay (500,000 microseconds) at 100 kHz

// Configure Timer-2 for the delay
configureTimer2ForDelay(delay_value);

// Your main code continues here...

return 0;
}

Set the period register to the delay value:

  • TCPWM_CNT2_PERIOD = delay_value; sets the period register to the desired delay value (50,000 for 0.5 seconds at 100 kHz).

Below are pictures of motor driven by PWM and continuous mode in anti-clockwise and clockwise direction. whenever the user presses the onboard button then the motor changes its direction. It is a practical demo shown at infineon office in Bangalore.

We had a test today afternoon for Young Graduate Trainee Position.

Ananth sir explained the solutions to the problem

Thanks for reading! Let me know if you have any suggestions or corrections. Please clap if you liked the post!

--

--

Tabrez Ahmed
Tabrez Ahmed

Written by Tabrez Ahmed

Electronics & Communication Engineering graduate RV College of Engineering.

No responses yet