- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello everyone, this is my second question on this lovely community.
If the person who had helped in my previous question sees this, I posted this in a new post so the other one doesn't get out of context and doesn't become too long 🙂
Last time, a member helped solve my previous problem, which is to generate a 45 kHz signal over a period of 10 ms every second. I will post below the build and the code, and what my new problem is according to their suggestion.
The idea is to use a timer, and call an interrupt one overflow of the timer counter to generate the signal over 10 ms and disable the PWM afterwards.
Here is the m04 code:
#include "project.h"
#include <stdio.h>
void Counter_Int_Handler() //Counter interrupt handler
{
printf("Handler is here \r\n");
Cy_TCPWM_ClearInterrupt(Timer_HW, Timer_CNT_NUM, CY_TCPWM_INT_ON_TC); //Clearing the interrupt
Cy_GPIO_Inv(LED_PORT, LED_NUM);
CyDelay(10);
Cy_GPIO_Inv(LED_PORT, LED_NUM);
PWM_Disable();
CyDelay(990);
PWM_Start();
printf("End of Handler \r\n\n");
}
int main(void)
{
UART_Start();
Timer_Start();
PWM_Start();
bool flag = true;
Cy_GPIO_Write(LED_PORT,LED_NUM,1);
Cy_SysInt_Init(&SysInt_1_cfg,Counter_Int_Handler); //Configuring the interrupt
NVIC_ClearPendingIRQ(SysInt_1_cfg.intrSrc); //Clearing the interrupt
NVIC_EnableIRQ(SysInt_1_cfg.intrSrc); //Calling the interrupt handler
__enable_irq(); //Enable global interrupts
//(void)Cy_TCPWM_Counter_Init(Timer_HW, Timer_CNT_NUM, &Timer_config);
Cy_TCPWM_Enable_Multiple(Timer_HW, Timer_CNT_MASK); //
Cy_TCPWM_TriggerReloadOrIndex(Timer_HW, Timer_CNT_MASK);
printf ("\033[3J"); //Clearing PuTTY's scrollback buffer
printf ("\ec"); //Clearing previous PuTTY outputs
printf("UART link established \r\n\n");
__enable_irq();
for(;;)
{
printf("Hello for loop! \r\n");
Cy_SysPm_Sleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
}
}
The problem is that once the interrupt handler is called and start executing, it executes infinitely and never exits back to the for loop.
Also, although I am I managed to get the interrupt service routine to work, I am not quite sure if I understand how I exactly did it, nor what is the exact logic behind it as well; you could say I am following my sense and basic understanding of these matters.
My questions are as following:
1) Is the interrupt logic correct?
2) Could the interrupt logic used here be enhanced to be more efficient and/or exit to the for loop and back to the interrupt again without flags?
3) How to use flags?
I will post a weird attempt of mine to grasp the idea of flags, but in my opinion I failed miserably and most probably didn't actually understand anything.
Here is the miserable attempt on grasping flags:
#include "project.h"
#include <stdio.h>
void Counter_Int_Handler() //Counter interrupt handler
{
bool flag = true;
printf("Handler is here \r\n");
Cy_TCPWM_ClearInterrupt(Timer_HW, Timer_CNT_NUM, CY_TCPWM_INT_ON_TC); //Clearing the interrupt
Cy_GPIO_Inv(LED_PORT, LED_NUM);
CyDelay(10);
Cy_GPIO_Inv(LED_PORT, LED_NUM);
PWM_Disable();
CyDelay(990);
PWM_Start();
if (flag == true){
printf("End of Handler flag trigered \r\n\n");
NVIC_ClearPendingIRQ(SysInt_1_cfg.intrSrc);
__NVIC_DisableIRQ(SysInt_1_cfg.intrSrc);
}
}
int main(void)
{
UART_Start();
Timer_Start();
PWM_Start();
bool flag = false;
Cy_GPIO_Write(LED_PORT,LED_NUM,1);
Cy_SysInt_Init(&SysInt_1_cfg,Counter_Int_Handler); //Configuring the interrupt
NVIC_ClearPendingIRQ(SysInt_1_cfg.intrSrc); //Clearing the interrupt
NVIC_EnableIRQ(SysInt_1_cfg.intrSrc); //Calling the interrupt handler
__enable_irq(); //Enable global interrupts
//(void)Cy_TCPWM_Counter_Init(Timer_HW, Timer_CNT_NUM, &Timer_config);
Cy_TCPWM_Enable_Multiple(Timer_HW, Timer_CNT_MASK); //
Cy_TCPWM_TriggerReloadOrIndex(Timer_HW, Timer_CNT_MASK);
printf ("\033[3J"); //Clearing PuTTY's scrollback buffer
printf ("\ec"); //Clearing previous PuTTY outputs
printf("UART link established \r\n\n");
if (flag == true){
for(;;){
printf("Hello for loop! flag is true \r\n");
NVIC_EnableIRQ(SysInt_1_cfg.intrSrc); //Calling the interrupt handler
flag = false;
Cy_SysPm_Sleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
}
}
else {
printf("Flag is flase! \r\n");
flag = true;
return flag;
}
}
and here is the output of the last attempt with the flag:
I am excited and looking forward everyone's suggestions/solutions!
Thank you and best regards,
HappyPotamus.
Solved! Go to Solution.
- Labels:
-
PSoC 6 MCU
- Tags:
- code efficiency
- flags
- interrupt
- interrupt handler
- interrupt service routine
- putty
- pwm
- tcpwm
- timer counter
- uart
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can think of a bunch of ways to accomplish this task.
Method 1: (which I would never do)
1. Start the output pwm (which you called PWM)
2. Cydelay(10)
3. Stop the output pwm
4. CyDelay(990)
5. go back to step (1)
Method 2:
use the systick interrupt to make a software PWM to enable and disable the output pwm
Method 3:
Setup another pwm with a frequency of 1hz and a duty cycle of 990... then connect the output of that pwm to the count input of the output PWM
Method 4:
use a udb and gate to and off the pwm signal using a pwm with a period of 1hz and a duty cycle of 990
Method 5:
use the smart/o to gate the pwm with a source and signal from another PWM
Hopefully this helps.
ARH
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You definitely do not want to
1) printf
2) cydelay
Inside of an interrupt handler.
Both of these operation will take a long time and block the CPU.
I looked at your code... and I don't understand what you are trying to do... could you state simply what you are trying to achieve?
Alan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello @ARH ,
I am sorry that my code/commenting isn't clear, I am new to this entire thing 🙂
I have a PWM that is a continuous generating 45 kHz signal. But, I want this signal to be generated for 10 ms out of an entire second (Square signal in 10 ms out of the entire second and the rest 990 ms is a flat line). The timer is configured for overflow interrupt, and the time is for 1 second.
So that basically is what I am trying to achieve. Now that you mentioned to me that I should not include printf nor CyDelay in an interrupt handler because it block the CPU, how can I achieve my goal? I am sorry if what I wrote here also doesn't make sense, if it doesn't, please tell me I will rephrase my goal.
Many thanks,
HappyPotamus.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can think of a bunch of ways to accomplish this task.
Method 1: (which I would never do)
1. Start the output pwm (which you called PWM)
2. Cydelay(10)
3. Stop the output pwm
4. CyDelay(990)
5. go back to step (1)
Method 2:
use the systick interrupt to make a software PWM to enable and disable the output pwm
Method 3:
Setup another pwm with a frequency of 1hz and a duty cycle of 990... then connect the output of that pwm to the count input of the output PWM
Method 4:
use a udb and gate to and off the pwm signal using a pwm with a period of 1hz and a duty cycle of 990
Method 5:
use the smart/o to gate the pwm with a source and signal from another PWM
Hopefully this helps.
ARH