PSoC 6 Stopwatch on UART

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
GaAr_4611026
Level 1
Level 1
First like given

Hi Hope you're doing well.

I and am working on a project that requires me to read the x, y, z axis accelerometer values and print the time (in minutes/second/milliseconds) during which it has been registered, that is for each reading of course. Note that I am willing to read more than 84000 readings as fast as possible.

I did the accelerometer part, I am stuck now on the time part.

I want to implement a timer in my project that:

1- starts counting in min:sec:ms during the start of a trigger (input via GPIO)

2- print on UART with a string format of  min:sec:ms, by using printf (that is how i'm printing accelerometer values)

Any help regarding on how to implement this timer?

Please mention basic reference links or code that could be helpful for me. I am still a beginner in PSoC.

Notes:

- I am using CYBLE416045-02

Thanks and Best regards,

Garen A.

0 Likes
1 Solution
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

Garen,

Another means of getting a 1ms resolution without allocating a special timer is to use the PDL SysTick.

With the SysTick you can:

  • Cy_SysTick_Init() - Initialize it for 1msec resolution
  • Cy_SysTick_Enable() -  Enable it to start
  • Cy_SysTick_GetValue() - gets the current counter value (24-bit).  This is a count-down value. This allows for 4.66 hours before the counter wraps around.
  • Cy_SysTick_Clear() - set the counter back to the reload value if you need to restart the counter.
  • If more than 4.66 hours is needed, there is a Cy_SysTick_GetCountFlag() that let's you know if the SysTick counter wrapped.

Len

Len
"Engineering is an Art. The Art of Compromise."

View solution in original post

10 Replies
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

Garen,

Are you using PSoC Creator or ModusTollbox as your IDE?

Either way.  Here is a link to example code for a free-running timer that you can use as a starting point:  https://www.cypress.com/documentation/code-examples/ce220498-psoc-6-mcu-free-running-multi-counter-w...

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

Garen,

Another means of getting a 1ms resolution without allocating a special timer is to use the PDL SysTick.

With the SysTick you can:

  • Cy_SysTick_Init() - Initialize it for 1msec resolution
  • Cy_SysTick_Enable() -  Enable it to start
  • Cy_SysTick_GetValue() - gets the current counter value (24-bit).  This is a count-down value. This allows for 4.66 hours before the counter wraps around.
  • Cy_SysTick_Clear() - set the counter back to the reload value if you need to restart the counter.
  • If more than 4.66 hours is needed, there is a Cy_SysTick_GetCountFlag() that let's you know if the SysTick counter wrapped.

Len

Len
"Engineering is an Art. The Art of Compromise."

Hi Thank you for your responses!

I wanted a 1ms resolution so I went ahead and tried using the systick example.

I wrote the following as your instruction and the API manual for the PSOC 6.

Note that I am using PsocCreator 4.2

Main Code:

#include "project.h"

#include <stdio.h>

#include <inttypes.h>

int main(void)

{

    __enable_irq(); /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

    UART_1_Start();

   

    setvbuf(stdin, NULL, _IONBF,0);

    //char c[16];

   

    uint32_t clock = Cy_SysTick_GetClockSource();

    Cy_SysTick_Init(clock, Cy_SysTick_GetReload());

Cy_SysTick_Enable();

    uint32_t time_value;

    int i;

   

    for(i=0;i<1000;i++)

    {

        time_value = Cy_SysTick_GetValue();

        printf( "%" PRIu32,time_value);

        printf("\r\n");

       

       

    }

}

//END OF CODE

I tested out printf with a regular string and it is working alright.

I'm getting no errors nor warnings during building and flashing.

Could you please point out what am I missing or what am I doing wrong?

Thanks in advance.

0 Likes

Garen,

The code looks good.  Systick access is pretty simple.  The only thing is that it is a count-down counter.  A little math can make it a count-up function.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Len,

Well Cy_SysTick_GetValue() is outputing 0, essentially that was my issue before getting into the math.

Garen

0 Likes

Here i am printing Cy_SysTick_GetValue() after converting it to char.

Uart output.jpg

0 Likes

Garen,

Sorry.  I didn't test out your code until now.

Issues:

    uint32_t clock = Cy_SysTick_GetClockSource();     // SysTick not initialized at startup.  Therefore the clock value returned = 0 = CY_SYSTICK_CLOCK_SOURCE_CLK_LF

    Cy_SysTick_Init(clock, Cy_SysTick_GetReload());    // Cy_SysTick_GetReload() returns 0. 

     //Therefore you're initializing Init() with the low freq clock with a Reload of 0 which effectively does nothing.

    Cy_SysTick_Enable();     // This is redundant since Cy_SysTick_Init() enabled before exiting.

Here is some code frags that I got to work using the IMO clock as the clock source.  IMO set to 8MHz.

uint32_t tick = 0;  // This increments every time the SysTick counter decrements to 0. 

/*********************************************************************************/

void systick_isr(void)

{

    tick++;

}

void main()

{

...

/*Initialize and Enable the SysTick resource*/

Cy_SysTick_Init(CY_SYSTICK_CLOCK_SOURCE_CLK_IMO, (8000000/1000)-1);    // IMO freq/1000 = # of SysTick counts

Cy_SysTick_SetCallback(0, systick_isr);        // point to SysTick ISR to increment the 1ms count

...

     printf("%ld",tick);

...

}

The code above will increment tick every 1msec at the IMO accuracy.

There is another way if you want to avoid the systick_isr if you're interested.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Garen,

Updated:  It appears the Cy_SysTick_GetCountFlag() is not working.  Here's a rewrite of this post:

If you want to avoid the ISR occurring once every 1 msec then you can set up the following:  (Now it happens once every 8.53 minutes)

  • Set the System Clock CLK_LF to WCO.  This is the 32768 Hz +/- 150ppm clock.  More accurate than the RC ILO clock.
  • Use this as the code in main for the setup and counter value retrieval.

uint32_t systick_wrap = 0;     // Needed if you want to count beyond 24 bits.

/*********************************************************************************/

void systick_isr(void)

{

    systick_wrap++;

}

#define SYSTICK_MAX_CNT_BITS 24u

#define SYSTICK_MAX_CNT        (1<<SYSTICK_MAX_CNT_BITS)-1

/*********************************************************************************/

int main(void)

{

...

/*Initialize and Enable the SysTick resource*/

Cy_SysTick_Init(CY_SYSTICK_CLOCK_SOURCE_CLK_LF, SYSTICK_MAX_CNT);

// Clock source set to the CLK_LF system clock which is actually the WCO (32768 Hz) source.

// Reload counter is set to maximum of the 24-bit counter

...

          printf("\r\n%lX%lX\r\n", systick_wrap>>(32-SYSTICK_MAX_CNT_BITS), (((systick_wrap & 0xF)<<SYSTICK_MAX_CNT_BITS) | ((~time_value) & (SYSTICK_MAX_CNT))));

          // First 32-bit is the MS and the the last 32-bits the LS.  If you don't want more than 24-bits of count the MS can be eliminated.

...

}
// You can eliminate the systick_wrap variable if 24-bits of count before the SysTick counter wrap is enough.

With the source clock @ CLK_LF = 32768 Hz, your resolution with GetValue() is about 30.5us per tick.

The closest to 1msec is 1.024msec for 32 SysTick counts.

At 24-bits count before wrap this means every 8.53 minutes the counter will wrap.  If this is sufficient, then you don't need the systick_wrap variable.

With the systick_wrap, the new virtual wrap value is at 56-bits.  This equates to 69,730 years.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
RodolfoGL
Employee
Employee
250 solutions authored 250 sign-ins 5 comments on KBA

PSoC 6 also provides an RTC implementation, which works perfectly for time stamps.

Refer to this code example:

GitHub - cypresssemiconductorco/mtb-example-psoc6-rtc-basics: This example demonstrates the usage of...

0 Likes

Rodolfo,

The RTC does not have msec resolution (struct cy_stc_rtc_config_t).  The best you can get is 1 sec resolution.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes