После настройки моего проекта для пользовательской платы STM32F7, которая включает преобразователь FT2232H UART <-> USB, у меня возникло несколько проблем при отправке (и получении данных). Код, который я использую, в основном сгенерирован CubeMX и находится в конце поста.
Во-первых, я не могу заставить stm передавать данные со скоростью выше стандартной 115200, согласно даташитам, и FT2232H, и STM32F7 должны поддерживать скорость не менее 12 Мбод. Для FT2232H это работает, так как я отправляю некоторые символы со своего терминала (сторона USB) и получаю символы обратно, когда я замыкал контакты RX и TX на выходной стороне FT2232H.
Во-вторых, я не могу вызывать функцию sendUART() несколько раз подряд, почему DMA Fifo не используется для хранения данных, которые я хочу отправить?
Также как правильно отобразить все полученные данные, но использовать fifo, чтобы данные не терялись, если они не опрашиваются вовремя?
Может быть, это глупые вопросы, но я уже пытался найти решение здесь и в остальном Интернете, но не могу найти.
void MX_UART4_Init(void)
{
huart4.Instance = UART4;
huart4.Init.BaudRate = 115200;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspInit 0 */
/* USER CODE END UART4_MspInit 0 */
/* UART4 clock enable */
__HAL_RCC_UART4_CLK_ENABLE();
/**UART4 GPIO Configuration
PA0/WKUP ------> UART4_TX
PA1 ------> UART4_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* UART4 DMA Init */
/* UART4_TX Init */
hdma_uart4_tx.Instance = DMA1_Stream4;
hdma_uart4_tx.Init.Channel = DMA_CHANNEL_4;
hdma_uart4_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_uart4_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart4_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart4_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_uart4_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart4_tx.Init.Mode = DMA_NORMAL;
hdma_uart4_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_uart4_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_uart4_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_uart4_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_uart4_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
if (HAL_DMA_Init(&hdma_uart4_tx) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(uartHandle,hdmatx,hdma_uart4_tx);
/* UART4_RX Init */
hdma_uart4_rx.Instance = DMA1_Stream2;
hdma_uart4_rx.Init.Channel = DMA_CHANNEL_4;
hdma_uart4_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_uart4_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart4_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart4_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_uart4_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart4_rx.Init.Mode = DMA_NORMAL;
hdma_uart4_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_uart4_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_uart4_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_uart4_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_uart4_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
if (HAL_DMA_Init(&hdma_uart4_rx) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_uart4_rx);
/* USER CODE BEGIN UART4_MspInit 1 */
/* USER CODE END UART4_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspDeInit 0 */
/* USER CODE END UART4_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_UART4_CLK_DISABLE();
/**UART4 GPIO Configuration
PA0/WKUP ------> UART4_TX
PA1 ------> UART4_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);
/* UART4 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmatx);
HAL_DMA_DeInit(uartHandle->hdmarx);
/* USER CODE BEGIN UART4_MspDeInit 1 */
/* USER CODE END UART4_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
void sendUART(char msg[]){
//HAL_UART_Transmit(&huart4,(uint8_t *) msg, strlen(msg),10000);
HAL_UART_Transmit_DMA(&huart4,(uint8_t *) msg, strlen(msg));
}
void echo(){
if(HAL_UART_Receive_DMA(&huart4, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK){}
else if(HAL_UART_Transmit_DMA(&huart4, (uint8_t*)aRxBuffer, RXBUFFERSIZE)!= HAL_OK){
}
}
Во-первых, я не могу заставить stm передавать данные со скоростью выше стандартной 115200, согласно даташитам, и FT2232H, и STM32F7 должны поддерживать скорость не менее 12 Мбод.
Аппаратно поддерживает скорость до 27 Мбит (ну вы не сказали номер детали, я смотрю даташит на F756), но по словам , stm32f7xx_hal_uart.h
HAL не примет скорость выше 9М
#define IS_UART_BAUDRATE(BAUDRATE) ((BAUDRATE) < 9000001)
Более того, это зависит от тактовой частоты системы, в конфигурации по умолчанию, когда вы не трогаете вкладку Clock Configuration в STM32CubeMX, все работает на внутренних тактовых частотах HSI 16 МГц. Это означает не более 1 Мбит при использовании UART_OVERSAMPLING_16
или вдвое больше, если вы переключитесь на UART_OVERSAMPLING_8
(но тогда вы потеряете обнаружение шума).
Во-вторых, я не могу вызывать функцию sendUART() несколько раз подряд, почему DMA Fifo не используется для хранения данных, которые я хочу отправить?
Хотя существует 16-байтовый DMA FIFO, он недоступен программному обеспечению. Невозможно просто добавить дополнительные данные к текущей передаче DMA. HAL ничего не делает, но запускает передачу DMA с адреса буфера, предоставленного вызывающей стороной.
Вы должны дождаться завершения передачи или приостановить DMA и все равно ждать, пока FIFO не опустеет. Конечно, вы можете выделить буфер самостоятельно, добавлять данные по мере их поступления и перезапускать DMA всякий раз, когда он завершается и в буфере появляются новые данные.
Также как правильно отобразить все полученные данные, но использовать fifo, чтобы данные не терялись, если они не опрашиваются вовремя?
Мне кажется, что вы не можете иметь одновременно DMA и прерывания для каждого полученного символа. По крайней мере, ISR
значение регистра состояния будет бесполезным, и обработчик прерывания не сможет решить, что делать. Его чтение может даже помешать передаче DMA. Следовательно, вы должны выбрать один.
Используя DMA для помещения данных в буфер (или два), вы можете затем регулярно опрашивать счетчик передачи в цикле простоя или прерывании таймера. Немедленного ответа не будет, но, возможно, это вообще не имеет значения, потому что интерфейс USB также будет иметь некоторую задержку.
Джейн Доу
последовал за Моникой в Codidact