STM32F103 实例应用(11)——DMA接收不定长串口数据

   日期:2021-02-21     浏览:110    评论:0    
核心提示:一、DMA 简介DMA(Direct Memory Access)—直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候,CPU 可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。DMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道,DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中.

一、DMA 简介

DMA(Direct Memory Access)—直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候,CPU 可以干其他的事情,好像是多线程一样。

数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH

DMA 控制器包含了 DMA1DMA2,其中 DMA1 有 7 个通道,DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。

二、DMA 功能框图

DMA 控制器独立于内核,属于一个单独的外设,结构比较简单,从编程的角度来看,我们只需掌握功能框图中的三部分内容即可,具体见下图:

  1. ①DMA 请求

如果外设要想通过 DMA 来传输数据,必须先给 DMA 控制器发送 DMA 请求,DMA收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且 DMA 控制器收到应答信号之后,就会启动 DMA 的传输,直到传输完毕。
DMA 有 DMA1 和 DMA2 两个控制器,DMA1 有 7 个通道,DMA2 有 5 个通道,不同的 DMA 控制器的通道对应着不同的外设请求,这决定了我们在软件编程上该怎么设置,具体见 DMA 请求映像表。

  1. ②通道
    DMA 具有 12 个独立可编程的通道,其中 DMA1 有 7 个通道,DMA2 有 5 个通道,每个通道对应不同的外设的 DMA 请求。虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个,不能同时接收多个。

  2. ③仲裁器
    当发生多个 DMA 通道请求时,就意味着有先后响应处理的顺序问题,这个就由仲裁器也管理。仲裁器管理 DMA 通道请求分为两个阶段。第一阶段属于软件阶段,可以在DMA_CCRx 寄存器中设置,有 4 个等级:非常高、高、中和低四个优先级。第二阶段属于硬件阶段,如果两个或以上的 DMA 通道请求设置的优先级一样,则他们优先级取决于通 道编号,编号越低优先权越高,比如通道 0 高于通道 1。在大容量产品和互联型产品中,
    DMA1 控制器拥有高于 DMA2 控制器的优先级。

三、设计实例

本示例使用串口1打印并接收电脑端发来的指令,串口3作为与4G通信的渠道。
bsp_usart.h


#ifndef __USART_H
#define __USART_H


#include "stm32f10x.h"
#include <stdio.h>

	

	
// 串口1-USART1
#define DEBUG_USARTx USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200

// USART GPIO 引脚宏定义
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
    
#define DEBUG_USART_TX_GPIO_PORT GPIOA 
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10

#define DEBUG_USART_IRQ USART1_IRQn
#define DEBUG_USART_IRQHandler USART1_IRQHandler


// 串口2-USART2
//#define DEBUG_USARTx USART2
//#define DEBUG_USART_CLK RCC_APB1Periph_USART2
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200

 USART GPIO 引脚宏定义
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
// 
//#define DEBUG_USART_TX_GPIO_PORT GPIOA 
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_2
//#define DEBUG_USART_RX_GPIO_PORT GPIOA
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_3

//#define DEBUG_USART_IRQ USART2_IRQn
//#define DEBUG_USART_IRQHandler USART2_IRQHandler

// 串口3-USART3
#define LTE_USARTx USART3
#define LTE_USART_CLK RCC_APB1Periph_USART3
#define LTE_USART_APBxClkCmd RCC_APB1PeriphClockCmd
#define LTE_USART_BAUDRATE 115200

// USART GPIO 引脚宏定义
#define LTE_USART_GPIO_CLK (RCC_APB2Periph_GPIOB)
#define LTE_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
    
#define LTE_USART_TX_GPIO_PORT GPIOB 
#define LTE_USART_TX_GPIO_PIN GPIO_Pin_10
#define LTE_USART_RX_GPIO_PORT GPIOB
#define LTE_USART_RX_GPIO_PIN GPIO_Pin_11

#define LTE_USART_IRQ USART3_IRQn
#define LTE_USART_IRQHandler USART3_IRQHandler

