You are here

More PDL Examples - Handling PWM Interrupts | Cypress Semiconductor

More PDL Examples - Handling PWM Interrupts

It's time to add an interrupt to our PWM and show you a few more API functions. As with last week's example, it is basically the same process with PDL as it is is with the instance-based functions.

First of all, in the schematic, you add the Interrupt (SysInt_PDL) component to the PWM interupt output. I called it SysInt_Blinky because I am not very imaginative.

PSoC TCPWM Blinky Schematic

Then you check that the PWM will generate an interrupt on every terminal count by selecting the "Overflow/Underflow" option for the "Interrupt Source" parameter. That's all we need on the hardware side.

PSoC TCPWM Blinky Interrupt configuration

Because there is only one interrupt in my design the priority does not really matter. If you really want to change it - or are actually doing something a bit more sophisticated - then open the Design Wide Resources file and choose the priority you want.

PSoC design-wide resources

Note that I am using a dual-core PSoC 6 device and so you can choose to service the interrupt on the CM0+ core. That's a topic for another day - I am doing everything on the CM4 to keep everything simple. Of course, you can also change the priority in firmware, but let's just get the interrupt firing today.

In my C code I wanted to make the PWM blink faster so, after the "init" code from last week, I added this line, which gives my PWM a period of 100ms (10Hz) because its input clock is 1kHz.

Cy_TCPWM_PWM_SetPeriod0( BlinkyPWM_HW, BlinkyPWM_CNT_NUM, 100 );

Next I wrote my ISR. In PSoC 4 you would use the CY_ISR() macro but those are not used for PSoC 6. You just install a function that accepts no arguments (void) and returns nothing (void) into the vector table. Here is my handler.

void PWMInterruptHandler(void)
{   
    uint32_t compare = Cy_TCPWM_PWM_GetCompare0( BlinkyPWM_HW, BlinkyPWM_CNT_NUM );
    
    /* Clear the terminal count interrupt */
    Cy_TCPWM_ClearInterrupt( BlinkyPWM_HW, BlinkyPWM_CNT_NUM, CY_TCPWM_INT_ON_TC);   
    
    if( compare > Cy_TCPWM_PWM_GetPeriod0( BlinkyPWM_HW, BlinkyPWM_CNT_NUM ) )
        Cy_TCPWM_PWM_SetCompare0( BlinkyPWM_HW, BlinkyPWM_CNT_NUM, 0 );
    else
        Cy_TCPWM_PWM_SetCompare0( BlinkyPWM_HW, BlinkyPWM_CNT_NUM, compare + 1 );
}

The handler changes how my LEDs blink (I have two LEDs, one driven by the direct PWM output and the other by its inverse). It clears the interrupt, reads the compare value, then increments it and writes it back to the PWM. If the compare exceeds the period it resets the compare to zero. What does this do? It starts by blinking one LED for a long time and one very briefly, then it gradually extends one and contracts the other's blink time. Eventually the two swap roles completely, then the reset occurs and the cycle repeats itself.

That's great but before it will run, I had to install the ISR and enable the interrupt. The Cy_SysInt_Init() function puts the handler function into the vector table and sets the priority (from the CYDWR file). The following code does all this and enables the interrupt.

Cy_SysInt_Init( &SysInt_Blinky_cfg, PWMInterruptHandler );
NVIC_EnableIRQ( SysInt_Blinky_cfg.intrSrc ); /* Enable the core interrupt */
    
__enable_irq(); /* Enable global interrupts. */

That's all I need in order to run the program. But where did that SysInt_Blinky_cfg struct come from? PSoC Creator generated it for me. If you look in cyfitter_sysint_cfg.c you will see this code.

const cy_stc_sysint_t SysInt_Blinky_cfg = {
    .intrSrc = (IRQn_Type)SysInt_Blinky__INTC_NUMBER,
    .intrPriority = SysInt_Blinky__INTC_CORTEXM4_PRIORITY
};

