搜索
查看: 12447|回复: 7

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

[复制链接]

该用户从未签到

50

主题

243

帖子

0

蝴蝶豆

金牌会员

最后登录
2021-3-6
发表于 2015-6-25 14:07:14 | 显示全部楼层 |阅读模式
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);
  }
}

回复

使用道具 举报

该用户从未签到

307

主题

3432

帖子

0

蝴蝶豆

论坛元老

最后登录
2020-7-17
发表于 2015-6-25 14:25:56 | 显示全部楼层
谢谢,要是有代码注释或者文字说明更好啦
回复 支持 反对

使用道具 举报

该用户从未签到

53

主题

3438

帖子

61

蝴蝶豆

论坛元老

最后登录
2024-3-19
发表于 2015-6-25 17:05:13 | 显示全部楼层
学习一下
回复

使用道具 举报

该用户从未签到

50

主题

243

帖子

0

蝴蝶豆

金牌会员

最后登录
2021-3-6
 楼主| 发表于 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库的宏定义拷贝过来使用,以提高标准外设驱动库的效率,
又保证标准外设驱动库的灵活性。



回复 支持 反对

使用道具 举报

该用户从未签到

47

主题

3456

帖子

30

蝴蝶豆

版主

最后登录
2022-12-25
发表于 2015-6-25 20:38:16 | 显示全部楼层
多谢分享。。。支持下。。
回复 支持 反对

使用道具 举报

该用户从未签到

4

主题

237

帖子

0

蝴蝶豆

高级会员

最后登录
2019-1-10
发表于 2015-7-3 16:57:05 | 显示全部楼层
多谢分享。。。支持下。。
回复 支持 反对

使用道具 举报

该用户从未签到

9

主题

40

帖子

0

蝴蝶豆

初级会员

最后登录
2019-9-23
发表于 2016-11-10 16:43:14 | 显示全部楼层
回复

使用道具 举报

该用户从未签到

4

主题

488

帖子

0

蝴蝶豆

金牌会员

最后登录
2022-4-16
发表于 2016-11-11 08:13:25 | 显示全部楼层
学习一下
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2024-5-8 17:21 , Processed in 1.179161 second(s), 40 queries .

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表