// 串口4-UART4
//#define DEBUG_USARTx UART4
//#define DEBUG_USART_CLK RCC_APB1Periph_UART4
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200

 USART GPIO 引脚宏定义
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
// 
//#define DEBUG_USART_TX_GPIO_PORT GPIOC 
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10
//#define DEBUG_USART_RX_GPIO_PORT GPIOC
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11

//#define DEBUG_USART_IRQ UART4_IRQn
//#define DEBUG_USART_IRQHandler UART4_IRQHandler


// 串口5-UART5
//#define DEBUG_USARTx UART5
//#define DEBUG_USART_CLK RCC_APB1Periph_UART5
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200

 USART GPIO 引脚宏定义
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
// 
//#define DEBUG_USART_TX_GPIO_PORT GPIOC 
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_12
//#define DEBUG_USART_RX_GPIO_PORT GPIOD
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_2

//#define DEBUG_USART_IRQ UART5_IRQn
//#define DEBUG_USART_IRQHandler UART5_IRQHandler


void USART_Config(void);
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch);
void Usart_SendString( USART_TypeDef * pUSARTx, char *str);
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch);

#endif 

bsp_usart.c




#include "bsp_usart.h"
#include "bsp_dma.h"
#include "stm32f10x.h"

static void NVIC_Configuration(void);



void USART_Config(void)
{ 
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	// 打开串口GPIO的时钟
	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
	LTE_USART_GPIO_APBxClkCmd(LTE_USART_GPIO_CLK, ENABLE);
	
	// 打开串口外设的时钟
	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
	LTE_USART_APBxClkCmd(LTE_USART_CLK, ENABLE);

		
	// 将USART Tx的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

	// 将USART Rx的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
	
	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
	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(DEBUG_USARTx, &USART_InitStructure);
	
					
	GPIO_InitStructure.GPIO_Pin = LTE_USART_TX_GPIO_PIN;	         
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_Init(LTE_USART_TX_GPIO_PORT, &GPIO_InitStructure);		   
	
	GPIO_InitStructure.GPIO_Pin = LTE_USART_RX_GPIO_PIN;	        
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
	GPIO_Init(LTE_USART_RX_GPIO_PORT, &GPIO_InitStructure);
	
	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//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(LTE_USARTx, &USART_InitStructure); 
  
	
	// 串口中断优先级配置
	NVIC_Configuration();
	
	// 使能串口接收中断
	USART_ITConfig(DEBUG_USARTx, USART_IT_IDLE, ENABLE);	
	USART_ITConfig(LTE_USARTx, USART_IT_IDLE, ENABLE);
	
	// 使能串口
	USART_Cmd(DEBUG_USARTx, ENABLE);	   
	USART_Cmd(LTE_USARTx, ENABLE); 
	
	USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  //使能串口1的DMA发送 
    USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);  //使能串口1的DMA接收 
	
	USART_DMACmd(USART3,USART_DMAReq_Tx,ENABLE);  //使能串口1的DMA发送 
    USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE);  //使能串口1的DMA接收 

}


void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{ 
	
	USART_SendData(pUSARTx,ch);
		
	
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}


void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
{ 
  uint8_t i;
	
	for(i=0; i<num; i++)
  { 
	    
	    Usart_SendByte(pUSARTx,array[i]);	
  
  }
	
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}


void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{ 
	unsigned int k=0;
  do 
  { 
      Usart_SendByte( pUSARTx, *(str + k) );
      k++;
  } while(*(str + k)!='\0');
  
  
  while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
  { }
}


void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{ 
	uint8_t temp_h, temp_l;
	
	
	temp_h = (ch&0xFF00)>>8;
	
	temp_l = ch&0xFF;
	
	
	USART_SendData(pUSARTx,temp_h);	
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
	
	
	USART_SendData(pUSARTx,temp_l);	
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}


int fputc(int ch, FILE *f)
{ 
		
		USART_SendData(DEBUG_USARTx, (uint8_t) ch);
		
		
		while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);		
	
		return (ch);
}


