STM32F4 串口+DMA收发+注释·干货

分享一些项目上所运用串口收发代码

#define USART2_TX_MAX_SIZE 1024
#define USART2_RX_MAX_SIZE 1024
#define USART2_RX_MAX_TIME 5
#define USART2_TX_PIN GPIOD_USART2_TX  			/* GPIOD */
#define USART2_RX_PIN GPIOD_USART2_RX  			/* GPIOD */

#define DIRVER_USART2_INIT true                 /* 普通串口配置 */
#define DIRVER_USART2_DMA_CONFIG true           /* DMA串口配置 */

unsigned char  usart2_tx_buffer[USART2_TX_MAX_SIZE];
unsigned char  usart2_rx_buffer[USART2_RX_MAX_SIZE];
unsigned short usart2_rx_size = 0;
unsigned char  usart2_rx_time = 0;
bool           usart2_rx_flag = false;


static void Usart2_GPIO_Init()
{
  GPIO_InitTypeDef GPIO_InitStructure;

  GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2);

  GPIO_InitStructure.GPIO_Pin   = USART2_TX_PIN;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin   = USART2_RX_PIN;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
}

void Usart2_Init(uint32_t baudrate, uint16_t parity, uint16_t stopbits, uint16_t wordlength)
{
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef  NVIC_InitStructure;

  Usart2_GPIO_Init();

  USART_InitStructure.USART_BaudRate            = baudrate;
  USART_InitStructure.USART_Parity              = parity;
  USART_InitStructure.USART_StopBits            = stopbits;
  USART_InitStructure.USART_WordLength          = wordlength;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;

  USART_Init(USART2, &USART_InitStructure);

#if DIRVER_USART2_DMA_CONFIG == true
  USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
#elif DIRVER_USART2_DMA_CONFIG == false
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
#endif

  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  /* 注释的情况下,该中断采用默认配置的优先级 */
  //  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
  //  NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  USART_Cmd(USART2, ENABLE);
}

static void Usart2_DMA_TX_Init()
{
  DMA_InitTypeDef  DMA_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  DMA_DeInit(DMA1_Stream6);
  while (DMA_GetCmdStatus(DMA1_Stream6) != DISABLE)
    ;
  /* config usart2_tx_dma */
  DMA_InitStructure.DMA_Channel            = DMA_Channel_4;               /* 当前所用外设所处通道 */
  DMA_InitStructure.DMA_DIR                = DMA_DIR_MemoryToPeripheral;  /* 传输方向,当前为内存->外设 */
  DMA_InitStructure.DMA_BufferSize         = USART2_TX_MAX_SIZE;          /* 数据长度 */
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);     /* 外设目标地址 */
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; /* 外设传输带宽,当前为字节 */
  DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;   /* 当前地址是否自增,当前为否 */
  DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;  /* 传输模式,单次或突发模式,当前为单次,突发模式需要FIFO支持缓冲区 */
  DMA_InitStructure.DMA_Memory0BaseAddr    = (uint32_t)usart2_tx_buffer;  /* 源内存地址 */
  DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;     /* 内存传输带宽,当前为字节 */
  DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;        /* 当前地址是否自增,当前为是 */
  DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;      /* 传输模式,单次或突发模式,当前为单次,突发模式需要FIFO支持缓冲区 */
  DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;        /* FIFO模式是否使能,当前为否 */
  DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_HalfFull;  /* FIFO阈值 */
  DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;             /* DMA模式 */
  DMA_InitStructure.DMA_Priority           = DMA_Priority_High;           /* 中断优先级 */
  DMA_Init(DMA1_Stream6, &DMA_InitStructure);

  DMA_ITConfig(DMA1_Stream6, DMA_IT_TC, ENABLE);

  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;
  /* 注释的情况下,该中断采用默认配置的优先级 */
  //  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
  //  NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);

  DMA_Cmd(DMA1_Stream6, DISABLE);
}

