使用DMA中断规避或减轻单片机对通信快速响应的需求

使用DMA中断规避或减轻单片机对通信快速响应的需求

可能在很多时候我们想到使用DMA只是为了处理大量数据接收的时候减轻对单片机的使用负荷,其实这在一定程度上也是可以认为对需要快速响应去做接收以及长时间接收的一种很好的处理方法。因为总会有遇到正在执行任务的时候单片机来不及去响应某一通信以及处理大量数据。因此我们可以使用DMA在脱离单片机内核的情况下,先响应通信接收完数据之后,然后再产生中断告诉单片机去处理DMA接收好的数据。

1.示意图:
个人觉得还是画个图来的直观,哈哈

在这里插入图片描述
2.代码实现
这里以串口通信为例:
(1)外围硬件初始化函数

void Hardware_Init(void)
{

    delay_init(168);        //初始化时钟

    Usart1_Init(115200);	//串口1初始化
	
	DMA_Config_About_Rx();	//关于DMA接收配置
	
	DMA_Config_About_Tx();	//关于DMA发送配置
}

(2)串口1初始化函数(需要看详细注释,可下载文末工程链接)

void Usart1_Init(unsigned int baud)
{
	GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);                     
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);                    

    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);                  
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);                 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;                  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                             
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                        
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                           
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;                             
    GPIO_Init(GPIOA,&GPIO_InitStructure);                                    

    USART_InitStructure.USART_BaudRate = baud;                               
    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(USART1, &USART_InitStructure);                                

    USART_Cmd(USART1, ENABLE);                                               
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);                           

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;                        
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;                  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		                 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			                 
    NVIC_Init(&NVIC_InitStructure);	                                         

    USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);                             
    USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);                             

}

(3)串口中断服务函数

void USART1_IRQHandler(void)
{
    u16 Res;

    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  						
    {
		DMA_Cmd(DMA2_Stream5, DISABLE);                                        	
		
		Res = USART1->SR;                                                       
		Res = USART1->DR;                                                       
		
		Rx_Data_Lenth = BufferLen - DMA_GetCurrDataCounter(DMA2_Stream5);   
        if(Rx_Data_Lenth!=0)                                                    
        {
            rx_flag=true;                                                       
            for(Res=0; Res < Rx_Data_Lenth; Res++)
            {
                SendBuffer[Res]= ReceiveBuffer[Res];                             
            }
            for(Res=0; Res < Rx_Data_Lenth; Res++)                               
            {
                ReceiveBuffer[Res]=0;
            }
        }
		DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);
        DMA_SetCurrDataCounter(DMA2_Stream5, BufferLen);                       		
        DMA_Cmd(DMA2_Stream5, ENABLE);                                         		
    }

(4)DMA发送配置

void DMA_Config_About_Tx(void)
{
	DMA_InitTypeDef  DMA_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);                      
	DMA_DeInit(DMA2_Stream7);
	while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);                       
	DMA_InitStructure.DMA_Channel = DMA_Channel_4;                           
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;             
	DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SendBuffer;                 
	DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                  
	DMA_InitStructure.DMA_BufferSize = BufferLen;                            
	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_Medium;                    
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;              
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;     
	DMA_Init(DMA2_Stream7, &DMA_InitStructure);                              
 
	NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;  
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
	NVIC_Init(&NVIC_InitStructure);  
	DMA_ITConfig(DMA2_Stream7,DMA_IT_TC,ENABLE);
}

(5)DMA接收配置

void DMA_Config_About_Rx(void)
{
	DMA_InitTypeDef  DMA_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);                      
	DMA_DeInit(DMA2_Stream5);
	while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE);                       
	DMA_InitStructure.DMA_Channel = DMA_Channel_4;                           
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;             
	DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ReceiveBuffer;              
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;                 
	DMA_InitStructure.DMA_BufferSize = BufferLen;                            
	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_Circular;                          
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                    
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;              
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;     
	DMA_Init(DMA2_Stream5, &DMA_InitStructure);                              
 
	DMA_Cmd(DMA2_Stream5, ENABLE);                                           
}

(6)DMA中断服务函数

void DMA2_Stream7_IRQHandler(void)                                         
{
  if(DMA_GetFlagStatus(DMA2_Stream7,DMA_FLAG_TCIF7)!=RESET)                
  {  
    DMA_ClearFlag(DMA2_Stream7,DMA_FLAG_TCIF7);                            
    DMA_Cmd(DMA2_Stream7,DISABLE);                                                 
    DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7);                      
// 	DMA_Config_About_Rx();
  }  
}

3.实现效果
这里实现的是,串口DMA接收以及将接收到的数据通过DMA发送出来。
在这里插入图片描述

4.工程链接(免费):
https://download.csdn.net/download/tiange1996/85031420

							2022.03.24----ltt																												
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

修才生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值