int fgetc(FILE *f)
{ 
		
		while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(DEBUG_USARTx);
}


void USART1_IRQHandler(void)  
{   
    uint16_t data;  
    if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)  
    {   
        DMA_Cmd(DMA1_Channel5, DISABLE); //关闭DMA,防止处理其间有数据 
  
        data = USART1->SR;  
        data = USART1->DR;  
          
        g_uart1ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5);  
        if(g_uart1ReceiveSize !=0)  
        {   
           // OSSemPost(DMAReceiveSize_Sem); 
			printf("shoudao1:%s", g_uart1ReceiveBuff);
        }  
        DMA_ClearFlag(DMA1_FLAG_TC5 | DMA1_FLAG_TE5 | DMA1_FLAG_HT5);//清除DMA2_Steam7传输完成标志 
        DMA_SetCurrDataCounter(DMA1_Channel5, RECEIVE_BUF_SIZE);  
        DMA_Cmd(DMA1_Channel5, ENABLE);     //打开DMA, 
  
    }  
} 

 
void USART3_IRQHandler(void)  
{   
    uint16_t data;  
    if(USART_GetITStatus(USART3,USART_IT_IDLE) != RESET)  
    {   
        DMA_Cmd(DMA1_Channel3, DISABLE); //关闭DMA,防止处理其间有数据 
  
        data = USART3->SR;  
        data = USART3->DR;  
          
        g_uart3ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel3);  
        if(g_uart3ReceiveSize !=0)  
        {   
           // OSSemPost(DMAReceiveSize_Sem); 
			printf("shoudao3:%s", g_uart3ReceiveBuff);
        }  
        DMA_ClearFlag(DMA1_FLAG_TC3 | DMA1_FLAG_TE3 | DMA1_FLAG_HT3);//清除DMA2_Steam7传输完成标志 
        DMA_SetCurrDataCounter(DMA1_Channel3, RECEIVE_BUF_SIZE);  
        DMA_Cmd(DMA1_Channel3, ENABLE);     //打开DMA, 
  
    }  
}



static void NVIC_Configuration(void)
{ 
	NVIC_InitTypeDef NVIC_InitStructure;
  
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
	
	
	NVIC_InitStructure.NVIC_IRQChannel = LTE_USART_IRQ;
	
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	
	NVIC_Init(&NVIC_InitStructure);
	
	
	NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
}

bsp_dma.h


#ifndef __DMA_H
#define __DMA_H 


#include "stm32f10x.h"

						    					    
#define RECEIVE_BUF_SIZE 255
#define SEND_BUF_SIZE 255


extern uint8_t g_uart1ReceiveBuff[RECEIVE_BUF_SIZE];   			//接收缓冲 
extern uint8_t g_uart1SendBuff[SEND_BUF_SIZE];    				//发送数据缓冲区 
extern uint16_t g_uart1ReceiveSize;  
  
extern uint8_t  g_uart3ReceiveBuff[RECEIVE_BUF_SIZE];   		//接收缓冲 
extern uint8_t  g_uart3SendBuff[SEND_BUF_SIZE];    				//发送数据缓冲区 
extern uint16_t g_uart3ReceiveSize; 
 

void DMA_Config(void);
void DmaSendDataProc(DMA_Channel_TypeDef *DMA_Streamx,uint16_t ndtr);
void Uart1DmaSendByte(uint8_t nSendInfo);
void Uart1DmaSendString(uint8_t* pSendInfo, uint16_t nSendCount);
void Uart3DmaSendByte(uint8_t nSendInfo);
void Uart3DmaSendString(uint8_t* pSendInfo, uint16_t nSendCount);

#endif 

bsp_dma.c




#include "bsp_dma.h"
#include <stdio.h>

static void NVIC_Configuration(void);


uint8_t  g_uart1ReceiveBuff[RECEIVE_BUF_SIZE];   //接收缓冲 
uint8_t  g_uart1SendBuff[SEND_BUF_SIZE];    //发送数据缓冲区 
uint16_t g_uart1ReceiveSize = 0;  
  
