关于STM32747双核串口DMA数据接收经验

最近在调试红旗某弹型号的惯导系统,主控芯片用得是STM32747双核,不得不说算力还是很给力,但是STM32串口接收数据时候遇到问题,如果波特率太高再使用中断接收的话会中断太快打断其他任务,所以一般使用串口dma空闲接收数据。但是按照之前STM32其他型号的写法跑不起来,原因是因为没有设置RAM缓存位置。这里和其他单核芯片有区别。配置如下,直接上干货。

系统时钟配置

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Supply configuration update enable
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  __HAL_RCC_SYSCFG_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 5;
  RCC_OscInitStruct.PLL.PLLN = 192;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

串口配置初始化

/* USER CODE BEGIN 0 */
__attribute__((section(".RAM_D3"))) struct Usart usart1,usart2,usart3,usart4,usart5,usart6,usart7;
struct UsartA usartA4,usartA5,usartA7;
/* USER CODE END 0 */

UART_HandleTypeDef huart4;
UART_HandleTypeDef huart5;
UART_HandleTypeDef huart7;
UART_HandleTypeDef huart3;
UART_HandleTypeDef huart6;
DMA_HandleTypeDef hdma_uart4_rx;
DMA_HandleTypeDef hdma_uart4_tx;
DMA_HandleTypeDef hdma_uart5_rx;
DMA_HandleTypeDef hdma_uart5_tx;
DMA_HandleTypeDef hdma_uart7_rx;
DMA_HandleTypeDef hdma_uart7_tx;
DMA_HandleTypeDef hdma_usart3_rx;
DMA_HandleTypeDef hdma_usart3_tx;
DMA_HandleTypeDef hdma_usart6_rx;
DMA_HandleTypeDef hdma_usart6_tx;

/* UART4 init function */
void MX_UART4_Init(void)
{

  /* USER CODE BEGIN UART4_Init 0 */

  /* USER CODE END UART4_Init 0 */

  /* USER CODE BEGIN UART4_Init 1 */

  /* USER CODE END UART4_Init 1 */
  huart4.Instance = UART4;
  huart4.Init.BaudRate = 614400;
  huart4.Init.WordLength = UART_WORDLENGTH_9B;
  huart4.Init.StopBits = UART_STOPBITS_1;
  huart4.Init.Parity = UART_PARITY_EVEN;
  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.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart4) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN UART4_Init 2 */

  /* USER CODE END UART4_Init 2 */

}

最关键的代码

/* USER CODE BEGIN 0 */
__attribute__((section(".RAM_D3"))) struct Usart usart1,usart2,usart3,usart4,usart5,usart6,usart7;

串口的其他配置

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(uartHandle->Instance==UART4)
  {
  /* USER CODE BEGIN UART4_MspInit 0 */

  /* USER CODE END UART4_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART4;
    PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    /* UART4 clock enable */
    __HAL_RCC_UART4_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**UART4 GPIO Configuration
    PB8     ------> UART4_RX
    PB9     ------> UART4_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* UART4 DMA Init */
    /* UART4_RX Init */
    hdma_uart4_rx.Instance = DMA1_Stream0;
    hdma_uart4_rx.Init.Request = DMA_REQUEST_UART4_RX;
    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_CIRCULAR;
    hdma_uart4_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_uart4_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_uart4_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_uart4_rx);

    /* UART4_TX Init */
    hdma_uart4_tx.Instance = DMA1_Stream1;
    hdma_uart4_tx.Init.Request = DMA_REQUEST_UART4_TX;
    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_LOW;
    hdma_uart4_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_uart4_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmatx,hdma_uart4_tx);

    /* UART4 interrupt Init */
    HAL_NVIC_SetPriority(UART4_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(UART4_IRQn);
  /* USER CODE BEGIN UART4_MspInit 1 */

  /* USER CODE END UART4_MspInit 1 */
  }
}

