cancel
Showing results for 
Search instead for 
Did you mean: 

UART only one byte received

Raider E
Associate III
Posted on January 04, 2017 at 00:52

Hi Guys,

I am transmitting two bytes between two nucleo boards on uart1 and only receiving one byte (one charachter)? what could be the problem

HAL_UART_Receive(&huart1,(uint8_t *)data3,5,10);  void MX_USART1_UART_Init(void) { huart1.Instance = USART1;  huart1.Init.BaudRate = 9600;  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();  } }   void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) { if(huart->Instance==USART1)  {  /* USER CODE BEGIN USART1_MspDeInit 0 */ /* USER CODE END USART1_MspDeInit 0 */  /* Peripheral clock disable */  __HAL_RCC_USART1_CLK_DISABLE();    /**USART1 GPIO Configuration   PB14 ------> USART1_TX  PB15 ------> USART1_RX   */  HAL_NVIC_DisableIRQ(USART1_IRQn);  HAL_GPIO_DeInit(GPIOB, GPIO_PIN_14|GPIO_PIN_15); }  /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ }�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Note: this post was migrated and contained many threaded conversations, some content may be missing.
9 REPLIES 9
Posted on January 04, 2017 at 03:55

You don't provide enough information for anyone to answer your question.  Copying CubeMX generated code is useless.  What is the code you created for the sending node?  You show a call to the HAL receive function which will not return until it gets 5 characters.  How are you getting one character?

Seb
ST Employee
Posted on January 04, 2017 at 17:41

When are these board SW starting (reset)? ==> Start timings, SW delays before sending

Also using a scope, it can be good to check that there is no glitch on TX/RX lines when configuring the GPIO as alternate function (fake byte received by UART)

Hope this helps

Posted on January 04, 2017 at 23:05

Code on the transmitting node is a simple buffer loaded with 5 characters and tranmitting every 200ms in a FreeRTOS thread as follows:

Now if start reception using DMA am receiving the full five characters no problems!, not sure whats the issue with normal transmission. One more thing, what commands I can use to check if transfer and reception are complete by UART?. Many thanks.

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
osThreadId defaultTaskHandle;
osThreadId defaultTaskHandle2;
/* Private variables ---------------------------------------------------------*/
uint8_t Byte_num = 0, LD1=0x0;
uint8_t data[]='GA123';


void Send_can(void *p){
 uint8_t asdf = 0;
 Address_I[0]=0x10;
 Address_I[1]=0x11;
while(1){
 HAL_UART_Transmit(&huart1, (uint8_t*)data,5,100);
HAL_CAN_Transmit(&hcan1, 1);
vTaskDelay(200);
}
}
 
int main(void)
{
 MX_GPIO_Init();
 MX_CAN1_Init();
 MX_SPI1_Init();
 MX_ADC1_Init();
 MX_DAC_Init();
 MX_USART1_UART_Init();
 OLEDinit();
xTaskCreate(Send_can,(signed char*)'TX',1024,NULL,1,NULL);
 xTaskCreate(Receive_can,(signed char*)'RX',1024,NULL,1,NULL);
 vTaskStartScheduler();
while (1)
 {
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
 RCC_ClkInitTypeDef RCC_ClkInitStruct;
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
/**Configure the main internal regulator output voltage 
 */
 __HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/**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 = 8;
 RCC_OscInitStruct.PLL.PLLN = 192;
 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
 RCC_OscInitStruct.PLL.PLLQ = 2;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
/**Activate the Over-Drive mode 
 */
 if (HAL_PWREx_EnableOverDrive() != HAL_OK)
 {
 Error_Handler();
 }
/**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_DIV4;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6) != HAL_OK)
 {
 Error_Handler();
 }
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_USART2;
 PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
 PeriphClkInitStruct.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
/**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, 15, 0);
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
 huart1.Init.BaudRate = 9600;
 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();
 }
}
////////////////////////////////////////////////////////msp file:
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
 if(huart->Instance==USART1)
 {
 /* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
 /* Peripheral clock enable */
 __HAL_RCC_USART1_CLK_ENABLE();
 
 /**USART1 GPIO Configuration 
 PB14 ------> USART1_T
X PB15 ------> USART1_RX 
 */
 GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_PULLUP;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF4_USART1;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
 }
}
}

/////
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
if(huart->Instance==USART1)
 {
 /* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
 /* Peripheral clock disable */
 __HAL_RCC_USART1_CLK_DISABLE();
 
 /**USART1 GPIO Configuration 
 PB14 ------> USART1_T
X PB15 ------> USART1_RX 
 */
 HAL_GPIO_DeInit(GPIOB, GPIO_PIN_14|GPIO_PIN_15);
}
 /* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
 else if(huart->Instance==USART2)
 {
 /* USER CODE BEGIN USART2_MspDeInit 0 */
/* USER CODE END USART2_MspDeInit 0 */
 /* Peripheral clock disable */
 __HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
 PA2 ------> USART2_T
X PA3 ------> USART2_R
X */
 //HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
 HAL_GPIO_DeInit(GPIOD, GPIO_PIN_5|GPIO_PIN_6);
/* Peripheral DMA DeInit*/
 //HAL_DMA_DeInit(huart->hdmarx);
/* Peripheral interrupt DeInit*/
 HAL_NVIC_DisableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspDeInit 1 */
/* USER CODE END USART2_MspDeInit 1 */
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Posted on January 04, 2017 at 23:39