uint8_t  g_uart3ReceiveBuff[RECEIVE_BUF_SIZE];   //接收缓冲 
uint8_t  g_uart3SendBuff[SEND_BUF_SIZE];    //发送数据缓冲区 
uint16_t g_uart3ReceiveSize = 0;  





void DMA_Config(void)
{ 
	DMA_InitTypeDef  DMA_InitStructure;
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);	//使能DMA传输
	
	
    DMA_DeInit(DMA1_Channel4);  
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;//DMA外设地址 
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)g_uart1SendBuff;//DMA 存储器0地址 
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//存储器到外设模式 
    DMA_InitStructure.DMA_BufferSize = SEND_BUF_SIZE;//数据传输量 
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式 
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式 
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位 
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位 
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级 
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);//初始化DMA Stream
	DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
	
	
    DMA_DeInit(DMA1_Channel5);  
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;//DMA外设地址 
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)g_uart1ReceiveBuff;//DMA 存储器0地址 
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC ;//外设到存储器模式 
    DMA_InitStructure.DMA_BufferSize = RECEIVE_BUF_SIZE;//数据传输量 
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式 
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式 
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位 
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位 
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级 
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
    DMA_Init(DMA1_Channel5, &DMA_InitStructure);//初始化DMA Stream 
	
	
	
	
    DMA_DeInit(DMA1_Channel2);  
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART3->DR;//DMA外设地址 
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)g_uart3SendBuff;//DMA 存储器0地址 
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//存储器到外设模式 
    DMA_InitStructure.DMA_BufferSize = SEND_BUF_SIZE;//数据传输量 
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式 
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式 
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位 
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位 
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级 
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
    DMA_Init(DMA1_Channel2, &DMA_InitStructure);//初始化DMA Stream
	DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);
	
	
    DMA_DeInit(DMA1_Channel3);  
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART3->DR;//DMA外设地址 
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)g_uart3ReceiveBuff;//DMA 存储器0地址 
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC ;//外设到存储器模式 
    DMA_InitStructure.DMA_BufferSize = RECEIVE_BUF_SIZE;//数据传输量 
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式 
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式 
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位 
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位 
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级 
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
    DMA_Init(DMA1_Channel3, &DMA_InitStructure);//初始化DMA Stream 
	
	
	
	
	NVIC_Configuration();
	
	DMA_Cmd(DMA1_Channel5, ENABLE);  //开启DMA传输
	DMA_Cmd(DMA1_Channel3, ENABLE);  //开启DMA传输
	
	DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);  
	DMA_ITConfig(DMA1_Channel3,DMA_IT_TC,ENABLE);  
}

  
void DmaSendDataProc(DMA_Channel_TypeDef *DMA_Streamx,uint16_t ndtr)  
{   

    DMA_Cmd(DMA_Streamx, DISABLE);                      //关闭DMA传输 

    DMA_SetCurrDataCounter(DMA_Streamx,ndtr);          //数据传输量 

    DMA_Cmd(DMA_Streamx, ENABLE);                      //开启DMA传输 
}

 
void Uart1DmaSendByte(uint8_t nSendInfo)  
{   
    uint8_t *pBuf = NULL;  
    //指向发送缓冲区
    pBuf = g_uart1SendBuff;  
    *pBuf++ = nSendInfo;  
  
    DmaSendDataProc(DMA1_Channel4, 1); //开始一次DMA传输! 
} 

 
void Uart1DmaSendString(uint8_t* pSendInfo, uint16_t nSendCount)  
{   
    uint16_t i = 0;  
    uint8_t *pBuf = NULL;  
    //指向发送缓冲区 
    pBuf = g_uart1SendBuff;  
  
    for (i=0; i<nSendCount; i++)  
    {   
        *pBuf++ = pSendInfo[i];  
    }  
    //DMA发送方式 
    DmaSendDataProc(DMA1_Channel4, nSendCount); //开始一次DMA传输! 
}  

 
void Uart3DmaSendByte(uint8_t nSendInfo)  
{   
    uint8_t *pBuf = NULL;  
    //指向发送缓冲区
    pBuf = g_uart3SendBuff;  
    *pBuf++ = nSendInfo;  
  
    DmaSendDataProc(DMA1_Channel2, 1); //开始一次DMA传输! 
} 

 
void Uart3DmaSendString(uint8_t* pSendInfo, uint16_t nSendCount)  
{   
    uint16_t i = 0;  
    uint8_t *pBuf = NULL;  
    //指向发送缓冲区 
    pBuf = g_uart3SendBuff;  
  
    for (i=0; i<nSendCount; i++)  
    {   
        *pBuf++ = pSendInfo[i];  
    }  
    //DMA发送方式 
    DmaSendDataProc(DMA1_Channel2, nSendCount); //开始一次DMA传输! 
}


