mokongking

usart+dma接收不定长数据,dma溢出的问题

#include "usart1.h"
#include "main.h"
#include "stdio.h"
#include "string.h"
#include "stdbool.h"
#include "stdlib.h"
#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
   set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

DMA_HandleTypeDef hdma_uart1_rx;
UART_HandleTypeDef huart1;

uint8_t rx_buffer[1024] = {0};
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(huart->Instance == USART1)
    {
        USARTx_RX_GPIO_CLK_ENABLE();
        USARTx_TX_GPIO_CLK_ENABLE();
        __HAL_RCC_AFIO_CLK_ENABLE();//重定向时钟//需要重映射的话要开启重映射时钟,不重映射开启这个时钟也没有影响
        //首先开启引脚的时钟,开启引脚的复用模式,关于引脚被复用成什么功能是与接下来开启哪个外设的时钟有关系,
        //比如开启串口的时钟就是串口的功能,开启adc的时钟就是adc的功能
        USARTx_CLK_ENABLE();
        //时钟开始后开始配置串口发送引脚
        
        GPIO_InitStruct.Pin = USARTx_TX_PIN;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        //配置引脚这些配置放到初始化函数中
        HAL_GPIO_Init(USARTx_TX_GPIO_PORT,&GPIO_InitStruct);
        //配置接受引脚
        GPIO_InitStruct.Pin = USARTx_RX_PIN;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        
        HAL_GPIO_Init(USARTx_RX_GPIO_PORT,&GPIO_InitStruct);
        //使用中断开启中断
        __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
        HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
    
    }
}
void usart1_dma1_congfig()
{
       __HAL_RCC_DMA1_CLK_ENABLE();
            hdma_uart1_rx.Instance = DMA1_Channel5;
            hdma_uart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
            hdma_uart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
            hdma_uart1_rx.Init.MemInc = DMA_MINC_ENABLE;
            hdma_uart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
            hdma_uart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
            hdma_uart1_rx.Init.Mode = DMA_NORMAL; // 循环模式(持续接收)
            hdma_uart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
            HAL_DMA_Init(&hdma_uart1_rx);
        
            __HAL_LINKDMA(&huart1, hdmarx, hdma_uart1_rx);
    
}
void uart_open()
{
//    HAL_UART_MspInit(&huart1);
    uint8_t ch;
    huart1.Instance = USARTx;
    huart1.Instance        = USARTx;
  huart1.Init.BaudRate   = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits   = UART_STOPBITS_1;
  huart1.Init.Parity     = UART_PARITY_NONE;
  huart1.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
  huart1.Init.Mode       = UART_MODE_TX_RX;
    huart1.Init.OverSampling= UART_OVERSAMPLING_16;//16倍过采样是保证每次都取到中间值去掉前后干扰如0~16取值是9
    if(HAL_UART_Init(&huart1) != HAL_OK)
    {
     Error_Handler();
  }
    usart1_dma1_congfig();
    HAL_UART_Receive_DMA(&huart1, rx_buffer, sizeof(rx_buffer));
}
void USART1_IRQHandler()
{
    if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE))
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);
            huart1.Instance->DR;
            huart1.Instance->SR;
        uint32_t remaining = __HAL_DMA_GET_COUNTER(&hdma_uart1_rx);
        uint32_t received_len = sizeof(rx_buffer)-remaining;
         HAL_UART_Transmit(&huart1, rx_buffer,received_len, 0xFFFF);
        HAL_UART_DMAStop(&huart1);//处理完重置//接受完成后一定要加停止,让dma重新从0开始传输,不然会dma通道会溢出,停止之后再重新开启dma传输
        memset(rx_buffer,0,sizeof(rx_buffer));
    }
    HAL_UART_Receive_DMA(&huart1, rx_buffer, sizeof(rx_buffer));
}

int fputc(int ch, FILE *f)
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART2 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

  return ch;
}

 

posted on 2025-03-26 15:15  虎啸岳林  阅读(123)  评论(0)    收藏  举报

导航