cancel
Showing results for 
Search instead for 
Did you mean: 

Input Capture: How can I compare the values in a circular DMA buffer?

DMårt
Lead

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);
}

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer
7 REPLIES 7

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

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?

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

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

In this case, I'm uisng STM32F37xxx advanced Arm®-based 32-bit MCUs

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

0693W00000Dq0HhQAJ.pngwith the caveat I mentioned above. I don't have experience with the single-port DMA in this regard.

JW

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?

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

Yes.

JW