Both of those struct members are populated from the CYDWR file. The priority is 7 and the vector number is 95, both of which you can see in the image above. The vector number is fixed. It is determined, by PSoC Creator, for the TCPWM block that you are using. That, in turn, is decided by the LED pins I chose to drive so you can see that PSoC Creator is saving us a little bit of investigation into the device innards here.

Next time I will dig into GPIO a little bit and explain how to do simple LED and button handling with PDL. I'll also dig into interrupt handling a little more and give you all the options for messing with the priority. Lastly, here is the whole C code file for your reference.

#include "project.h"

void PWMInterruptHandler(void)
{   
    uint32_t compare = Cy_TCPWM_PWM_GetCompare0( BlinkyPWM_HW, BlinkyPWM_CNT_NUM );
    
    /* Clear the terminal count interrupt */
    Cy_TCPWM_ClearInterrupt( BlinkyPWM_HW, BlinkyPWM_CNT_NUM, CY_TCPWM_INT_ON_TC);

    /* Modify the compare value to change the LED blink lengths */
    if( compare > Cy_TCPWM_PWM_GetPeriod0( BlinkyPWM_HW, BlinkyPWM_CNT_NUM ) )
        Cy_TCPWM_PWM_SetCompare0( BlinkyPWM_HW, BlinkyPWM_CNT_NUM, 0 );
    else
        Cy_TCPWM_PWM_SetCompare0( BlinkyPWM_HW, BlinkyPWM_CNT_NUM, compare + 1 );
}

int main(void)
{
    Cy_SysInt_Init( &SysInt_Blinky_cfg, PWMInterruptHandler );
    NVIC_EnableIRQ( SysInt_Blinky_cfg.intrSrc ); /* Enable the core interrupt */    
    __enable_irq(); /* Enable global interrupts. */

    //BlinkyPWM_Start();
    Cy_TCPWM_PWM_Init( BlinkyPWM_HW, BlinkyPWM_CNT_NUM, &BlinkyPWM_config );
    Cy_TCPWM_PWM_Enable( BlinkyPWM_HW, BlinkyPWM_CNT_NUM );
    Cy_TCPWM_TriggerStart( BlinkyPWM_HW, BlinkyPWM_CNT_MASK );
    
    Cy_TCPWM_PWM_SetPeriod0( BlinkyPWM_HW, BlinkyPWM_CNT_NUM, 100 );

    for(;;)
    {
        Cy_SysPm_Sleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
    }
}

 

Blog: 

Comments

0234rihankhan_3298166's picture

The article is very nice just visit information here click this link  game risk online as if you want entertainment then you must visit this  place to play the standard version is played on a bored depicting a political map of the earth thanks for it

barnnyross_3298731's picture

WOMEN’S HISTORY MONTH – CELEBRATING CYPRESS’ LEADING LADIES, I will be there for sure and will wrap up my all www.resumesplanet-au.com work so that I can be there on time. Good share!

katiewatson035_3301116's picture

An interrupt is equipment created change of stream inside the framework. An interrupt on handler manages the reason for the interrupt. Control is then come back to the interfered with setting A hinder is an equipment created change of stream inside the framework. An interrupt on handler manages the reason for the interrupt. Control is then come back to the interrupted with setting.

Regards: essay help UK

ALL CONTENT AND MATERIALS ON THIS SITE ARE PROVIDED "AS IS". CYPRESS SEMICONDUCTOR AND ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF THESE MATERIALS FOR ANY PURPOSE AND DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THESE MATERIALS, INCLUDING BUT NOT LIMITED TO, ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL PROPERTY RIGHT. NO LICENSE, EITHER EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, IS GRANTED BY CYPRESS SEMICONDUCTOR. USE OF THE INFORMATION ON THIS SITE MAY REQUIRE A LICENSE FROM A THIRD PARTY, OR A LICENSE FROM CYPRESS SEMICONDUCTOR.

Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms and Conditions of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms and Conditions of this site. Cypress Semiconductor and its suppliers reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.