I have some problem with the handling of the timer in code (STM32F303RE). My goal is to send messages to UART port every 200ms (one packet) and every 1s (second packet). I implemented timer (MX_TIM6_Init) which increments 2 variables (timer100ms and timer1000ms) every 100ms (HAL_TIM_PeriodElapsedCallback).
What the code does?
Sends messages to the UART in normal operation. Timing and data are OK - everything works fine here. When the other device wants to send information to the STM32, an "ED" frame is sent first, which changes the flag (flag_UART_SEND_DATA to FALSE) and turns off all communication in main loop. Then it sends the relevant frame and waits for a response with the same frame (echo).
When the code have commented sections about checking the values of timers and data everything works good (even when data is send every 100ms-120ms):
if (flag_UART_SEND_DATA == TRUE) {
// if (timer100ms >= 2) {
Print_CAN_Frame("Tx", IPC_Ligths.ID, IPC_Ligths.DLC, IPC_Ligths.CAN_Tx);
HAL_Delay(5);
Print_CAN_Frame("Tx", IPC_SpeedOdometerInfo.ID, IPC_SpeedOdometerInfo.DLC, IPC_SpeedOdometerInfo.CAN_Tx);
HAL_Delay(5);
Print_CAN_Frame("Tx", IPC_SpeedOdometerInfo.ID, IPC_SpeedOdometerInfo.DLC, IPC_SpeedOdometerInfo.CAN_Tx);
HAL_Delay(5);
Print_CAN_Frame("Tx", IPC_SpeedOdometerInfo.ID, IPC_SpeedOdometerInfo.DLC, IPC_SpeedOdometerInfo.CAN_Tx);
HAL_Delay(5);
timer100ms = 0;
// } else if (timer1000ms == 10) {
Print_CAN_Frame("Tx", IPC_StatusBCM.ID, IPC_StatusBCM.DLC, IPC_StatusBCM.CAN_Tx);
HAL_Delay(100);
timer100ms = 0;
timer1000ms = 0;
// }
}
Where does the issue occur?
When the sections are uncommented as below. The breaks between sent frames are larger and despite this the code does not work properly. When any message is sent (e.g. by TeraTerm), only the first two characters of the sent message are received in response (e.g. by sending HELLO gives HE). The only difference when there is a problem is that the sections in the main loop. The frame sent by UART to the device goes to entirely and full data is passed on to HAL_UART_TRANSMIT_IT (in HAL_UART_RxCpltCallback) and HAL_UART_TRANSMIT_IT return HAL_OK -> but on console it sends only 2 characters. Do you have any ideas / suggestions what to check more / where is the issue?
if (flag_UART_SEND_DATA == TRUE) {
if (timer100ms >= 2) {
Print_CAN_Frame("Tx", IPC_Ligths.ID, IPC_Ligths.DLC, IPC_Ligths.CAN_Tx);
HAL_Delay(5);
Print_CAN_Frame("Tx", IPC_SpeedOdometerInfo.ID, IPC_SpeedOdometerInfo.DLC, IPC_SpeedOdometerInfo.CAN_Tx);
HAL_Delay(5);
Print_CAN_Frame("Tx", IPC_SpeedOdometerInfo.ID, IPC_SpeedOdometerInfo.DLC, IPC_SpeedOdometerInfo.CAN_Tx);
HAL_Delay(5);
Print_CAN_Frame("Tx", IPC_SpeedOdometerInfo.ID, IPC_SpeedOdometerInfo.DLC, IPC_SpeedOdometerInfo.CAN_Tx);
HAL_Delay(5);
timer100ms = 0;
} else if (timer1000ms == 10) {
Print_CAN_Frame("Tx", IPC_StatusBCM.ID, IPC_StatusBCM.DLC, IPC_StatusBCM.CAN_Tx);
HAL_Delay(5);
timer100ms = 0;
timer1000ms = 0;
}
}
Full code:
#define TRUE 1
#define FALSE 0
#define FIFO_BUFFER g_rxFifo;
#define USART_HEADER_LENGTH 6
#define USART_ID_LENGTH 7
#define USART_DLC_LENGTH 1
#define USART_MAX_MESSAGE_LENGTH 17
#define USART_DLC_LOCATION 23
#define LENGTH_CARRIGE_RETURN_SIGN 1
TIM_HandleTypeDef htim6;
UART_HandleTypeDef huart2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM6_Init(void);
void SystemClockConfig(void);
void UART2_Init(void);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
void Clear_Array(uint8_t array[], uint16_t size);
void Print_CAN_Frame(char CanFrameName[], uint32_t CanID, uint32_t CanDlc, uint8_t CANmsg[]);
void Parse_From_UART(char CanFrame[]);
uint8_t* Convert_To_HEX(char *string);
void Save_Data_To_CAN_Frame(CAN_MessageTypeDef canBuffer);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
CAN_MessageTypeDef canUartBuffer;
uint32_t timer100ms = 0;
uint32_t timer1000ms = 0;
uint8_t uint_8Buffer[70];
uint8_t data_buffer[70];
uint32_t count = 0;
uint8_t rcvd_data;
uint8_t flag_UART_TX_COMPLETED = FALSE;
uint8_t flag_UART_RX_COMPLETED = FALSE;
uint8_t flag_UART_SEND_DATA = TRUE;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_USART2_UART_Init();
MX_TIM6_Init();
HAL_UART_Receive_IT(&huart2, &rcvd_data, 1);
HAL_TIM_Base_Start_IT(&htim6);
while (1)
{
if (flag_UART_SEND_DATA == TRUE) {
// if (timer100ms >= 2) {
Print_CAN_Frame("Tx", IPC_Ligths.ID, IPC_Ligths.DLC, IPC_Ligths.CAN_Tx);
HAL_Delay(5);
Print_CAN_Frame("Tx", IPC_SpeedOdometerInfo.ID, IPC_SpeedOdometerInfo.DLC, IPC_SpeedOdometerInfo.CAN_Tx);
HAL_Delay(5);
Print_CAN_Frame("Tx", IPC_SpeedOdometerInfo.ID, IPC_SpeedOdometerInfo.DLC, IPC_SpeedOdometerInfo.CAN_Tx);
HAL_Delay(5);
Print_CAN_Frame("Tx", IPC_SpeedOdometerInfo.ID, IPC_SpeedOdometerInfo.DLC, IPC_SpeedOdometerInfo.CAN_Tx);
HAL_Delay(5);
timer100ms = 0;
// } else if (timer1000ms == 10) {
Print_CAN_Frame("Tx", IPC_StatusBCM.ID, IPC_StatusBCM.DLC, IPC_StatusBCM.CAN_Tx);
HAL_Delay(100);
timer100ms = 0;
timer1000ms = 0;
// }
}
while((flag_UART_RX_COMPLETED && flag_UART_TX_COMPLETED))
{
if (data_buffer[0] == 'S' || data_buffer[0] =='E') // if received data is START / END tx Transmission:
{
Clear_Array(data_buffer, strlen(data_buffer));
count = 0;
flag_UART_RX_COMPLETED = FALSE;
flag_UART_TX_COMPLETED = FALSE;
HAL_UART_Receive_IT(&huart2, &rcvd_data, 1);
} else {
count = 0;
//Parse_From_UART(data_buffer);
//Save_Data_To_CAN_Frame(canUartBuffer);
Clear_Array(data_buffer, 70);
flag_UART_RX_COMPLETED = FALSE;
flag_UART_TX_COMPLETED = FALSE;
}
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (rcvd_data == '\r') {
data_buffer[count++] = '\r';
flag_UART_RX_COMPLETED = TRUE;
if (data_buffer[0] == 'S' && data_buffer[1] == 'T') {
flag_UART_SEND_DATA = TRUE;
}
else if ((data_buffer[0] == 'E' && data_buffer[1] == 'D') || (data_buffer[0] == 'E' && data_buffer[1] == 'E')) {
flag_UART_SEND_DATA = FALSE;
HAL_UART_Transmit_IT(&huart2, data_buffer, count);
while (HAL_UART_GetState(&huart2) != HAL_UART_STATE_BUSY_TX);
count = 0;
HAL_UART_Receive_IT(&huart2, &rcvd_data, 1);
return;
}
if (HAL_UART_Transmit_IT(&huart2, data_buffer, count) != HAL_OK)
{
Error_Handler(); // if HAL_ERROR
}
count = 0;
}
else
{
data_buffer[count++] = rcvd_data;
}
HAL_UART_Receive_IT(&huart2, &rcvd_data, 1);
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
flag_UART_TX_COMPLETED = TRUE;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
timer100ms=timer100ms+1;
timer1000ms=timer1000ms+1;
}
static void MX_TIM6_Init(void)
{
htim6.Instance = TIM6;
htim6.Init.Prescaler = 119;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
htim6.Init.Period = (59999);
if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
{
Error_Handler();
}
}
void Print_CAN_Frame(char CanFrameName[], uint32_t CanID, uint32_t CanDlc, uint8_t CANmsg[])
{
char buffer[70] = {0};
sprintf(buffer,"CAN_%s| ID:0x%02X| DLC:%d| FRAME: ",CanFrameName,(unsigned int)CanID,(unsigned int)CanDlc);
for (uint16_t i = 0; i<CanDlc; i++)
{
sprintf(buffer+strlen(buffer),"%02X ",*(CANmsg+i)); // print all DATA elements one by one
}
sprintf(buffer+strlen(buffer),"\n\r");
Clear_Array(uint_8Buffer, 70);
for (uint8_t i = 0U; i<strlen(buffer);i++)
{
uint_8Buffer[i] = (uint8_t)buffer[i];
}
if (HAL_UART_Transmit_IT(&huart2, uint_8Buffer, strlen(buffer)) != HAL_OK)
{
Error_Handler();
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
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_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
static void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
}
@update
I found a partial solution - I reduced the priority of timer interruptions so that the UART has higher. For bigger times (500ms) it seems to work but this solution still doesn't satisfy me - its unstable. And what's more, the 300ms timer only works well if the device is in debugging mode. After turning off the debugger the device does not work properly.