2026-03-09 3:58 PM
New programmer and new to the STM32 ecosystem as well.
I am working with a STM32F401 as it has 5v tolerant inputs and 2 32bit clocks.
I have a simple program that reads the 2 32bit TIMs (2&5) in encoder mode, sums the results and then outputs a quadrature signal to a device. I have the GPIO outputs set to "low" speed, which according to my reading should give them a max of 2Mhz output.
Even this appears to be too fast with the HCLK set to the maximum of 84Mhz. On a scope the signal looks pretty bad and my device (cheap DRO) cannot read the signal at that speed.
If I drop the HCLK down to 4Mhz everything works as expected and I get real nice square waves on the scope but this feels "kludgy"
My question is, is there something else I should be looking at to adjust the output rate? HAL_Delay etc feel even more kludgy than stepping the clock down.
Any help would be greatly appreciated; Code follows
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
int32_t cnt1 = __HAL_TIM_GET_COUNTER(&htim2);
int32_t cnt2 = __HAL_TIM_GET_COUNTER(&htim5);
int32_t diff = (cnt1 + cnt2) - lastcnt;
lastcnt = (cnt1 + cnt2);
// Debug
/* float total = ((float)lastcnt * 5);
total = (total/25400);
sprintf(MSG, "EncA: %ld\tEncB: %ld\tLastcnt: %ld\tMoved(in.): %f\n\r", cnt1, cnt2, lastcnt, total);
HAL_UART_Transmit(&huart1, (const uint8_t *)MSG, strlen(MSG), 100);
*/
if (diff < 0) {
dir = false;
diff = abs(diff);
} else {
dir = true;
}
for ( int32_t cnt = 0; cnt < diff; cnt++ ){
if (dir == true){
if (current == 3) { next = 0; } else { next = (current + 1); };
} else {
if (current == 0) { next = 3; } else { next = (current - 1); };
}
quadout (next, dir);
current = next;
}
}
/* USER CODE END 3 */
}
<SNIP>
void quadout(int next, int dir){
//NOTE GPIO_PIN_RESET = HIGH, GPIO_PIN_SET = LOW !!
switch (next) {
case 0:
if (dir == true) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
} else {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9 ,GPIO_PIN_RESET);
}
break;
case 1:
if (dir == true) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8 ,GPIO_PIN_RESET);
}
break;
case 2:
if (dir == true) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9 ,GPIO_PIN_SET);
}
break;
case 3:
if (dir == true) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
} else {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8 ,GPIO_PIN_SET);
}
break;
default:
break;
}
}
Solved! Go to Solution.
2026-03-11 12:14 AM
To me this looks like problematic power supply/PCB layout/ground arrangement.
What hardware is this, your own, or a "known good" board such as Nucleo?
JW
2026-03-11 3:51 AM
This is a NUCLEO-F401RE
Full disclosure: everything is connected via breadboard and could be suspect.
2026-03-11 3:55 AM
Thank you! This seems like the correct solution.
2026-03-12 3:40 AM
Just to follow up this worked perfectly. I set up a 5us delay following each bit swap and the signal is now nice and clean and the DRO reads the signal perfectly.