- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I've created a project that is essentially a pulse generator. It is implemented using the TCPWM block set as a Timer Counter. I'm using the CY8CKIT-042 Pioneer Kit.
The count frequency is set to 20 kHz (50 us between counts) and it runs continuously. What I did was the following:
1) Init Compare register of the counter with a first value.
2) After the counter reaches the set value, the compare register performs a swap with the Compare Buffer. This is done by ticking the option given in the Counter tab.
3) An interrupt is signaled at the time of compare equal, and it updates the Compare Buffer with the next value (with a counter increment after update).
4) The signal from the cc output of the TCPWM was hooked to the reload input in order to reset the counter.
All the compare values are below 20000, so in theory I expect to get a pulse every less than a second or so. But in this setting, I had about 2-3 seconds interval before the next pulse arrives. To make sure it wasn't the compare value that I got wrong, I used 20000 as a fixed value in both Compare and Compare Buffer registers (without any update of these values) and it still outputs one pulse every 3 seconds.
I'm wondering if I did something wrong. I attach the project in this post. UART is for debug. Alternatively, you can reroute HR_Out_Pin to the polychromatic LED pins.
Thanks,
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello
The pulse takes 2 to 3 seconds interval to arrive in the initial project because although the compare buffer values are being continuously changed, the period value remains a constant 65535 (i.e., reload does not happen) as shown in the figure below:
The interrupt will be generated once the counter value equals the compare value but this will happen only once during a period. This is because even after the interrupt is generated the counter will keep on incrementing upto the maximum value and reload only after that. Thus the interrupt interval will be around 65535/20000 = 3.27 sec
In order to generate pulse within 1 or less than 1 sec (depending upon the hrCountVal), we need to change the 'period' value also along with the compare value.
In order to do this we need to use the API: HR_Trigger_Counter_WritePeriod(hrCountVal[hrCountIdx++]); in the sampling part of the code
Also set the initial period, compare value and compare buffer value as 20000 as shown in the figure below.
I have attached the modified project below.
Regards
Ekta
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I notices some points I'd like to suggest to change
(1) make index which is updated in the ISR to volatile
volatile uint16 hrCountIdx = 0; // modified
(2) WriteCompareBuf should be changed to WriteCompare
(3) The reload may not working correctly, so I added WriteCounter(0) ;
(4) Do not put UartPutString() inside an ISR instead I used the red led.
At least the LED's on/off interval seems to be around 1sec or less on my CY8CKIT-042.
so my modified main.c looked like
===============
/* Heart-Rate Sensor
*
* Muhammad Haziq Kamarul Azman
* Universiti Kuala Lumpur
* British Malaysian Institute
*
*/
#include <device.h>
#define HR_COUNTER_IDX_NUM 748
uint16 hrCountVal[HR_COUNTER_IDX_NUM] = {
/* removed to make it shorter to display here */
17425, 17689, 17749, 17423, 17342, 17620 };
volatile uint16 hrCountIdx = 0; // modified
CY_ISR_PROTO(HR_Update_Swap_Int_EXISR);
CY_ISR(HR_Update_Swap_Int_EXISR)
{
// HR_Trigger_Counter_WriteCompareBuf(hrCountVal[hrCountIdx]) ;
HR_Trigger_Counter_WriteCompare(hrCountVal[hrCountIdx]) ;
HR_Trigger_Counter_WriteCounter(0) ;
hrCountIdx = (hrCountIdx + 1) % HR_COUNTER_IDX_NUM ;
LED_Write(!LED_Read()) ;
// Comm_UART_UartPutString("Sample!\r\n");
HR_Update_Swap_Int_ClearPending();
HR_Trigger_Counter_ClearInterrupt(HR_Trigger_Counter_INTR_MASK_CC_MATCH);
}
int main(void)
{
CyGlobalIntEnable; // Enable global interrupts.
/* Initialization */
HR_Sample_Clock_Start();
HR_Update_Swap_Int_StartEx(HR_Update_Swap_Int_EXISR);
Comm_UART_Start();
Comm_UART_UartPutString("Starting\r\n");
/* Start sampling*/
HR_Trigger_Counter_WriteCompare(20000);//hrCountVal[hrCountIdx++]);
HR_Trigger_Counter_Start();
while(1);
}
===============
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
After posting previous response, I felt having reload, which is not working uneasy.
So I modified your project like below
Schematic
Since you are using TCPWM as a timer, let's use "period" for the control
so that when period hits, TC is asserted and reload is automatically done
Then I set the initial period to 20000, instead of 65535.
And I modified your ISR as
======================
CY_ISR(HR_Update_Swap_Int_EXISR)
{
period = hrCountVal[hrCountIdx] ;
// HR_Trigger_Counter_WritePeriod(period) ;
HR_Trigger_Counter_WritePeriodBuf(period) ;
hrCountIdx = (hrCountIdx + 1) % HR_COUNTER_IDX_NUM ;
LED_Write(!LED_Read()) ;
HR_Update_Swap_Int_ClearPending();
HR_Trigger_Counter_ClearInterrupt(HR_Trigger_Counter_INTR_MASK_TC) ;
}
======================
I tried both
HR_Trigger_Counter_WritePeriod(period) ;
and
HR_Trigger_Counter_WritePeriodBuf(period) ;
for my human sense I did not notice difference,
but may be WritePeriodBuf() can set more exact timing.
And let main report the change of the period
======================
int main(void)
{
CyGlobalIntEnable; // Enable global interrupts.
Comm_UART_Start();
sprintf(str, "Starting (%s %s)\r\n",__DATE__, __TIME__);
print(str) ;
/* Initialization */
HR_Sample_Clock_Start();
HR_Update_Swap_Int_StartEx(HR_Update_Swap_Int_EXISR);
/* Start sampling*/
HR_Trigger_Counter_WritePeriod(period);//hrCountVal[hrCountIdx++]);
HR_Trigger_Counter_Start();
while(1) {
if (period != prev_period) {
sprintf(str, "period %d\r\n", period) ;
print(str) ;
prev_period = period ;
}
}
}
======================
Then Tera Term log was
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello
The pulse takes 2 to 3 seconds interval to arrive in the initial project because although the compare buffer values are being continuously changed, the period value remains a constant 65535 (i.e., reload does not happen) as shown in the figure below:
The interrupt will be generated once the counter value equals the compare value but this will happen only once during a period. This is because even after the interrupt is generated the counter will keep on incrementing upto the maximum value and reload only after that. Thus the interrupt interval will be around 65535/20000 = 3.27 sec
In order to generate pulse within 1 or less than 1 sec (depending upon the hrCountVal), we need to change the 'period' value also along with the compare value.
In order to do this we need to use the API: HR_Trigger_Counter_WritePeriod(hrCountVal[hrCountIdx++]); in the sampling part of the code
Also set the initial period, compare value and compare buffer value as 20000 as shown in the figure below.
I have attached the modified project below.
Regards
Ekta
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Thanks for the replies (also to Tanaka).
The thing about the counter not stopping makes sense (also answers why the period is roughly 3 secs).
However, I don't understand why the reload input is not working. I might be wrong about the cc output being a pulse.
Anyone knows about this issue?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I tried to measure what was happening
with slightly modified schematic.
I probed LED(P1[1]) pin and HR_Out_Pin (P0[2])
The pulse at CC (HR_Out_Pin) was
pulse width was about 136ns (= 7.353MHz),
where the clock to the counter is 24MHz divided by 1200 = 20KHz?
So this pulse will be very difficult to be caught by the counter.
Meantime, I measured the delay from the pulse to the LED(ISR assignment)
The delay was about 5+ us.
So resetting counter from ISR may be slow.
If we compare it with 20kHz (= 50us), it may be ignored.
But I'd rather let the hardware reset (or reload) the counter.
So I prefer to use counter period with which at TC the reload will take place automatically by the hardware
instead of using compare which will cause some delay before we can do something to reset the counter.
moto