DMA直接存储器访问-基于STM32F407-DMA接收

宏定义
/*******************************************************/

//DMA发送
#define DEBUG_USART_DR_BASE           			(USART1_BASE+0x04)		
#define SEND_BUFF_SIZE                     		64				//发送的数据量
#define DEBUG_USART_DMA_Tx_CLK               	RCC_AHB1Periph_DMA2	
#define DEBUG_USART_DMA_Tx_CHANNEL           	DMA_Channel_4
#define DEBUG_USART_DMA_Tx_STREAM            	DMA2_Stream7
#define DEBUG_USART_DMA_Tx_IRQ					DMA2_Stream7_IRQn
//DMA接收
#define DEBUG_USART_DR_BASE           			(USART1_BASE+0x04)		
#define RECEIVE_BUFF_SIZE                     	64				//接收的数据量
#define DEBUG_USART_DMA_Rx_CLK               	RCC_AHB1Periph_DMA2	
#define DEBUG_USART_DMA_Rx_CHANNEL           	DMA_Channel_4
#define DEBUG_USART_DMA_Rx_STREAM            	DMA2_Stream5
#define DEBUG_USART_DMA_Rx_IRQ					DMA2_Stream5_IRQn

//USART
#define DEBUG_USART					USART1
#define DEBUG_USART_CLK				RCC_APB2Periph_USART1
#define DEBUG_USART_BAUDRATE		115200

#define DEBUG_USART_RX_GPIO_PORT	GPIOA
#define DEBUG_USART_RX_GPIO_CLK		RCC_AHB1Periph_GPIOA
#define DEBUG_USART_RX_PIN			GPIO_Pin_10
#define DEBUG_USART_RX_AF			GPIO_AF_USART1
#define DEBUG_USART_RX_SOURCE		GPIO_PinSource10

#define DEBUG_USART_TX_GPIO_PORT	GPIOA
#define DEBUG_USART_TX_GPIO_CLK		RCC_AHB1Periph_GPIOA	
#define DEBUG_USART_TX_PIN			GPIO_Pin_9
#define DEBUG_USART_TX_AF			GPIO_AF_USART1
#define DEBUG_USART_TX_SOURCE		GPIO_PinSource9

#define DEBUG_USART_IRQHandler                  USART1_IRQHandler
#define DEBUG_USART_IRQ                 		USART1_IRQn
/******************************
函数配置
/*******************************************************/

void Receive_DataPack(void);
void test(void);

void NVIC_Config(void){
	
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
	NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器

	NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_DMA_Tx_IRQ;		//中断类型:DMA2数据流7中断
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//开启中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;	//中断抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;			//中断响应优先级
	NVIC_Init(&NVIC_InitStructure);								//初始化中断
		
}

/*DMA_Tx*/
uint8_t SendBuff[SEND_BUFF_SIZE];
void USART1_DMA_Tx_Config(void) {

    DMA_InitTypeDef DMA_InitStructure;	
    RCC_AHB1PeriphClockCmd(DEBUG_USART_DMA_Tx_CLK, ENABLE);//开启DMA时钟
    DMA_DeInit(DEBUG_USART_DMA_Tx_STREAM);// 复位初始化DMA数据流

    /* 确保DMA数据流复位完成 */
    while (DMA_GetCmdStatus(DEBUG_USART_DMA_Tx_STREAM) != DISABLE)  {  }

    DMA_InitStructure.DMA_Channel = DEBUG_USART_DMA_Tx_CHANNEL;  				//sart1 tx对应dma2,通道4,数据流7
    DMA_InitStructure.DMA_PeripheralBaseAddr = DEBUG_USART_DR_BASE;	 		//设置DMA源:串口数据寄存器地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SendBuff;					//内存地址(要传输的变量的指针)
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;					//方向:从内存到外设
    DMA_InitStructure.DMA_BufferSize = SEND_BUFF_SIZE;						//传输大小DMA_BufferSize=SENDBUFF_SIZE
    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;			//内存数据单位 8bit

    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;	 			//DMA模式:不断循环
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;      	//优先级:中

    /*禁用FIFO*/
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;

    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;    			//存储器突发传输 16个节拍
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;    	//外设突发传输 1个节拍
    DMA_Init(DEBUG_USART_DMA_Tx_STREAM, &DMA_InitStructure);					//配置DMA2的数据流7
    
    DMA_Cmd(DEBUG_USART_DMA_Tx_STREAM, ENABLE);//使能DMA
    
    while(DMA_GetCmdStatus(DEBUG_USART_DMA_Tx_STREAM) != ENABLE)  { }// 等待DMA数据流有效
}

/*DMA_Rx*/
 uint8_t ReceiveBuff[RECEIVE_BUFF_SIZE];
