2023-11-25 08:12 AM
I'm having an issue with my STM32F303RE. I'm using CubeMX to initialize ADC1_IN1 as single ended on PA0, and PWM generation on TIM2_CH1 on PA15. Unfortunately, PA0 will OUTPUT a voltage roughly proportional with the duty cycle of the PWM on PA15, i.e. setting the PWM (again, supposed to be on PA15) to 50% duty cycle results in about 1.5V on PA0. The PWM on PA15 is generated correctly. The PA0 voltage looks like a noisy but constant signal, it doesn't have the PWM signal "shape". PA0 is itself compatible with TIM2_CH1, so I guess something is bleeding over somewhere. Please help me fix this programmatically, I'm really not keen on redoing my circuit.
2023-11-25 08:29 AM
What is PA0 connected to externally? Note that results from floating ADC inputs are irrelevant.
2023-11-26 01:14 AM - edited 2023-11-26 01:25 AM
PA0 is connected to the current sense (IPROPI) pin of a DRV8251A motor driver, incidentally driven from the PWM of TIM2 on PA15 and PB3. The motor driver is supposed down if the current is too high, and I suspect that setting a voltage on the current sense pin is interpreted as just that.
As far as I can see, though, the problem here is the bleeding of TIM2_CH1's PWM onto the wrong pin. The same setup (driver, ADC, PWM) works just fine for TIM15 (PA2, PA3) and ADC2 (PA4), and I'm observing the same failure mode on two identical PCB's -- so I don't think anything's fried.
Thanks for replying so quickly btw. Left the office just after posting, but appreciate it.
2023-11-26 06:00 PM
If channels were routed to the wrong pins, it would be a pretty major bug that would have turned up in the errata.
Could be:
You have R_IPROPI on your board, right? Can't see it being due to a bad or malfunctioning DRV8251A in any way.
2023-11-27 12:26 AM
I agree, that's kind of why I can't make sense of it. On a general note, where would I find such errata? I've been looking for a datasheet for the STM32F303 expecting to find a ~2000-page document with basically all I need to know about the mcu, but I can only seem to find application notes and such. I did find the HAL doc, though. I'm completely new to STM, and somewhat green on embedded programming as well.
Which leads me to my followup: how can I check the register values? As I mentioned, the same setup works fine for a different combination of timer/adc/pins, so if anything it's CubeMX messing up the code generation (I'm using the makefile setting and programming in vscode fwiw). The init functions seem to be correct in that all the config information from the CubeMX GUI is carried over to the relevant init functions for ADC and PWM as far as I can see, but I haven't been able to go any deeper than that. Setting the ADC/PA0 pin to RESET_STATE in the GUI does remove the problem.
I just realised that the F303 has DAC functionality. I'm not using it at all, but I suppose what I'm seeing can be said to be a noisy DAC output.
My R_IPROPI is at about 500Ohms, and indeed, those drivers are pretty sturdy. I did suspect some sort of short in it. I didn't have time to unsolder it to remove it as an error source entirely, but the fact that the voltage is proportional to the PWM duty cycle and goes away when I set the pin to RESET_STATE pretty much confirms that the problem is somewhere on the STM.
2023-11-27 01:51 AM
ST puts the most important info usually into 2 documents:
- datasheet: basic description only, but package and pins, including alternate function mapping
- reference manual: detailed descriptions of all peripherals, down to registers and bits
Here's what googling "STM32F303 datasheet" (or ref manual) got me:
https://www.st.com/resource/en/datasheet/stm32f303cb.pdf
2023-11-27 02:27 AM
In the problematic state, read out and check/post GPIOA registers content.
JW
2023-11-27 02:41 AM
Thanks! Reference manual was the magic phrase then, as my version of Google only gave me the basic stuff when I looked for data sheet.
How about my other question about checking what the registers are actually initialized to/which pins are mapped to what functions? Does CubeMX put that in one of the plentiful .h-files it generates, or will I have to check each init function+call tree to see that each register is initiated correctly according to the ref manual?
2023-11-27 03:23 AM
> what the registers are actually initialized to/which pins are mapped to what functions
Read out and check/post GPIOA registers content.
JW
2023-11-27 03:48 AM
what you set to gpio etc you can see in Cube, ie:
+ if not trust in this, see the generated code (in source -> main.c + xxx_msp.c )
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_green_GPIO_Port, LED_green_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_rt_GPIO_Port, LED_rt_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(UCPDn_GPIO_Port, UCPDn_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : USER_BUTTON_Pin */
GPIO_InitStruct.Pin = USER_BUTTON_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(USER_BUTTON_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PF4 */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
....
and in ..msp.c for peripherals :
here for tim-x-init :
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspPostInit 0 */
/* USER CODE END TIM1_MspPostInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/**TIM1 GPIO Configuration
PB1 ------> TIM1_CH3N
PE8 ------> TIM1_CH1N
PE9 ------> TIM1_CH1
PE13 ------> TIM1_CH3
*/
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
....