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

【原创】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
谢谢,要是有代码注释或者文字说明更好啦
数码小叶 回答时间: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
学习一下

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

官网相关资源

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