AnsweredAssumed Answered

[STM32F746 Discovery] Receiving multiple bytes over UART7

Question asked by Ivan Ivan on Jun 26, 2017
Latest reply on Jul 5, 2017 by Ivan Ivan

Hello. I'm trying to establish connection between PC and device using UART7. I have developed such code (showing here only main file):

#include "main.h"
#include "stm32f7xx_hal.h"

UART_HandleTypeDef huart6;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void My_UART7_Init(void);
void LL_SendByteUSART(uint8_t data);
#define MAX_RX_BUFFER 512
#define STOP_SYMBOL 0x0D
//#define MANY_SYMBOLS
int main(void)
{
uint8_t rxBuffer[MAX_RX_BUFFER];
uint16_t rxBufferSize= 0;


/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock. */
SystemClock_Config();
SystemCoreClockUpdate();
/* Initialize all configured peripherals */
MX_GPIO_Init();
//MX_USART6_UART_Init();
My_UART7_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */

while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//p1045 of MCU manual

    if (UART7->ISR & USART_ISR_RXNE) {
       uint8_t UART_data = UART7->RDR;
       #ifdef MANY_SYMBOLS
          if (UART_data!=STOP_SYMBOL) {
          rxBuffer[rxBufferSize] = UART_data;
          rxBufferSize+=1;
      } else {
          rxBuffer[rxBufferSize] = 0x00;
          LL_SendByteUSART('O');
          LL_SendByteUSART('K');
          LL_SendByteUSART('|');
          char symbs[20];
          sprintf(symbs, "total length: %d", rxBufferSize);
          uint8_t symbs_indx = 0;
          //here it goes!
              int totalbytes2 = sprintf(symbs, "total length: %d", rxBufferSize);
           while ( symbs_indx<=totalbytes2 ) {
                 LL_SendByteUSART(symbs[symbs_indx]);
                 symbs_indx++;
              }
          //yep!
          rxBufferSize = 0;
       }
       #else
          LL_SendByteUSART('_');
          LL_SendByteUSART(UART_data);
       #endif
    }
}
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 216000000
* HCLK(Hz) = 216000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 25000000
* PLL_M = 25
* PLL_N = 432
* PLL_P = 2
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 7
* @param None
* @retval None
*/

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 = 25;
RCC_OscInitStruct.PLL.PLLN = 432;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 9;

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_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
{
Error_Handler();
}
/*
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART6;
PeriphClkInitStruct.Usart6ClockSelection = RCC_USART6CLKSOURCE_SYSCLK;
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, 0, 0);
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct2;

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOI_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();

/*Configure GPIO pin : PI11 */
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);

}


static void My_UART7_Init(void) {
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;

PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART7;
PeriphClkInitStruct.Uart7ClockSelection = RCC_UART7CLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}

__HAL_RCC_UART7_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct;
/**UART7 GPIO Configuration
PF7 ------> UART7_RX
PF6 ------> UART7_TX
*/

GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; /*GPIO_MODE_AF_PP;*/
GPIO_InitStruct.Pull = GPIO_PULLUP;
//GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART7;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
//baud rate. calculated as in p1002 MCU_ReferenceManual
UART7->BRR = 0xAFC4; //9600, over8 = 1; 8 bit data; no parity; 1 stop bit
//UART7->CR2 |= USART_CR2_MSBFIRST; //Most significant bit first. p1033. Useless
//stop bit is set in CR2. keep it default, 1 stop bit
//UART7->CR3 |= USART_CR3_OVRDIS; //This bit is used to disable the receive overrun. Might be worth setting when receiving is invloved. Or not? Better not touch it
UART7->CR1 = 0x00;
UART7->CR2 = 0x00;
//USART6->CR1 &= ~USART_CR1_M; //word length: 8 bit
//USART6->CR2 &= ~USART_CR2_STOP; //1 stop bit
//p1029
//0b00000000000000000000000000000000
//M1(bit28)M0(bit12) -> 0;0 (1 Start bit, 8 data bits, n stop bits) Keep default, no change
UART7->CR1 |= USART_CR1_OVER8; //oversampling=8. involved in calculation of baud rate.
UART7->CR1 |= USART_CR1_RE; //enable receiver
UART7->CR1 |= USART_CR1_TE; //enable transmitter
UART7->CR1 |= USART_CR1_UE; //enable UART7

}
//Send one byte
void LL_SendByteUSART(uint8_t data) {
while(!(UART7->ISR & USART_ISR_TXE)) {}; //Wait for bit in SR Register
UART7->TDR=data; //write data to UART register
}

Error_Handler routine is omitted here, it's not needed.

I actually need to receive a lot of data from other devices (ending with some marker symbol), but now I'm testing exchange with PC. I have decided to construct some testing sample which sends back the received bytes with some marker ('_') (It is executed when MANY_SYMBOLS definition is commented out). When I send bytes manually, the device works fine. When I send the line of bytes, the device returns only 4 of them and then stops responding. Only pushing RESET button helps, but not from the first time. 

Failure of UART7 transmission. Bytes after sending line are discarded

Other branch (executed when MANY_SYMBOLS is available) returns back nothing. KEIL IDE just hangs when I try to debug the fragment (it hangs on receiving second byte which is 0x0D on line 43 of this example).

 

Why does UART behave like this? How can I make UART to work with lines of data without gaps between them?

Outcomes