'Callback in STM32 isn't called
Trying to make simple PWM transmitter i faced with a problem. I have TIM2 with Channel2 (in PWM Generation mode) on board NUCLEO F042K6 and USART1 connected to the board in Async mode (USART works in DMA).
I wanted to make a PWM transmitter that uses a circular buffer that can be filled with one character or several characters at once. The plan was that when the user enters a character (or several characters), the idle line callback is processed, in which a function is called that stores the data in a cyclic buffer. After saving, the data transferred to the buffer is passed to the function PWM_SendChar(...) to convert the data into bits and transfer them over the PWM line. But the problem is when the program goes into PWM_SendChar(...) the callback HAL_TIM_PWM_PulseFinishedCallback(...) isn't called and program stucks in infinite while loop because variable used as a flag for detecting the end of single pulse (PWM_data_sent_flag) wasn't set to value 1.
However, if I use HAL_UART_Recieve(...) func in while(1) loop (located in main(void)) to recieve a char from user program works fine without stucking in while loop in TIM callback. Ofc, for this method I don't use HAL_UARTEx_RxEventCallback(...) and cycle buffer.
Thats's why I think the problem is in USART idle line detection and please help me solve it.
Code Example
Global variable used for waiting the end of pulse:
volatile uint16_t PWM_data_sent_flag = 0;
PWM timer callback:
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM2) {
HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_2);
PWM_data_sent_flag = 1;
}
}
Callback for USART idle line:
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
if (huart == &huart1) {
// Function_to_save_input_char_in_cycle_buffer() is called
}
}
Function used to send char as a PWM signal (emited after Function_to_save_input_char_in_cycle_buffer() completed):
void PWM_SendChar(char ch) {
for (int i = 0, mv = 7; i <= 7; ++i, --mv) {
uint8_t bit = (ch & (1 << mv)) ? 1 : 0;
// PWM_LOW_PERCENT encodes bit with zero value, PWM_HIGH_PERCENT encodes bit with value one
uint16_t duty_cycle = bit == 0 ? PWM_LOW_PERCENT : PWM_HIGH_PERCENT;
// Change TIM2 CCR2 value according to bit's value
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2,
GET_PERCENT_VALUE(TIM2->ARR, duty_cycle));
HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_2);
// Program comes to this cycle and doesn't leave it
while (!PWM_data_sent_flag)
;
PWM_data_sent_flag = 0;
}
}
USART receive to idle launch (half data transmitted callback disabled):
int main(void) {
// Init code
// ...
if (HAL_UARTEx_ReceiveToIdle_DMA(&huart1, (uint8_t*) ring_buf.buff,
ARRAY_LEN(ring_buf.buff)) != HAL_OK) {
Error_Handler();
}
// Disable half word transmitted callback
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
while(1) {
}
}
TIM2 settings:
static void MX_TIM2_Init(void) {
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = { 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 = 48000 - 1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 100 - 1;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK) {
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) {
Error_Handler();
}
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_2)
!= HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
HAL_TIM_MspPostInit(&htim2);
}
USART1 settings:
static void MX_USART1_UART_Init(void) {
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
DMA settings:
static void MX_DMA_Init(void) {
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel4_5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel4_5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel4_5_IRQn);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|