void DMA1_Channel4_IRQHandler(void)  
{   
    //清除标志 
    if(DMA_GetFlagStatus(DMA1_FLAG_TC4)!=RESET)//等待传输完成 
    {    
        DMA_ClearFlag(DMA1_FLAG_TC4);//清除传输完成标志 
    }  
} 

 
void DMA1_Channel5_IRQHandler(void)  
{   
    //清除标志 
    if(DMA_GetFlagStatus(DMA1_FLAG_TC5)!=RESET)//等待传输完成 
    {    
        DMA_Cmd(DMA1_Channel5, DISABLE); //关闭DMA,防止处理其间有数据 
  
        g_uart1ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5);  
        if(g_uart1ReceiveSize !=0)  
        {   
            // 此处不处理数据,uart处理
        }  
          
        DMA_ClearFlag(DMA1_FLAG_TC5 | DMA1_FLAG_TE5 | DMA1_FLAG_HT5);//清除DMA2_Steam7传输完成标志 
        DMA_SetCurrDataCounter(DMA1_Channel5, RECEIVE_BUF_SIZE);  
        DMA_Cmd(DMA1_Channel5, ENABLE);     //打开DMA, 
    }  
}  


void DMA1_Channel2_IRQHandler(void)  
{   
    //清除标志 
    if(DMA_GetFlagStatus(DMA1_FLAG_TC2)!=RESET)//等待传输完成 
    {    
        DMA_ClearFlag(DMA1_FLAG_TC2);//清除传输完成标志 
    }  
} 

 
void DMA1_Channel3_IRQHandler(void)  
{   
    //清除标志 
    if(DMA_GetFlagStatus(DMA1_FLAG_TC3)!=RESET)//等待传输完成 
    {    
        DMA_Cmd(DMA1_Channel3, DISABLE); //关闭DMA,防止处理其间有数据 
  
        g_uart3ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel3);  
        if(g_uart3ReceiveSize !=0)  
        {   
            // 此处不处理数据,uart处理
        }  
          
        DMA_ClearFlag(DMA1_FLAG_TC3 | DMA1_FLAG_TE3 | DMA1_FLAG_HT3);//清除DMA2_Steam7传输完成标志 
        DMA_SetCurrDataCounter(DMA1_Channel3, RECEIVE_BUF_SIZE);  
        DMA_Cmd(DMA1_Channel3, ENABLE);     //打开DMA, 
    }  
} 



static void NVIC_Configuration(void)
{ 
	NVIC_InitTypeDef NVIC_InitStructure;

	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	
	// 配置UART1发送 
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
    NVIC_Init(&NVIC_InitStructure);    
	
	// 配置UART1接收 
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
    NVIC_Init(&NVIC_InitStructure);    
	
	// 配置UART3发送 
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
    NVIC_Init(&NVIC_InitStructure);    
	
	// 配置UART3接收 
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
    NVIC_Init(&NVIC_InitStructure);    
}

main.c

int main()
{ 
	...
	USART_Config();
	DMA_Config();
	...
}

• 由 青梅煮久 写于 2021 年 02 月 20 日

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服