9. 直接存储器存取DMA

9. 直接存储器存取DMA

  9.1 DMA简介

  9.2 USART的DMA操作

  9.3 TIM的DMA操作

  9.4 ADC的DMA操作

  9.1 DMA简介

  • 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的批量数据传输。DMA传送过程中无须CPU干预,数据可以通过DMA快速地传送,这就节省了CPU的资源来做其他操作
  • STM32的两个DMA控制器有12个通道(DMA1有7个通道DMA2有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求,还有一个仲裁器来协调各个DMA请求的优先权
  • DMA1的通道请求源

  • DMA1通过30(2+4*7)个寄存器进行操作

  • 中断位状态位

  • 中断标志清除位

  • 通道配置寄存器

  • DMA1的2级中断控制

9.2 USART的DMA操作

  • 与DMA有关的USART控制位(USART控制寄存器3)

  • 与DMA有关的USART初始化程序段
USART1->CR3 |= 1<<6;                     //允许DMA接收
  • DMA1通道5初始化程序
//DMA1通道5初始化程序

void Dma1_Ch5_Init(void)
{
    RCC->AHBENR |= 1;                          //开启DMA1时钟

    DMA1_Channe15-> CNDTR = 4;                 //传输数据数量

    DMA1_Channe15-> CPAR = 0x40013804;         //外设地址(USART->DR)

    DMA1_Channe15->CMAR = (int)usart1_rxd;     //存储器地址

    DMA1_Channe15-> CCR |= 0xa3;         //允许DMA1通道5,允许传输完成中断
                                         //外设读,循环模式,存储器地址增量
 
    NVIC->ISER[0] |= 1<<15;              //允许DMA1通道5中断
}
  • DMA1通道5中断处理程序
//DMA1通道5中断处理程序
void DMAChanne15_IRQHandler(void)
{
    DMA1->IFCR |= 0x70000;                               //清除中断标志

    min = ((usart1_rxd[0] -0x30)<<4)+usart1_rxd[1]-0x30; //设置分值

    sec = ((usart1_rxd[2] -0x30)<<4)+usart1_rxd[3]-0x30; //设置秒值
}

9.3 TIM的DMA操作

  • 与DMA有关的TIM控制位(TIM DMA/中断使能寄存器)

  • 与DMA有关的TIM初始化程序段
TIM1->DIER |= 1<<8;                 //允许更新DMA请求
  • DMA1通道5初始化程序
void Dma1_Ch5_Init(void)
{
    RCC->AHBENR |= 1;                     //开启DMA1时钟

    DMA1_Channe15->CNDTR = 9;             //传输数据数量

    DMA1_Channe15->CPAR = 0x40012C34;     //外设地址(TIM1->CCR1)

    DMA1_Channe15->CMAR = (int)tim1_ccr1; //存储器地址

    DMA1_Channe15->CCR |= 0x5b1;     //允许DMA1通道5,存储器读
                                     //循环模式,存储器地址增量,16位
}
  • 此时的DMA1通道5不需要中断操作
  • 由于USART1_RX和TIM1_UP共用DMA1通道5,所以两者不能同时工作

9.4 ADC的DMA操作

  • 与DMA有关的ADC控制位(ADC控制寄存器2)

  • 与DMA有关的ADC初始化程序段
ADC1->CR2 |= 1<<8;                 //DMA模式
  • DMA1通道1初始化程序
//DMA1通道1初始化程序
void Dma1_Ch1_Init(void)
{
    RCC->AHBENR |= 1;                     //开启DMA1时钟

    DMA1_Channel1->CNDTR = 2;             //传输数据数量

    DMA1_Channel1->CPAR = 0x4001244c;     //外设地址(ADC1->DR)

    DMA1_Channel1->CMAR = (int)adc1_dat;  //存储器地址

    DMA1_Channel1->CCR |= 0x5a1;        //允许DMA1通道1,外设读
                                        //循环模式,存储器地址增量,16位
}

猜你喜欢

转载自blog.csdn.net/SherlockHolmess/article/details/88014380