2021-08-21 09:25 AM
Hi!
I have Input Capture enabled with DMA. It works.
My buffer is 2 elements and it's a circular buffer. Each element in the buffer gets the counter value from a timer and the counter value goes from 0 to 65535 at 6.5535 seconds.
Question:
I want to compare the difference between the buffer's 2 elements. How can I do that?
Assume that element 0 is 60000 and element 1 is 1000, then the difference would be 65535 - 60000 + 1000 + 1 because the counter value is unsinged 16-bit.
But I don't know which index in the buffer that has the latest updated vale. Do you know?
static uint16_t input_capture0[2] = {0};
static uint16_t input_capture1[2] = {0};
void STM32_PLC_Input_Capture(TIM_HandleTypeDef* htim17, TIM_HandleTypeDef* htim16) {
/*
* Input capture for measuring frequency
* For TIM17 and TIM16
* Timer clock: 48 Mhz
* Prescaler: 4799
* Counter: 65535 (0xffff)
* Update frequency: 0.1526 Hz (1/0.1526 = 6.5535 seconds)
* Example: For every second, it will count 10000
* Lowest frequency measurement: 1/(0xFFFF*0.0001) = 0.1526 Hz
* Highest frequency measurement: 1/(1*0.0001) = 10000 Hz
*/
if(HAL_TIM_IC_Start_DMA(htim16, TIM_CHANNEL_1, (uint32_t*)input_capture1, 2) != HAL_OK)
Error_Handler();
if(HAL_TIM_IC_Start_DMA(htim17, TIM_CHANNEL_1, (uint32_t*)input_capture0, 2) != HAL_OK)
Error_Handler();
}
static float compute_frequency(uint16_t input_capture[]) {
/*
* Typical worst case scenarios:
* T1: 0xFFFF - T0: 0x0
* T1: 0x0 - T0: 0xFFFF
* T1: 0x7FFF - T0: 0x7FFF
* T1: 0x0 - T0: 0x0
*/
uint16_t difference;
if(input_capture[1] > input_capture[0]) {
difference = input_capture[1] - input_capture[0];
return (float) 1/(difference*0.0001f);
} else if(input_capture[1] < input_capture[0]) {
difference = 0xFFFF - input_capture[1] + input_capture[0] + 1;
return (float) 1/(difference*0.0001f);
} else {
return 1/(65335*0.0001f);
}
}
float STM32_PLC_Input_Capture_Get(uint8_t i) {
if(i == 0)
return compute_frequency((uint16_t*)input_capture0);
else
return compute_frequency((uint16_t*)input_capture1);
}
2021-08-21 09:51 AM
Which STM32?
> But I don't know which index in the buffer that has the latest updated vale.
Observe content of DMA NDTR/CNDTR register, beware of the late write in case of dual-port DMA.
I personally wouldn't go for a 2-element buffer.
JW
2021-08-21 10:14 AM
So you would use a longer buffer? Like 1000?
I don't understand. According to the reference manual, this htim17->hdma->Instance->CNDTR, does not tell me at what index the DMA is going to write inside the buffer?
2021-08-21 10:31 AM
Which STM32?
CNDTR indicates you are using a model with single-port DMA. Description of CNDTR in different STM32 models which use it differs, but most if not all explain that it decrements after each transfer.
JW
2021-08-21 10:32 AM
In this case, I'm uisng STM32F37xxx advanced Arm®-based 32-bit MCUs
2021-08-21 10:39 AM
with the caveat I mentioned above. I don't have experience with the single-port DMA in this regard.
JW
2021-08-21 10:45 AM
So if my reference manual says
post-decrementing of the programmed DMA_CNDTRx register
This register contains the remaining number of data items to transfer (number of AHB
‘read followed by write’ transfers)
That means if I have 2 bytes buffer and the DMA have already filled 1 index at the buffer, that means CNDTR will show 1?
And when the circular buffer have been filled, then CNDTR = 0 and then directly CNDTR = 2 because not it's starting at index 0 again?
I can intepret CNDTR as how many elements it has left to write?
2021-08-21 01:08 PM
Yes.
JW