开dma接收

        HAL_UART_Receive_DMA(&huart4,usart4.RX_data,8);//开启DMA

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 对于STM32H755芯片的双核编程,首先需要了解该芯片的双核架构。STM32H755芯片包含两个核心:一个Cortex-M7核心和一个Cortex-M4核心。双核架构允许这两个核心同时运行不同的任务,并可以通过IPC(Inter-Processor Communication,处理器间通信)进行通信与同步。 编程双核芯片的一般步骤如下: 1. 确定双核编程的需求:首先,确定双核处理是为了提高性能还是为了实现功能分离。这有助于确定核心之间的任务分配和通信机制选择。 2. 配置和引导:在启动程序中配置双核处理器。这通常包括时钟配置、地址映射和中断向量表等。确保两个核心以正确的时钟和优先级启动。 3. 分配任务:确定每个核心的任务和功能。根据需求分配任务,以便获得良好的系统性能。可能需要将某些任务优先分配给一个核心,而其他任务分配给另一个核心。 4. 编写应用程序:使用适当的开发环境(如Keil或STM32CubeIDE)编写应用程序。可以为每个核心编写不同的应用程序,也可以使用共享库来实现共享功能。 5. IPC通信:在需要时使用IPC机制进行核心之间的通信和同步。IPC机制可以是共享内存、消息传递、互斥锁等。根据需求选择适当的IPC机制。 6. 编译和调试:编译应用程序并下载到双核芯片上进行调试。使用调试工具跟踪和调试每个核心的代码,确保程序的正确性和性能。 7. 验证和优化:测试和验证双核系统的性能和功能。根据实际需求进行性能优化,例如任务调度策略、时间片分配等。 在双核编程中,关键是充分利用两个核心的性能,并确保它们之间的通信和同步。适当的任务分配、IPC机制和优化可以实现更高效的双核编程。 ### 回答2: STM32H755芯片是一款双核处理器,可以同时运行两个独立的核心。下面是如何对STM32H755芯片双核编程的步骤: 1. 配置开发环境:首先,需要选择合适的集成开发环境(IDE)和编译器来进行开发。常用的IDE包括Keil MDK、IAR Embedded Workbench等,可以根据个人喜好和项目需求选择适合的开发环境。 2. 创建工程:在选择的IDE中,创建一个新的工程。在工程中,可以选择适合的配置文件和库文件,以支持双核编程。 3. 配置双核:在工程中,需要设置双核处理器的配置。可以选择合适的配置选项,例如选择双核开关、选择核间通信方式等。 4. 编写代码:根据项目需求,在IDE中编写代码。可以使用适合的编程语言,如C或者C++。编写代码时,需要根据具体需求来进行双核编程相关的设置,如任务创建、任务切换、核间通信等。 5. 编译和下载:完成代码编写后,使用IDE提供的编译器将代码编译成可执行文件。然后,将可执行文件下载到STM32H755芯片中。 6. 调试和测试:将芯片连接到开发板上,使用相应的调试器进行调试和测试。通过调试和测试,可以验证双核程序的正确性和性能,以及检查是否存在任何错误或异常情况。 需要注意的是,双核编程需要处理器的硬件支持,并且在设计和编程过程中需要考虑诸如任务间同步与通信、资源共享等各种问题。另外,双核编程虽然可以充分利用处理器的性能,但也增加了代码的复杂性和维护的困难度,需要仔细设计和测试。 ### 回答3: 对于STM32H755芯片的双核编程,主要包括以下几个方面: 1. 硬件配置:首先需要在芯片上配置正确的时钟和外设。可以使用STM32CubeMX软件进行配置,选择适当的外设和时钟源,并生成相应的代码初始化文件。 2. 编写启动代码:为每个核心编写启动代码。启动代码主要完成对应核心的堆栈和中断向量表的初始化,将控制权转交给应用程序入口点。 3. 系统初始化:编写系统初始化代码,包括对共享资源的初始化和配置。在双核场景下,需要处理两个核心之间的通信和同步问题。可以使用共享内存、信号量或者消息传递等机制来实现核心间的通信和同步。 4. 编写应用程序:根据需求编写应用程序代码,并根据双核情况进行适当的调度和切换。可以使用RTOS(实时操作系统)或者裸机编程来实现。 5. 中断处理:根据需要,编写中断处理程序。在双核编程中,需要注意双核之间的中断处理的优先级和抢占关系。 6. 调试和验证:完成代码编写后,进行调试和验证。可以使用调试器进行单步调试,观察程序的执行流程,并根据需要进行修正和优化。 总结来说,对STM32H755芯片的双核编程需要进行硬件配置、编写启动代码、系统初始化、编写应用程序、中断处理和调试验证等步骤。需要注意双核之间的通信和同步问题,以及中断处理的优先级和抢占关系。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值