I am working with an stm32 f767zit and I am trying to generate PWM signals to control servos, but they are not generating correctly. I followedd the tutorial from here Deep Blue Embedded and was able to generate the PWM signals just fine on an stm32 f103rb, but I switched to the f767zit because I needed more PWM outputs. I have already looked at the HAL documentation and for both and compared them and as far as I can tell there are not any differences in how the pwm signals should be generated.
I have done several projects with the stm32 boards but I am still sort of a noob. I have looked for many hours for a solution but I can not find one. Sorry if this is actually just something simple and basic that I am missing.
Here are screen shots of the pwm outputs. as you can see the f103rb generates them normally, sguare waves at 50hz and 3.3v peaks. The pwm signals on the f767 are made up of lots of spikes and have peaks at 10mV. Although, they do seem to be generating at the correct pulse length
PWM Output of f103rb
PWM Output of f767
In my code all I am trying to do is initalize the servos and the set them to a positon. There are 12 servos and they are using timers 1-4. The specific channels and pins can be seen in the Servo configuration code. My main code initializes all of the perifrials and then calls initServos() which calls SERVO_init() for each servo in SERVO_CfgParam. Then my main loop calls SERVO_moveto(). I am only moving one servo in the main code but I have tested every pin that I am using and get the same results.
I used the same meathod and code for controlling 3 servos on my f013rb without any problems. I cannot figure out what difference there is on the f767zit.
Main Code
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART3_UART_Init();
MX_USB_OTG_FS_PCD_Init();
MX_SPI1_Init();
MX_TIM1_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_TIM4_Init();
/* USER CODE BEGIN 2 */
initServos();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
SERVO_MoveTo(11,90);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Servo configuration.
typedef struct
{
GPIO_TypeDef * SERVO_GPIO;
uint16_t SERVO_PIN;
TIM_TypeDef* TIM_Instance;
uint32_t* TIM_CCRx;
uint32_t PWM_TIM_CH;
uint32_t TIM_CLK;
float MinPulse;
float MaxPulse;
}SERVO_CfgType;
const SERVO_CfgType SERVO_CfgParam[SERVO_NUM] =
{
// Servo Motor 1 Configurations
{
GPIOE,
GPIO_PIN_9,
TIM1,
&TIM1->CCR1,
TIM_CHANNEL_1,
72000000,
0.65,
2.3
},
// Servo Motor 2 Configurations
{
GPIOE,
GPIO_PIN_11,
TIM1,
&TIM1->CCR2,
TIM_CHANNEL_2,
72000000,
0.65,
2.3
},
// Servo Motor 3 Configurations
{
GPIOE,
GPIO_PIN_13,
TIM1,
&TIM1->CCR3,
TIM_CHANNEL_3,
72000000,
0.65,
2.3
},
// Servo Motor 4 Configurations
{
GPIOE,
GPIO_PIN_14,
TIM1,
&TIM1->CCR4,
TIM_CHANNEL_4,
72000000,
0.65,
2.3
},
// Servo Motor 5 Configurations
{
GPIOA,
GPIO_PIN_15,
TIM2,
&TIM2->CCR1,
TIM_CHANNEL_1,
72000000,
0.65,
2.3
},
// Servo Motor 6 Configurations
{
GPIOB,
GPIO_PIN_10,
TIM2,
&TIM2->CCR2,
TIM_CHANNEL_3,
72000000,
0.65,
2.3
},
// Servo Motor 7 Configurations
{
GPIOB,
GPIO_PIN_11,
TIM2,
&TIM2->CCR4,
TIM_CHANNEL_4,
72000000,
0.65,
2.3
},
// Servo Motor 8 Configurations
{
GPIOC,
GPIO_PIN_6,
TIM3,
&TIM3->CCR1,
TIM_CHANNEL_1,
72000000,
0.65,
2.3
},
// Servo Motor 9 Configurations
{
GPIOC,
GPIO_PIN_7,
TIM3,
&TIM3->CCR2,
TIM_CHANNEL_2,
72000000,
0.65,
2.3
},
// Servo Motor 10 Configurations
{
GPIOC,
GPIO_PIN_8,
TIM3,
&TIM3->CCR3,
TIM_CHANNEL_3,
72000000,
0.65,
2.3
},
// Servo Motor 11 Configurations
{
GPIOC,
GPIO_PIN_9,
TIM3,
&TIM3->CCR4,
TIM_CHANNEL_4,
72000000,
0.65,
2.3
},
// Servo Motor 12 Configurations
{
GPIOB,
GPIO_PIN_6,
TIM4,
&TIM4->CCR1,
TIM_CHANNEL_1,
72000000,
0.65,
2.3
}
};
Servo initialization function
void SERVO_Init(uint16_t au16_SERVO_Instance)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_HandleTypeDef htim;
uint32_t PSC_Value = 0;
uint32_t ARR_Value = 0;
//DWT_Delay_Init();
/*--------[ Configure The Servo PWM GPIO Pin ]-------*/
if(SERVO_CfgParam[au16_SERVO_Instance].SERVO_GPIO == GPIOA)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
}
else if(SERVO_CfgParam[au16_SERVO_Instance].SERVO_GPIO == GPIOB)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
}
else if(SERVO_CfgParam[au16_SERVO_Instance].SERVO_GPIO == GPIOC)
{
__HAL_RCC_GPIOC_CLK_ENABLE();
}
else if(SERVO_CfgParam[au16_SERVO_Instance].SERVO_GPIO == GPIOD)
{
__HAL_RCC_GPIOD_CLK_ENABLE();
}
else if(SERVO_CfgParam[au16_SERVO_Instance].SERVO_GPIO == GPIOE)
{
__HAL_RCC_GPIOE_CLK_ENABLE();
}
GPIO_InitStruct.Pin = SERVO_CfgParam[au16_SERVO_Instance].SERVO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(SERVO_CfgParam[au16_SERVO_Instance].SERVO_GPIO, &GPIO_InitStruct);
/*--------[ Calculate The PSC & ARR Values To Maximize PWM Resolution ]-------*/
/* Those Equations Sets The F_pwm = 50Hz & Maximizes The Resolution*/
PSC_Value = (uint32_t) (SERVO_CfgParam[au16_SERVO_Instance].TIM_CLK / 3276800.0);
ARR_Value = (uint32_t) ((SERVO_CfgParam[au16_SERVO_Instance].TIM_CLK / (50.0*(PSC_Value+1.0)))-1.0);
/*--------[ Configure The Servo PWM Timer Channel ]-------*/
/*--[Check The Timer & Enable Its Clock]--*/
if(SERVO_CfgParam[au16_SERVO_Instance].TIM_Instance == TIM1)
{
__HAL_RCC_TIM1_CLK_ENABLE();
}
else if(SERVO_CfgParam[au16_SERVO_Instance].TIM_Instance == TIM2)
{
__HAL_RCC_TIM2_CLK_ENABLE();
}
else if(SERVO_CfgParam[au16_SERVO_Instance].TIM_Instance == TIM3)
{
__HAL_RCC_TIM3_CLK_ENABLE();
}
else if(SERVO_CfgParam[au16_SERVO_Instance].TIM_Instance == TIM4)
{
__HAL_RCC_TIM4_CLK_ENABLE();
}
htim.Instance = SERVO_CfgParam[au16_SERVO_Instance].TIM_Instance;
htim.Init.Prescaler = PSC_Value;
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.Period = ARR_Value;
htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
HAL_TIM_Base_Init(&htim);
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim, &sClockSourceConfig);
HAL_TIM_PWM_Init(&htim);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, SERVO_CfgParam[au16_SERVO_Instance].PWM_TIM_CH);
/*--------[ Calculate & Save The Servo Pulse Information ]-------*/
gs_SERVO_info[au16_SERVO_Instance].Period_Min = (uint16_t) (ARR_Value * (SERVO_CfgParam[au16_SERVO_Instance].MinPulse/20.0));
gs_SERVO_info[au16_SERVO_Instance].Period_Max = (uint16_t) (ARR_Value * (SERVO_CfgParam[au16_SERVO_Instance].MaxPulse/20.0));
/*--------[ Start The PWM Channel ]-------*/
HAL_TIM_PWM_Start(&htim, SERVO_CfgParam[au16_SERVO_Instance].PWM_TIM_CH);
}
Moving the servo
/* Moves A Specific Motor To A Specific Degree That Can Be Float Number */
void SERVO_MoveTo(uint16_t au16_SERVO_Instance, float af_Angle)
{
uint16_t au16_Pulse = 0;
au16_Pulse = ((af_Angle*(gs_SERVO_info[au16_SERVO_Instance].Period_Max - gs_SERVO_info[au16_SERVO_Instance].Period_Min))/180.0)
+ gs_SERVO_info[au16_SERVO_Instance].Period_Min;
*(SERVO_CfgParam[au16_SERVO_Instance].TIM_CCRx) = au16_Pulse;
}
GPIO and timer intitializations
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin|LD2_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(USB_PowerSwitchOn_GPIO_Port, USB_PowerSwitchOn_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : USER_Btn_Pin */
GPIO_InitStruct.Pin = USER_Btn_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(USER_Btn_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : RMII_MDC_Pin RMII_RXD0_Pin RMII_RXD1_Pin */
GPIO_InitStruct.Pin = RMII_MDC_Pin|RMII_RXD0_Pin|RMII_RXD1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : RMII_REF_CLK_Pin RMII_MDIO_Pin RMII_CRS_DV_Pin */
GPIO_InitStruct.Pin = RMII_REF_CLK_Pin|RMII_MDIO_Pin|RMII_CRS_DV_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : LD1_Pin LD3_Pin LD2_Pin */
GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin|LD2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : RMII_TXD1_Pin */
GPIO_InitStruct.Pin = RMII_TXD1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(RMII_TXD1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : USB_PowerSwitchOn_Pin */
GPIO_InitStruct.Pin = USB_PowerSwitchOn_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(USB_PowerSwitchOn_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : USB_OverCurrent_Pin */
GPIO_InitStruct.Pin = USB_OverCurrent_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(USB_OverCurrent_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : RMII_TX_EN_Pin RMII_TXD0_Pin */
GPIO_InitStruct.Pin = RMII_TX_EN_Pin|RMII_TXD0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
}
static void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_OnePulse_Init(&htim1, TIM_OPMODE_SINGLE) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
sBreakDeadTimeConfig.Break2Filter = 0;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
}
/**
* #brief TIM2 Initialization Function
* #param None
* #retval None
*/
static void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 65535;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
HAL_TIM_MspPostInit(&htim2);
}
/**
* #brief TIM3 Initialization Function
* #param None
* #retval None
*/
static void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 65535;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
HAL_TIM_MspPostInit(&htim3);
}
/**
* #brief TIM4 Initialization Function
* #param None
* #retval None
*/
static void MX_TIM4_Init(void)
{
/* USER CODE BEGIN TIM4_Init 0 */
/* USER CODE END TIM4_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM4_Init 1 */
/* USER CODE END TIM4_Init 1 */
htim4.Instance = TIM4;
htim4.Init.Prescaler = 0;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 65535;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM4_Init 2 */
/* USER CODE END TIM4_Init 2 */
HAL_TIM_MspPostInit(&htim4);
}
Let me know if there is any more information that you need.
I think your problem might be due to the alternate function mapping. The F767 datasheet has a table on p.89 listing what values you should put into the GPIOn.AFR registers (GPIO_InitStruct.Alternate in the HAL - I assume) to get the right peripheral on the pin. It looks like your timer channels for those pins are all AF1, and you haven't defined which AF to use in your SERVO_Init routine. It's probably a good idea to fill in every member of the struct, even if you think it's unnecessary, just to make sure you don't miss anything deceptively important.
I am using STM32F401RCT6 chip, and I am trying to do some controlled PWM outputs. I am using TIM1, 2, 3, and 11 for PWM.
The thing is, when I set the same period for timer 1 as for any other timer, the period is the same length but the pulse is different. For example, TIM1 is pulse 6.9us and for others 82.4us when using period 4999.
The picture shows that the period is the same.
The next picture shows the difference in the pulse length.
When I change the pulse from 10 to 1000 the pulse for TIM1 is 720us and for TIM2 794us.
When I saw the difference, the first thing which comes to my mind was that the timers have a different frequency, but the thing is that it would have different frequency of PWM pulse too, but it is not the case.
Can anyone say, what can cause the pulse length to be shorter for timer 1?
My settings are the following:
void MX_TIM11_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim11.Instance = TIM11;
htim11.Init.Prescaler = HAL_RCC_GetPCLK2Freq()/124999;
htim11.Init.CounterMode = TIM_COUNTERMODE_UP;
htim11.Init.Period = 0;
htim11.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim11.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim11) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim11) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim11, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim11);
}
void MX_TIM2_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = HAL_RCC_GetPCLK1Freq()/124999;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim2);
}
void MX_TIM3_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = HAL_RCC_GetPCLK1Freq()/124999;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 0;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim3);
}
void MX_TIM1_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = HAL_RCC_GetPCLK2Freq()/124999;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 0;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim1);
}
I have following function to set parameters for PWM and for starting it:
void setPWM(TIM_HandleTypeDef timer, uint32_t channel, uint16_t period)
{
// stop generation of PWM
HAL_TIM_PWM_Stop(&timer, channel);
TIM_OC_InitTypeDef sConfigOC;
// set the period duration
timer.Init.Period = period;
// re-initialize with new period value
HAL_TIM_PWM_Init(&timer);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
// set the pulse duration
sConfigOC.Pulse = 10;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&timer, &sConfigOC, channel);
// start PWM generation
HAL_TIM_PWM_Start(&timer, channel);
}
UPDATE:
I need to change the period during the run, and it seems like if I call the setPWM function more then once, the problem occurs. The first call appears to be behaving as it should. The weird thing is that I call it the same way for all of the timers but only one will lose the length of the pulse. But right now I have run out of ideas about what to try to find the core of my problem.
Any Idea what I can try to find what cause it?
Thank you,
Hana
I have now all timers are working the same way. I am not sure why it was reacting differently on timer 1, but if I do not call setPWM() again and instead I just set the ARR register while running, it behaves the same for all timers.
timer.Instance->ARR = period;
I'm working on the ADC , conversion triggered by timer2 , but there is no output. APB2 Timers clock is 80Mhz. Only 1 ADC channel. ADC clock is also 80Mhz. ADC conversion is triggered by 3.3us. Controller is STM32L452. Ignore Timer3.
Please let me know where I'M WRONG.
ADC+TIMER2+DMA
#define BUFFERSIZE (50U)
static uint32_t adc_buf[BUFFERSIZE] = {0};
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
ADC_ChannelConfTypeDef sConfig;
DMA_HandleTypeDef hdma_adc1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_TIM3_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM2_Init(void);
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
/**
* #brief The application entry point.
*
* #retval None
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM3_Init();
MX_ADC1_Init();
MX_TIM2_Init();
MX_DMA_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start(&htim2);
/* USER CODE END 2 */
HAL_ADC_Start_DMA(&hadc1, adc_buf, BUFFERSIZE);
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
PeriphClkInit.PLLSAI1.PLLSAI1M = 1;
PeriphClkInit.PLLSAI1.PLLSAI1N = 16;
PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_ADC1CLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_1);
/**Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* ADC1 init function */
static void MX_ADC1_Init(void)
{
/**Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_5;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/* TIM2 init function */
static void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
__HAL_RCC_TIM2_CLK_ENABLE();;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 267;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.RepetitionCounter = 0;
// htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/* TIM3 init function */
static void MX_TIM3_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 2000;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (HAL_TIM_OC_Init(&htim3) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
// sConfigOC.OCMode = TIM_OCMODE_TIMING;
// sConfigOC.Pulse = 0;
// sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
// sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_TIM_MspPostInit(&htim3);
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
PA8 ------> RCC_MCO
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = DEBUG_LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DEBUG_LED_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PA8 */
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == htim3.Instance)
{
/* Toggle LED */
HAL_GPIO_TogglePin(DEBUG_LED_GPIO_Port, DEBUG_LED_Pin);
}
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hadc->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_ADC_CLK_ENABLE();
/**ADC1 GPIO Configuration
PA0 ------> ADC1_IN5
*/
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* ADC1 DMA Init */
/* ADC1 Init */
hdma_adc1.Instance = DMA1_Channel1;
hdma_adc1.Init.Request = DMA_REQUEST_0;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_NORMAL;
hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
enter link description here
firstly htim2.Init.Prescaler = 0; try to give any number but 0 to prescaler to receive interrupt htim2.Init.Prescaler = 1 or 2 or else;
Secondly in your callback you are checking timer 2
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == htim3.Instance)
{
/* Toggle LED */
HAL_GPIO_TogglePin(DEBUG_LED_GPIO_Port, DEBUG_LED_Pin);
}
}
I propose you to check timer2 because you are initializing the timer2 in your code which is //HAL_TIM_Base_Start(&htim2);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2)
{
/* Toggle LED */
HAL_GPIO_TogglePin(DEBUG_LED_GPIO_Port, DEBUG_LED_Pin);
}
}
Im using STM32F429 board and my ultimate goal is to get ADC conversion(set to deliver 2.7Ksps or 2.7 samples every 1ms) using TIM8 trigger, collect 1000 samples in buffer and do DMA transfer every second. I managed to get Timer running, but for some reason ADC conversion is not triggered. Without timer ADC is running well and DMA working (just not every 1ms, but faster).
APB2 Timers clock is 168Mhz.
APB2 Peripherals clock is 84Mhz.
TIM8 init function:
void MX_TIM8_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_OC_InitTypeDef sConfigOC;
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
__HAL_RCC_TIM8_CLK_ENABLE();
htim8.Instance = TIM8;
htim8.Init.Prescaler = TIM_CLOCKPRESCALER_DIV8; // 1/(168MHz / 2^8) = 1.5238us
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 655; // 1.5238us * 656 = 0.999ms ~ 1ms
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_TIM_Base_Start(&htim8);
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_DISABLE;
sSlaveConfig.InputTrigger = TIM_TS_ITR1;
if (HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (HAL_TIM_OC_Init(&htim8) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sConfigOC.OCMode = TIM_OCMODE_TIMING;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_OC_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
ADC init function:
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
__HAL_RCC_GPIOA_CLK_ENABLE();
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; // 84MHz / 2^6 = 1312.5 KHz
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_5;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; // 1312.5KHz / 480cyc per sample = 2.7Ksps
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_7;
sConfig.Rank = 2;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
}
}
Main code:
int main(void)
{
//MCU Configuration----------------------------------------------------------
// Reset of all peripherals, Initializes the Flash interface and the Systick.
HAL_Init();
// Configure the system clock
SystemClock_Config();
// Initialize all configured peripherals
MX_DMA_Init();
MX_ADC1_Init();
MX_TIM8_Init();
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_buf, ADC_BUFFER_LENGTH);
DBGMCU->APB2FZ |= (DBGMCU_APB2_FZ_DBG_TIM8_STOP); //Stop timer if code hit a breakpoint
int timerValue = 0;
while (1)
{
timerValue = __HAL_TIM_GET_COUNTER(&htim8);
if (halfConvFlag != false)
{
println ("Half Conversion callback");
halfConvFlag = false;
}
else if (fullConvFlag != false)
{
println ("Full Conversion callback");
fullConvFlag = false;
}
}
}
When debugging, __HAL_TIM_GET_COUNTER gives me the count that proves it is working, but ADC_buf is not collecting any values. What am I missing, clock configurations should be correct 2 channels, 2 samples per ms and timer is close to 1ms. I generated the timer configuration using STM32CubeMX.
I generated some code with CubeMX. I want that timer 2 is triggering timer 3. If an overflow on Timer 2 occurs, Timer 3 should count up 1. I tried some configurations but nothing worked - no interrupt on timer3 when I set the output trigger (timer 2)
sMasterConfig.MasterOutputTrigger
to the same value as (timer 3)
sSlaveConfig.SlaveMode
I have still no interrupt on timer 3
This is the full configurationcode from both Timers:
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
/* TIM2 init function */
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 54;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 250;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim3.Instance = TIM3;
htim3.Init.Prescaler = 1;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 8000;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
if (HAL_TIM_SlaveConfigSynchronization(&htim3, &sSlaveConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
Config structs should be initialized.
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
Structures defined in a function body will not be initialized, fields not explicitly initialized will get some unpredictable value.
TIM_ClockConfigTypeDef sClockSourceConfig = {};
Using this form will explicitly zero all fields before use.
Wrong input trigger
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
Using ITR0 makes TIM3 a slave of TIM1. The correct value is TIM_TS_ITR1. See the TIMx internal trigger connection table at the end of the desciption of the TIMx slave mode control register TIMx_SMCR in the Reference Manual.
A working example without HAL
Well, it's still using a few useful macros from HAL.
void TIM3_IRQHandler(void) {
if(TIM3->SR & TIM_SR_UIF) {
TIM3->SR = ~TIM_SR_UIF;
do_something();
}
}
void starttimers(void) {
NVIC_EnableIRQ(TIM3_IRQn);
__HAL_RCC_TIM2_CLK_ENABLE();
__HAL_RCC_TIM3_CLK_ENABLE();
TIM3->ARR = 8000; // slave timer period
// trigger selection TS=001 ITR1 = TIM2, slave mode SMS=0111 external clock mode 1
TIM3->SMCR = TIM_TS_ITR1 | TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_2;
TIM3->DIER = TIM_DIER_UIE; // interrupt on update event (timer overflow)
TIM3->CR1 = TIM_CR1_CEN; // enable timer 3
TIM2->PSC = 54; // prescaler preload
TIM2->EGR = TIM_EGR_UG; // update prescaler
TIM2->ARR = 250; // master timer period
TIM2->CR2 = TIM_TRGO_UPDATE; // master mode selection MMS=010 Update event
TIM2->CR1 = TIM_CR1_CEN; // enable timer 2
}