- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When I used an Arduino for Ws2812 leds, I would use a non-blocking delay such as a millis() timer so I could control the speed of an animation but not lock up the processor and allow it to do other tasks at the same time. I saw an example on a PSOC4 that used a timer and a function to set the period of the required delay.
PSoC Timer Example - Microcontroller - eewiki
When I tried this on the Psoc6 BLE Kit I'm having difficulty somewhere. I might be doing the Interrupt wrong but this is how I understand it.
Using the function ms_delay(50);
Sets the period of the timer, then enables the timer.
When one period of the timer is complete it triggers the ISR which sets the flag to 1 and closes the while(!timer);
Stops the timer and sets the flag back to 0
This is the condensed code from the link above and if found near the bottom of the page.
#define TIMER_CLOCK 24000000
// This value should match the clock input to the Timer
uint8 timer_flag = 0;
void
ms_delay (uint32 ms);
CY_ISR(MY_ISR) {
timer_flag = 1;
}
// This function can be used for delays in units of ms.
// Valid value of ms can be in the range [0 ~ 4,294,967,295].
void
ms_delay (uint32 ms) {
uint32 period = TIMER_CLOCK/1000*ms;
Timer_1_WritePeriod(period);
Timer_1_Enable();
// start the timeout counter
while
(!timer_flag);
Timer_1_Stop();
timer_flag = 0;
}
I'm still new to Psoc in general so any help or guidance is much appreciated
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I agree that the interrupt handling of PSoC 6 is much more complicated than PSoC 4,
and I'm still learning, too.
If you'd like to handle asynchronous events,
may be considering FreeRTOS is not a bad option.
Attached is my trial of using timer without RTOS using PSoC 6 BLE Pioneer kit.
I change color of RGB LED each 0.1 second, using polling method,
let's pretend this as your animation.
Meantime, with timer interrupt, one of LED_8 and LED_9 is ON/OFF each 1.0 sec.
So we can see that even while waiting, the animation is running.
My strategy is let ISR only set the flag.
Taking care of the flag is in the main loop.
So I hope this wait does not block the MCU.
===============================
#include "project.h"
#include <stdio.h>
#define LED_ON (0)
#define LED_OFF (1)
volatile uint8_t alarm_flag = 0 ;
void alarm_isr(void)
{
NVIC_ClearPendingIRQ(Alarm_INT_cfg.intrSrc) ;
NVIC_DisableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;
MS_Timer_Disable() ;
MS_Timer_SetCounter(0) ;
Clock_1kHz_Disable() ;
alarm_flag = 1 ;
}
void init_hardware(void)
{
__enable_irq(); /* Enable global interrupts. */
UART_Start() ;
Cy_SysInt_Init(&Alarm_INT_cfg, alarm_isr) ;
}
void set_alarm_ms(uint32_t wait_ms)
{
NVIC_ClearPendingIRQ(Alarm_INT_cfg.intrSrc) ;
NVIC_DisableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;
Clock_1kHz_Enable() ;
MS_Timer_SetCounter(0) ;
MS_Timer_SetCompare0(wait_ms) ;
MS_Timer_Start() ;
NVIC_EnableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;
}
void doLEDs(uint8_t value)
{
if (value & 0x01) {
Cy_GPIO_Write(LED_B_0_PORT, LED_B_0_NUM, LED_ON) ;
} else {
Cy_GPIO_Write(LED_B_0_PORT, LED_B_0_NUM, LED_OFF) ;
}
if (value & 0x02) {
Cy_GPIO_Write(LED_G_0_PORT, LED_G_0_NUM, LED_ON) ;
} else {
Cy_GPIO_Write(LED_G_0_PORT, LED_G_0_NUM, LED_OFF) ;
}
if (value & 0x04) {
Cy_GPIO_Write(LED_R_0_PORT, LED_R_0_NUM, LED_ON) ;
} else {
Cy_GPIO_Write(LED_R_0_PORT, LED_R_0_NUM, LED_OFF) ;
}
}
void doTask1(void)
{
static int turn = 0 ;
if (alarm_flag) {
if (turn) {
Cy_GPIO_Write(LED_8_0_PORT, LED_8_0_NUM, LED_OFF) ;
Cy_GPIO_Write(LED_9_0_PORT, LED_9_0_NUM, LED_ON) ;
turn = 0 ;
} else {
Cy_GPIO_Write(LED_8_0_PORT, LED_8_0_NUM, LED_ON) ;
Cy_GPIO_Write(LED_9_0_PORT, LED_9_0_NUM, LED_OFF) ;
turn = 1 ;
}
alarm_flag = 0 ;
set_alarm_ms(1000) ;
}
}
void doTask2(void)
{
static int count = 0 ;
doLEDs(count) ;
count = (count + 1) % 8 ; /* 0~7 */
}
int main(void)
{
uint32_t count = 0 ;
init_hardware() ;
set_alarm_ms(1000) ;
for(;;) {
doTask1() ;
if ((count % 1000) == 0) {
doTask2() ;
}
count++ ;
CyDelayUs(100) ; /* 100us tick */
}
}
/* [] END OF FILE */
===============================
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Of course you can use the timer of PSoC 6 to implement the functionality of delay you mentioned.
Please refer to code example ce220169 to know well about the implementation details.
However, it seems the ms_delay code snippet you listed above would also get core stuck in while loop, instead of handing other tasks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I agree that the interrupt handling of PSoC 6 is much more complicated than PSoC 4,
and I'm still learning, too.
If you'd like to handle asynchronous events,
may be considering FreeRTOS is not a bad option.
Attached is my trial of using timer without RTOS using PSoC 6 BLE Pioneer kit.
I change color of RGB LED each 0.1 second, using polling method,
let's pretend this as your animation.
Meantime, with timer interrupt, one of LED_8 and LED_9 is ON/OFF each 1.0 sec.
So we can see that even while waiting, the animation is running.
My strategy is let ISR only set the flag.
Taking care of the flag is in the main loop.
So I hope this wait does not block the MCU.
===============================
#include "project.h"
#include <stdio.h>
#define LED_ON (0)
#define LED_OFF (1)
volatile uint8_t alarm_flag = 0 ;
void alarm_isr(void)
{
NVIC_ClearPendingIRQ(Alarm_INT_cfg.intrSrc) ;
NVIC_DisableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;
MS_Timer_Disable() ;
MS_Timer_SetCounter(0) ;
Clock_1kHz_Disable() ;
alarm_flag = 1 ;
}
void init_hardware(void)
{
__enable_irq(); /* Enable global interrupts. */
UART_Start() ;
Cy_SysInt_Init(&Alarm_INT_cfg, alarm_isr) ;
}
void set_alarm_ms(uint32_t wait_ms)
{
NVIC_ClearPendingIRQ(Alarm_INT_cfg.intrSrc) ;
NVIC_DisableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;
Clock_1kHz_Enable() ;
MS_Timer_SetCounter(0) ;
MS_Timer_SetCompare0(wait_ms) ;
MS_Timer_Start() ;
NVIC_EnableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;
}
void doLEDs(uint8_t value)
{
if (value & 0x01) {
Cy_GPIO_Write(LED_B_0_PORT, LED_B_0_NUM, LED_ON) ;
} else {
Cy_GPIO_Write(LED_B_0_PORT, LED_B_0_NUM, LED_OFF) ;
}
if (value & 0x02) {
Cy_GPIO_Write(LED_G_0_PORT, LED_G_0_NUM, LED_ON) ;
} else {
Cy_GPIO_Write(LED_G_0_PORT, LED_G_0_NUM, LED_OFF) ;
}
if (value & 0x04) {
Cy_GPIO_Write(LED_R_0_PORT, LED_R_0_NUM, LED_ON) ;
} else {
Cy_GPIO_Write(LED_R_0_PORT, LED_R_0_NUM, LED_OFF) ;
}
}
void doTask1(void)
{
static int turn = 0 ;
if (alarm_flag) {
if (turn) {
Cy_GPIO_Write(LED_8_0_PORT, LED_8_0_NUM, LED_OFF) ;
Cy_GPIO_Write(LED_9_0_PORT, LED_9_0_NUM, LED_ON) ;
turn = 0 ;
} else {
Cy_GPIO_Write(LED_8_0_PORT, LED_8_0_NUM, LED_ON) ;
Cy_GPIO_Write(LED_9_0_PORT, LED_9_0_NUM, LED_OFF) ;
turn = 1 ;
}
alarm_flag = 0 ;
set_alarm_ms(1000) ;
}
}
void doTask2(void)
{
static int count = 0 ;
doLEDs(count) ;
count = (count + 1) % 8 ; /* 0~7 */
}
int main(void)
{
uint32_t count = 0 ;
init_hardware() ;
set_alarm_ms(1000) ;
for(;;) {
doTask1() ;
if ((count % 1000) == 0) {
doTask2() ;
}
count++ ;
CyDelayUs(100) ; /* 100us tick */
}
}
/* [] END OF FILE */
===============================
moto