** STM32f427 UART с DMA ** Старший бит иногда равен 1 при получении данных с консоли - PullRequest
0 голосов
/ 12 июня 2018

У меня возникла проблема при использовании STM32f427 UART с DMA (с использованием библиотеки HAL stm cube).

Я хотел бы создать функцию эхосигнала консоли, поэтому я немедленно отвечаю на полученные данные в функции обработчика прерываний холостого хода uart.

Но иногда самый высокий бит полученных данных будет равен 1, когда я вводю любую клавишу на клавиатуре.такие как следующие

0x31 -> 0xB1
0x32 -> 0xB2
0x40 -> 0xC0

У кого-нибудь есть идеи?следующий сегмент кода.

Большое спасибо.

Моя конфигурация Uart выглядит следующим образом

uart_handler.Instance          = USARTx;
uart_handler.Init.BaudRate     = baudrate;
uart_handler.Init.WordLength   = UART_WORDLENGTH_8B;
uart_handler.Init.StopBits     = UART_STOPBITS_1;
uart_handler.Init.Parity       = UART_PARITY_NONE;
uart_handler.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
uart_handler.Init.Mode         = UART_MODE_TX_RX;
uart_handler.Init.OverSampling = UART_OVERSAMPLING_8;

Мои PIN и DMAконфигурация каналов выглядит следующим образом

GPIO_InitStruct.Pin       = USARTx_TX_PIN;
GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull      = GPIO_PULLUP;
GPIO_InitStruct.Speed     = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = USARTx_TX_AF;
HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = USARTx_RX_PIN;
GPIO_InitStruct.Mode      = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull      = GPIO_NOPULL;
GPIO_InitStruct.Alternate = USARTx_RX_AF;
HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);
hdma_tx.Instance                 = USARTx_TX_DMA_STREAM;
hdma_tx.Init.Channel             = USARTx_TX_DMA_CHANNEL;
hdma_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
hdma_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
hdma_tx.Init.MemInc              = DMA_MINC_ENABLE;
hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
hdma_tx.Init.Mode                = DMA_NORMAL;
hdma_tx.Init.Priority            = DMA_PRIORITY_LOW;
hdma_tx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
hdma_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
hdma_tx.Init.MemBurst            = DMA_MBURST_INC16;
hdma_tx.Init.PeriphBurst         = DMA_MBURST_INC16;
HAL_DMA_Init(&hdma_tx);

/ * Свяжите инициализированный дескриптор DMA с дескриптором UART * /

__HAL_LINKDMA(huart, hdmatx, hdma_tx);

/ * Настройте обработчик DMA для процесса приема * /

hdma_rx.Instance                 = USARTx_RX_DMA_STREAM;
hdma_rx.Init.Channel             = USARTx_RX_DMA_CHANNEL;
hdma_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
hdma_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
hdma_rx.Init.MemInc              = DMA_MINC_ENABLE;
hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
hdma_rx.Init.Mode                = DMA_NORMAL;
hdma_rx.Init.Priority            = DMA_PRIORITY_HIGH;
hdma_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
hdma_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
hdma_rx.Init.MemBurst            = DMA_MBURST_INC16;
hdma_rx.Init.PeriphBurst         = DMA_MBURST_INC16;

И использовать прерывание бездействия uart для получения данных.

uint32_t temp;
if((__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET))
{
__HAL_UART_CLEAR_IDLEFLAG(huart);
HAL_UART_DMAStop(&uart_handler);
temp = uart_handler.hdmarx->Instance->NDTR;
g_usart_info.rx_len =  USART_DMA_RECV_LEN - temp;
g_usart_info.receive_flag = 1;
g_usart_info.usart_dma_tx_buff = g_usart_info.usart_dma_rx_buff[0] ;
memset(g_usart_info.usart_dma_rx_buff, 0,                
sizeof(g_usart_info.usart_dma_rx_buff));
__HAL_UART_CLEAR_FLAG(&uart_handler, UART_FLAG_RXNE);
g_usart_info.usart_dma_rx_buff[0] = 0;
HAL_UART_Receive_DMA(&uart_handler, g_usart_info.usart_dma_rx_buff, 
USART_DMA_RECV_LEN);
}

Спасибо.

Я отследил функцию UART_Receive_IT и добавил код отладки.и вставьте точку останова для int a = * (huart-> pRxBuffPtr - 1);

Я обнаружил, что huart-> Instance-> DR равен 0x31, но int a равен 0xB1.

Я пыталсяотключить другое прерывание, но оно все еще не может быть решено.

if(huart->Init.Parity == UART_PARITY_NONE)
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
                if(*(huart->pRxBuffPtr - 1) != 0x31)
                {
                    int a = *(huart->pRxBuffPtr - 1);
                    a = a;
                }
      }
      else
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
      }

==============================================================================

Я нашел проблемную точку

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 /*| RCC_CLOCKTYPE_PCLK2*/);

Если я прокомментирую RCC_CLOCKTYPE_PCLK2, эту проблему можно решить.Но я не знаю почему, это официальный пример кода.Я думаю, что это должно быть правильно.

Ответы [ 2 ]

0 голосов
/ 15 июня 2018

Наконец, я получил основную причину для этого вопроса.Я использую официальный пример кода для своей платы, но этот пример кода предназначен для официальной платы разработки, плата с встроенной схемой stlink / v2, и она будет передавать 8 МГц на чип STM32F4 для тактовой частоты HSE.

Но моя плата делаетУ меня нет схемы, поэтому мне нужно использовать внешний модуль stlink / v2 для разработки моей платы.

Итак, мне нужно внести изменения ниже.

WAS: RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;

IS: RCC_OscInitStruct.HSEState = RCC_LSE_ON;

После изменения моя проблема будет решена.

И спасибо Хейн Вессельс за просмотр и помощь:).

0 голосов
/ 14 июня 2018

Хорошо, тогда это звучит как проблема с часами.

  • У вас есть осциллограф?Вместо проведения эхо-теста вы можете просто отправить известный байт из STM32.Я обычно отправляю 0xAA или 0x55.Затем вы можете измерить время UART вашего STM32 и убедиться, что оно правильное.
  • Иногда при более высоких тактовых частотах точность часов периферийного устройства уменьшается.Вы также можете попытаться увеличить частоту системных часов.

Мысль: Снова глядя на ваш код, я думаю, что, возможно, нашел проблему.В вашей конфигурации UART измените

uart_handler.Init.OverSampling = UART_OVERSAMPLING_8;

на

uart_handler.Init.OverSampling = UART_OVERSAMPLING_16;

Это заставит STM32 более тщательно смотреть на входящие байты, и может решить вашу проблему.В моем понимании 16x передискретизация является типичной конфигурацией, используемой даже при более низких скоростях UART.

...