void USART1_DMA_Rx_Config(void) {

    DMA_InitTypeDef DMA_InitStructure;
    RCC_AHB1PeriphClockCmd(DEBUG_USART_DMA_Rx_CLK, ENABLE);//开启DMA时钟
    DMA_DeInit(DEBUG_USART_DMA_Rx_STREAM);// 复位初始化DMA数据流

    
    while (DMA_GetCmdStatus(DEBUG_USART_DMA_Rx_STREAM) != DISABLE)  { }// 确保DMA数据流复位完成

    DMA_InitStructure.DMA_Channel = DEBUG_USART_DMA_Rx_CHANNEL;  				//sart1 tx对应dma2,通道4,数据流7
    DMA_InitStructure.DMA_PeripheralBaseAddr = DEBUG_USART_DR_BASE;	 		//设置DMA源:串口数据寄存器地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ReceiveBuff;					//内存地址(要传输的变量的指针)
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;					//方向:从内存到外设
    DMA_InitStructure.DMA_BufferSize = RECEIVE_BUFF_SIZE;						//传输大小DMA_BufferSize=SENDBUFF_SIZE
    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;			//内存数据单位 8bit

    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;	 			//DMA模式:不断循环
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;      	//优先级:中

    /*禁用FIFO*/
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;

    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;    			//存储器突发传输 16个节拍
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;    	//外设突发传输 1个节拍
    DMA_Init(DEBUG_USART_DMA_Rx_STREAM, &DMA_InitStructure);					//配置DMA2的数据流7
    
    DMA_Cmd(DEBUG_USART_DMA_Rx_STREAM, ENABLE);//使能DMA
    
    while(DMA_GetCmdStatus(DEBUG_USART_DMA_Rx_STREAM) != ENABLE)  { }// 等待DMA数据流有效
}

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

    RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK|DEBUG_USART_TX_GPIO_CLK,ENABLE);
    RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    /* 配置Tx引脚为复用功能  */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN  ;
    GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

    /* 配置Rx引脚为复用功能 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;
	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);  
  
    GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,DEBUG_USART_RX_SOURCE,DEBUG_USART_RX_AF); /* 连接 PXx 到 USARTx_Tx*/  
    GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,DEBUG_USART_TX_SOURCE,DEBUG_USART_TX_AF); /*  连接 PXx 到 USARTx__Rx*/

    /* 配置串DEBUG_USART 模式 */
    USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;/* 波特率设置:DEBUG_USART_BAUDRATE */
    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模式控制:同时使能接收和发送 */
    /* 完成USART初始化配置 */
    USART_Init(DEBUG_USART, &USART_InitStructure);
	
	//中断设置
	USART_ITConfig(DEBUG_USART,USART_IT_TC,DISABLE);		//关闭传输完成中断
	USART_ITConfig(DEBUG_USART,USART_IT_RXNE,DISABLE);	//关闭串口接收中断
	USART_ITConfig(DEBUG_USART,USART_IT_TXE,DISABLE);	//关闭发送寄存器空中断
	USART_ITConfig(DEBUG_USART,USART_IT_IDLE,ENABLE);	//开启空闲中断
   
	USART_Cmd(DEBUG_USART, ENABLE); //使能串口
	
	NVIC_Config();
	USART1_DMA_Tx_Config();
	USART1_DMA_Rx_Config();
	
	USART_DMACmd(DEBUG_USART,USART_DMAReq_Tx,ENABLE);	//开启DMA发模式
	USART_DMACmd(DEBUG_USART,USART_DMAReq_Rx,ENABLE);	//开启DMA收模式
	
	USART_ClearFlag(DEBUG_USART,USART_FLAG_TC);
	
}

 


/*******************************************************/
//发送中断函数
void DMA2_Stream7_IRQHandler(void){	
	if(DMA_GetITStatus(DMA2_Stream7,DMA_IT_TCIF7) !=RESET){		//判断中断类型
		DMA_Cmd(DMA2_Stream7,DISABLE);							//关闭DMA传输
		DMA_ClearFlag(DMA2_Stream7,DMA_FLAG_TCIF7);				//清除传输完成标志位
		DMA_SetCurrDataCounter(DMA2_Stream7,SEND_BUFF_SIZE);
		USART_ITConfig(DEBUG_USART,USART_IT_TC,ENABLE);			//开启串口传输完成中断,发送最后两个字节
	}
}

//串口中断函数
void USART1_IRQHandler(void){   
    if(USART_GetITStatus(DEBUG_USART,USART_IT_IDLE)!=RESET)
    {       
        Receive_DataPack(); //接收数据
        USART_ReceiveData( DEBUG_USART );// 清除空闲中断标志位
    }
}

//接收数据并处理
static u16 Recv_Size = 0;	//获取接收大小
void Receive_DataPack(void)
{	
	int i=0;	
    DMA_Cmd(DEBUG_USART_DMA_Rx_STREAM, DISABLE);  /* 关闭DMA ,防止干扰,数据尚未处理 */     
    DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5);  /* 清DMA标志位 */
    Recv_Size = RECEIVE_BUFF_SIZE - DMA_GetCurrDataCounter(DEBUG_USART_DMA_Rx_STREAM);//得到接收字节长度	
	
//	for(i=0;i<Recv_Size;i++){printf("%2X  ",ReceiveBuff[i]);}
    
	DMA_SetCurrDataCounter(DEBUG_USART_DMA_Rx_STREAM,RECEIVE_BUFF_SIZE);		/* 重新赋值计数值,必须大于等于最大可能接收到的数据帧数目 */    
	DMA_Cmd(DEBUG_USART_DMA_Rx_STREAM,ENABLE);	/* 此处应该在处理完数据再打开,如在 DataPack_Process() 打开*/
    
}
/*******************************************************/

 

/*******************************************************/
///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{		
	USART_SendData(DEBUG_USART, (uint8_t) ch);/* 发送一个字节数据到串口 */
	while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET);	/* 等待发送完毕 */
	return (ch);
}

///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
	/* 等待串口输入数据 */
	while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_RXNE) == RESET);
	return (int)USART_ReceiveData(DEBUG_USART);
}


extern uint8_t SendBuff[SENDBUFF_SIZE];//给SendBuff[]赋值时,需要在前面调用串口函数里面的SendBuff[]

USART_DMACmd(DEBUG_USART, USART_DMAReq_Tx, ENABLE); //USART1 向 DMA发出TX请求

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值