Seems like the problem is on the receive end.  What it sounds like is the routine calling the HAL_UART_Receive() is being interrupted and not running.  ie; The UART hardware has a receive buffer of one character.  When you use the polling version of the HAL call above, it sits in a spin loop waiting for a character, puts it into the receive buffer and waits for the next character.  If your call to HAL_UART_Receive() is either preempted by interrupts or task switches, it will not be polling the flag to empty the buffer and make room for another character.  Or, if the message has been completely sent by the time you call the Receive function, it may just get the one character that the hardware accepted in the buffer before it had an overrun condition.

I'd look to see if you either have a situation where the Receive task is being interrupted or if you are just starting it too late.  Using DMA will fix the first condition, probably not the second.

Posted on January 04, 2017 at 23:43

Thanks for your reply. You are actually right, I do have an interrupt enabled on can messages received every 200ms but thought that would be enough time to service the UART buffer and receive the message in full.

My can receiving routine when a can message received it calls:

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{

 if ((CanHandle->pRxMsg->StdId == 0x321)&&(CanHandle->pRxMsg->IDE == CAN_ID_STD) && (CanHandle->pRxMsg->DLC == 1))
 {
 HAL_UART_Receive(&huart1,(uint8_t *)data3,5);
 ILI9325_TextFont(70,100,&data3[1],RED,BLACK,FONT6x8_table); //&data3[1] means start at address 1 not 0 of the array
Byte_num=CanHandle->pRxMsg->Data[0]; //address
 switch(Byte_num & 0xF0) {
 case 0x10:
 if ((Byte_num & 0x0F)==0){
 //val_disp=(value[Byte_num & 0x0F]/40f)*3.3;
 val_disp=(rs485_ain_get(Byte_num)/40f)*3.3;
 Dic_val[Byte_num & 0x0F]=val_disp;
 sprintf(data, '%.2f', val_disp);
 ILI9325_TextFont(0,70,data,WHITE,BLACK,FONT6x8_table);
 ILI9325_TextFont(40,70,'0x00',RED,BLACK,FONT6x8_table);
//rs485_ain_get( Byte_num);
 }
 else if(((Byte_num & 0x0F)==1)) {
 //val_disp=(value[Byte_num & 0x0F]/40f)*3.3;
 val_disp=(rs485_ain_get(Byte_num)/40f)*3.3;
 Dic_val[Byte_num & 0x0F]=val_disp;
 sprintf(data, '%.2f', val_disp);
 ILI9325_TextFont(0,90,data,RED,BLACK,FONT6x8_table);
 ILI9325_TextFont(40,70,'0x01',RED,BLACK,FONT6x8_table);
 //val_disp=rs485_ain_get( Byte_num);
}
 case 0x20 :
 break;
 }
}
RxIntEnable(CanHandle);
}
void RxIntEnable(CAN_HandleTypeDef *CanHandle) {
 if(CanHandle->State == HAL_CAN_STATE_BUSY_TX)
 CanHandle->State = HAL_CAN_STATE_BUSY_TX_RX;
 else {
 CanHandle->State = HAL_CAN_STATE_BUSY_RX;
/* Set CAN error code to none */
 CanHandle->ErrorCode = HAL_CAN_ERROR_NONE;
/* Enable Error warning Interrupt */
 __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_EWG);
/* Enable Error passive Interrupt */
 __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_EPV);
/* Enable Bus-off Interrupt */
 __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_BOF);
/* Enable Last error code Interrupt */
 __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_LEC);
/* Enable Error Interrupt */
 __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_ERR);
 }
// Enable FIFO 0 message pending Interrupt
 __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_FMP0);
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Posted on January 04, 2017 at 23:52

are you only running the receive code every 200 ms?  if so, you are probably missing the message.  The blocking version of the HAL call waits for upcoming transmissions.  If you are expecting the UART to receive characters in the background you either have to use an Interrupt version of the call or a DMA version, both of which will fill the buffer you specify as long as you make the call to receive the data before it is sent, and then check the buffer (ideally using the end of transfer interrupt) when it's done.

Posted on January 05, 2017 at 00:02

The transmitting end is sending one can message and the the five uart characters every 200ms. which flag I can use to check if reception is complete?

Posted on January 05, 2017 at 00:28

I didn't look at your code before.  You are calling the UART receive from within your CAN receive callback.  Not a good idea.

If you just enable the interrupt on the UART, and either use the IT version of the receive call, or the DMA version, you have a similar HAL_UART_RxCompleteCallback() function like the one you are using for the CAN interface.  Keep them separate, don't try to service one I/O device from within the other's ISR context.  That's probably what was causing the problem in the first place.

Also, if you want to post code, in the upper right corner of the 'Add Comment Edit Box' there is a link for 'Use advanced editor'.  If you click that, then click the '...' menu selection, then pull down the 'more' pulldown, and select 'Syntax highlighter' it will bring up a window where you can paste code and select the language it is written in to highlight it correctly.  The way you are pasting code, it is not only not highlighted, but all of the tabs are lost making it difficult to read.

Posted on January 05, 2017 at 00:46

Thanks for the advice on posting I'll start using this.

So if I setup the HAL_UART_RxCompleteCallback(), do I need to enable the interrupts like I do in the

RxIntEnable( ) above?. If so which flags i will need to enable.

what i would like to achieve is to check if reception is complete, maybe easier to use DMA, but not sure how to check when its complete and then send an acknowledgmentback to uart that you can now send another set of charachters. would that be something reasnable to do to avoid losing data from transmitting node?