DMA数据的发送接收

本人本科在读,就是课下总结自己瞎写,能帮上就帮上!

1、什么是DMA?

Direct Memory Access 将数据从一个地址空间复制到另一个地址空间。

 

 先配置中断引脚和中断NVIC

#define bSize 512
uint8_t TperBuf[bSize];
uint8_t RperBuf[bSize];
void usart_gpio_ini()
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|
                           RCC_APB2Periph_USART1|
	                       RCC_APB2Periph_GPIOB|
	                       RCC_APB2Periph_AFIO, ENABLE) ;
	
	
	GPIO_InitTypeDef gpio_Ini;
	gpio_Ini.GPIO_Pin = GPIO_Pin_9; //PA.9
	gpio_Ini.GPIO_Speed = GPIO_Speed_50MHz;
	gpio_Ini.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOA, &gpio_Ini);//初始化GPIOA.9

	gpio_Ini.GPIO_Pin = GPIO_Pin_10;//PA10
	gpio_Ini.GPIO_Speed = GPIO_Speed_50MHz;
	gpio_Ini.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOA, &gpio_Ini);//初始化GPIOA.10  
	
	NVIC_InitTypeDef nvic_Ini;
	nvic_Ini.NVIC_IRQChannel=USART1_IRQn;
	nvic_Ini.NVIC_IRQChannelCmd=ENABLE;
	nvic_Ini.NVIC_IRQChannelPreemptionPriority=1;
	nvic_Ini.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&nvic_Ini);
	
	USART_InitTypeDef usart_Ini;
	usart_Ini.USART_BaudRate=9600;
	usart_Ini.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	usart_Ini.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	usart_Ini.USART_Parity=USART_Parity_No;
	usart_Ini.USART_StopBits=USART_StopBits_1;
	usart_Ini.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART1,&usart_Ini);
	
	USART_DMACmd(USART1,USART_DMAReq_Rx|USART_DMAReq_Tx,ENABLE);
	USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);//空闲中断
	USART_Cmd(USART1,ENABLE);
}

DMA通道4和5配置

数据长度是一个字节,寄存器内存增量,外设不可以增量。

void dma_ini()
{
	DMA_InitTypeDef dma_Ini;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	
	dma_Ini.DMA_BufferSize=bSize;
	dma_Ini.DMA_M2M=DMA_M2M_Disable;
	dma_Ini.DMA_DIR=DMA_DIR_PeripheralSRC;
	dma_Ini.DMA_MemoryBaseAddr=(uint32_t)RperBuf;
	dma_Ini.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
	dma_Ini.DMA_MemoryInc=DMA_MemoryInc_Enable;
	dma_Ini.DMA_Mode=DMA_Mode_Normal;
	dma_Ini.DMA_PeripheralBaseAddr=USART1_BASE+0x04;
	dma_Ini.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
	dma_Ini.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	dma_Ini.DMA_Priority=DMA_Priority_Medium;//DMA某通道具有优先级
	DMA_Init(DMA1_Channel5,&dma_Ini);
	
	dma_Ini.DMA_BufferSize=bSize;
	dma_Ini.DMA_DIR=DMA_DIR_PeripheralDST;
	dma_Ini.DMA_M2M=DMA_M2M_Disable;
	dma_Ini.DMA_MemoryBaseAddr=(uint32_t)TperBuf;
	dma_Ini.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
	dma_Ini.DMA_MemoryInc=DMA_MemoryInc_Enable;
	dma_Ini.DMA_Mode=DMA_Mode_Normal;
	dma_Ini.DMA_PeripheralBaseAddr=USART1_BASE+0x04;
	dma_Ini.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
	dma_Ini.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	dma_Ini.DMA_Priority=DMA_Priority_Medium;
	DMA_Init(DMA1_Channel4,&dma_Ini);
	
	DMA_Cmd(DMA1_Channel4,DISABLE);
	DMA_Cmd(DMA1_Channel5,ENABLE);//使能DMA传输完成通道	
}

串口1的配置, 

void USART1_IRQHandler()
{
	if(USART_GetITStatus(USART1,USART_IT_IDLE)==SET)//通道传输完成标志
	{
		USART_ClearITPendingBit(USART1,USART_IT_IDLE);
		uint16_t ls=USART_ReceiveData(USART1);
		
		DMA_Cmd(DMA1_Channel5,DISABLE);
		uint16_t size=bSize-DMA_GetCurrDataCounter(DMA1_Channel5);//总的减去当前有的内存空间
		
		for(int i=0;i<size;i++)
			TperBuf[i]=RperBuf[i];
		DMA_SetCurrDataCounter(DMA1_Channel5,bSize);//
		DMA_Cmd(DMA1_Channel5,ENABLE);
		
		DMA_Cmd(DMA1_Channel4,DISABLE);
		DMA_SetCurrDataCounter(DMA1_Channel4,size);
		DMA_Cmd(DMA1_Channel4,ENABLE);
		
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);
		for(int i=0;i<10000;i++);
		GPIO_SetBits(GPIOB,GPIO_Pin_5);
		for(int i=0;i<10000;i++);
	}
}

什么是IDLE中断

IDLE就是串口收到一帧数据后,超过1个Byte的时间没有收到数据,就发生的中断。

通道x传输数量寄存器

清除IDLE标志位,CurrdataCounter寄存器大于0并且使能开启就会自动发数据。

只能在通道停止时设置,通道启动后变为只读,指示剩余的待传输字节数;

寄存器内容变成0并配置成自动重加载模式时,会自动装载上次配置的值;

数值为0时,不进行数据传输;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值