static void Usart2_DMA_RX_Init()
{
  DMA_InitTypeDef DMA_InitStructure;

  DMA_DeInit(DMA1_Stream5);
  while (DMA_GetCmdStatus(DMA1_Stream5) != DISABLE)
    ;
  /* config usart2_rx_dma */
  DMA_InitStructure.DMA_Channel            = DMA_Channel_4;               /* 当前所用外设所处通道 */
  DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory;  /* 传输方向,当前为外设->内存 */
  DMA_InitStructure.DMA_BufferSize         = USART2_RX_MAX_SIZE;          /* 数据长度 */
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);     /* 外设源地址 */
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; /* 外设传输带宽,当前为字节 */
  DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;   /* 当前地址是否自增,当前为否 */
  DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;  /* 传输模式,单次或突发模式,当前为单次,突发模式需要FIFO支持缓冲区 */
  DMA_InitStructure.DMA_Memory0BaseAddr    = (uint32_t)usart2_rx_buffer;  /* 目标内存地址 */
  DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;     /* 内存传输带宽,当前为字节 */
  DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;        /* 当前地址是否自增,当前为是 */
  DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;      /* 传输模式,单次或突发模式,当前为单次,突发模式需要FIFO支持缓冲区 */
  DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;        /* FIFO模式是否使能,当前为否 */
  DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_HalfFull;  /* FIFO阈值 */
  DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;           /* DMA模式 */
  DMA_InitStructure.DMA_Priority           = DMA_Priority_High;           /* 中断优先级 */
  DMA_Init(DMA1_Stream5, &DMA_InitStructure);

  USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);

  DMA_Cmd(DMA1_Stream5, ENABLE);
}

void Usart2_DMA_Init(uint32_t baudrate, uint16_t parity, uint16_t stopbits, uint16_t wordlength)
{
  Usart2_DMA_TX_Init();

  Usart2_DMA_RX_Init();

  Usart2_Init(baudrate, parity, stopbits, wordlength);
}

/* USART2 Rx Config */
static void Usart2_Rx_Config()
{
  usart2_rx_time = USART2_RX_MAX_TIME;
  usart2_rx_flag = true;
}

#if (DIRVER_USART2_DMA_CONFIG == false)
/* USART2 Normal Rx Config */
static void Usart2_Normal_Rx_Config()
{
  if (usart2_rx_size >= USART2_RX_MAX_SIZE)
  {
    usart2_rx_size = USART2_RX_MAX_SIZE;
  }
  usart2_rx_buffer[usart2_rx_size++] = USART_ReceiveData(USART2);
  Usart2_Rx_Config();
}

/* usart2 normal send func */
void Usart2_Send_Data(uint8_t *data, uint16_t length)
{
  for (uint16_t i = 0; i < length; i++)
  {
    USART_SendData(USART2, *(data + i));
    while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)
      ;
  }
}
#elif (DIRVER_USART2_DMA_CONFIG == true)
/* USART2 DMA Rx Config */
static void Usart2_DMA_Rx_Config()
{
  DMA_Cmd(DMA1_Stream5, DISABLE);
  usart2_rx_size = (USART2_RX_MAX_SIZE - DMA_GetCurrDataCounter(DMA1_Stream5));
  DMA_Cmd(DMA1_Stream5, ENABLE);
  Usart2_Rx_Config();
}

/* usart2 DMA send func */
void Usart2_DMA_Send_Data(uint8_t *data, uint16_t length)
{
  for (uint16_t i = 0; i < length; i++)
  {
    usart2_tx_buffer[i] = *(data + i);
  }

  DMA_SetCurrDataCounter(DMA1_Stream6, length);
  DMA_Cmd(DMA1_Stream6, ENABLE);
}
#endif

void USART2_IRQHandler()
{
  if (USART_GetITStatus(USART2, USART_IT_RXNE))
  {
    USART_ClearITPendingBit(USART2, USART_IT_RXNE);
#if DIRVER_USART2_DMA_CONFIG == false
    Usart2_Normal_Rx_Config();
#endif
  }

  if (USART_GetITStatus(USART2, USART_IT_TXE))
  {
    USART_ClearITPendingBit(USART2, USART_IT_TXE);
  }

  if (USART_GetITStatus(USART2, USART_IT_IDLE))
  {
    /* 清空IDLE标识位的时序 */
    (void)USART2->SR;
    (void)USART2->DR;
		
#if DIRVER_USART2_DMA_CONFIG == true
    Usart2_DMA_Rx_Config();
#endif
  }
}

void DMA1_Stream6_IRQHandler(void)
{
  if (DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6) != RESET)
  {
    /* 清除标志位 */
    DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);
    /* 关闭DMA */
    DMA_Cmd(DMA1_Stream6, DISABLE);
  }
}

/* 该函数运行时基为1ms */
void Usart2_Rx_task()
{
  if ((usart2_rx_flag == true) || (usart2_rx_time > 0))
  {
    usart2_rx_time--;
    usart2_rx_flag = false;
    if (usart2_rx_time == 0)
    {
      /* add you app */

			
      memset(usart2_rx_buffer, 0, usart2_rx_size);
      usart2_rx_size = 0;
    }
  }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值