你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【原创】STM32F103的USART2配置代码, DMA方式发送!

[复制链接]
wjandsq 发布时间:2015-6-25 14:07
STM32电机培训online,大佬带你玩电机


#include "stm32f10x.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_dma.h"

uint8_t HEX_CODE[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
uint8_t USART2_DMA_TX_Buf[1024];
uint8_t Flag_USART2_DMA_TX_Finished = 1;
uint8_t Flag_USART2_Send = 0;

/**
  * Function Name  : USART2_Config
  * Description    : None
  * Input          : None
  * Output         : None
  * Return         : None
  */
void USART2_Config(void) {
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  DMA_InitTypeDef DMA_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  /* config USART2 clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

  /* *********************USART2 GPIO config **********************/
  /* Configure USART1 Tx (PA.02) as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);   
  /* Configure USART2 Rx (PA.03) as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* USART2 mode config 115200 8-N-1*/
  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No ;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USART2, &USART_InitStructure);
  USART_Cmd(USART2, ENABLE);


  USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
  /* Enable USART2 DMA TX request */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  DMA_DeInit(DMA1_Channel7);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_DMA_TX_Buf;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_BufferSize = 0;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel7, &DMA_InitStructure);
  DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  /* Enable USART2 DMA TX Finish Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  /* Enable USART2 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_Init(&NVIC_InitStructure);
}
/**
  * Function Name  : USART2_Data_Load
  * Description    : None
  * Input          : None
  * Output         : None
  * Return         : None
  */
void USART2_Data_Load(uint16_t temp1, uint16_t temp2, uint8_t temp3){
  USART2_DMA_TX_Buf[0] = HEX_CODE[temp1 >> 4];
  USART2_DMA_TX_Buf[1] = HEX_CODE[temp1 & 0x0F];
  USART2_DMA_TX_Buf[2] = HEX_CODE[temp2 >> 4];
  USART2_DMA_TX_Buf[3] = HEX_CODE[temp2 & 0x0F];
  USART2_DMA_TX_Buf[4] = 0x20;
  USART2_DMA_TX_Buf[5] = HEX_CODE[temp3];
  USART2_DMA_TX_Buf[6] = 0x0D;
  USART2_DMA_TX_Buf[7] = 0x0A;
  Flag_USART2_Send = 1;
}
/**
  * Function Name  : USART2_Data_Send
  * Description    : None
  * Input          : None
  * Output         : None
  * Return         : None
  */
void USART2_Data_Send(uint16_t len) {
  if(Flag_USART2_Send){
    if(Flag_USART2_DMA_TX_Finished == 1){
      Flag_USART2_DMA_TX_Finished = 0;
      DMA1_Channel7->CMAR  = (uint32_t)&USART2_DMA_TX_Buf[0];
      DMA1_Channel7->CNDTR = 8; // len
      DMA_Cmd(DMA1_Channel7, ENABLE);
      Flag_USART2_Send = 0;
    }
  }
}
/**
  * Function Name  : USART2_IRQHandler
  * Description    : This function handles USART2 global interrupt request.
  * Input          : None
  * Output         : None
  * Return         : None
  */
void USART2_IRQHandler(void) {
  if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) {
    (void)USART_ReceiveData(USART2);
  }
  if (USART_GetITStatus(USART2, USART_IT_TC) != RESET) {
    /* Disable the USART2 Transmit Complete interrupt */
    USART_ITConfig(USART2, USART_IT_TC, DISABLE);
    Flag_USART2_DMA_TX_Finished = 1;
  }     
  /* If overrun condition occurs, clear the ORE flag a.nd recover communication */   
  if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) != RESET) {
    (void)USART_ReceiveData(USART2);
  }
}
/**
  * Function Name  : DMA1_Channel7_IRQHandler
  * Description    : This function handles DMA1 Channel 7 interrupt request.
  * Input          : None
  * Output         : None
  * Return         : None
  */
void DMA1_Channel7_IRQHandler(void)
{
  if(DMA_GetITStatus(DMA1_IT_TC7)) {
    /* USART2 DMA 传输完成 */
    DMA_ClearITPendingBit(DMA1_IT_TC7);
    DMA_Cmd(DMA1_Channel7, DISABLE);
    /* Enable USART2 Transmit complete interrupt */
    USART_ITConfig(USART2, USART_IT_TC, ENABLE);
  }
}

收藏 4 评论7 发布时间:2015-6-25 14:07

举报

7个回答
沐紫 回答时间:2015-6-25 14:25:56
谢谢,要是有代码注释或者文字说明更好啦
wyxy163@126.com 回答时间:2015-6-25 17:05:13
提示: 作者被禁止或删除 内容自动屏蔽
wjandsq 回答时间:2015-6-25 20:37:02
本帖最后由 wjandsq 于 2015-6-25 20:45 编辑

所谓STM32F103串口数据的DMA发送,其本质流程如下:
1. 要发送的数据放在USART2_DMA_TX_Buf缓冲。
2. STM32串口DMA发送和DSP相比的优势。
   启动DMA传输后,USART2_DMA_TX_Buf缓冲中的数据通过DMA1_Channel7通道,
   自动传输到USART2->DR寄存器,这个工作不需要CPU干预,可以极大的节省CPU的资源。
   和DSP的FIFO相比,这优势很大,因为DSP的FIFO只有16字节,这意味着DSP的串口通过
   FIFO发送数据时,如果FIFO缓冲为空,可以迅速填入16个字节,然后去处理其它的事务。
   而STM32的DMA发送则没有此种限制。更具体的说,如果DSP发送的数据超过16字节,
   则必须等待前16个字节数据发送完毕,然后再继续发送后续的数据,需要第二次甚至
   第N次处理。而STM32启动一次DMA就搞定(DMA最大传输65535个数据)。
3. 发送结束的一些事务处理
   DMA传输完毕,数据全部通过DMA1_Channel7通道依次传入USART2-DR,这里开启了
   DMA传输完毕中断,进这个中断时,USART2-DR寄存器是最后一个要发送的数据,
   此时打开USART2发送完毕中断,进入USART2发送完毕中断后,可以设定标识,
   也可以操作GPIO, 进行RS485的换向动作。

最新的STM32F103的HAL库,几乎所有的通信,都可以启用DMA,HAL库函数抽象层次过高,灵活性不够,
但比较适合使用操作系统的场合。可以把HAL库的宏定义拷贝过来使用,以提高标准外设驱动库的效率,
又保证标准外设驱动库的灵活性。



Paderboy 回答时间:2015-6-25 20:38:16
多谢分享。。。支持下。。
HenryChen 回答时间:2015-7-3 16:57:05
多谢分享。。。支持下。。
fanyao-367090 回答时间:2016-11-10 16:43:14
zengyi703-16313 回答时间:2016-11-11 08:13:25
学习一下

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版