• STM32L151之DMA


    要想使用DMA功能,首先使能DMA模块的时钟。

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

    将SPI的接收和发送方式设置为DMA方式

    void SPI_Config(void)
    {
        SPI_I2S_DeInit(SPI1);//重置SPI1
        SPI_InitStruct.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//spi设置成双向双线全双工
    
        SPI_InitStruct.SPI_Mode=SPI_Mode_Master;//SPI工作在主模式
    
        SPI_InitStruct.SPI_DataSize=SPI_DataSize_8b;//SPI接收发送8位数据
    
        SPI_InitStruct.SPI_CPOL=SPI_CPOL_Low;//始终悬空低,SCK在空闲时保持低电平
    
        SPI_InitStruct.SPI_CPHA=SPI_CPHA_1Edge;//数据捕获于第一个时钟沿
    
        SPI_InitStruct.SPI_NSS=SPI_NSS_Soft;//软件控制NSS
    
        SPI_InitStruct.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_4;比特率预分频值为4分频
    
        SPI_InitStruct.SPI_FirstBit=SPI_FirstBit_MSB;//数据传输从MSB开始
    
        SPI_InitStruct.SPI_CRCPolynomial=7;//用于CRC值校验的多项式
    
        SPI_Init(SPI1,&SPI_InitStruct);
        SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,ENABLE);//将SPI1模块接收设置成DMA方式工作
        SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,ENABLE);//将SPI1模块发送设置成DMA方式工作
    
        SPI_Cmd(SPI1,ENABLE)
    }

    SPI的DMA接收配置:

    void SPI1_DMA_Recv_Config(void)
    {
        DMA1_Channel2->CPAR=(uint32_t)(&(SPI1->DR));//设置DMA通道2的外设地址
        DMA1_Channel2->CCR |= 0x2080;
        //PL=10  优先级高
        //MSIZ=00  存储8位
        //PSIZE=00  外设8位
        //MINC=1    存储地址自增
        //PINC=0   外设地址不变
        //CIRC=0   非循环模式
        //DIR=0    方向由外设到存储器
    }

    SPI的DMA发送配置:

    void SPI1_DMA_Send_Config(void)
    {
        DMA1_Channel3->CPAR=(uint32_t)(&(SPI1->DR));//设置DMA通道2的外设地址
        DMA1_Channel3->CCR |= 0x0090;
        //PL=10  优先级高
        //MSIZ=00  存储8位
        //PSIZE=00  外设8位
        //MINC=1    存储地址自增
        //PINC=0   外设地址不变
        //CIRC=0   非循环模式
        //DIR=1    方向由存储器到外设
    }

    当通道配置为非循环模式时,传输结束后(即传输计数变为0)将不再产生DMA操作。要开始新的DMA传输,需要在关闭DMA通道的情况下,在DMAx_CNDTR寄存器中重新写入传输数目。
    在循环模式下,最后一次传输结束时,DMA_CNDTRx寄存器的内容会自动地被重新加载为其初始数值,内部的当前外设/存储器地址寄存器也被重新加载为DMAx_CPAR/DMAx_CMAR寄存器设定的初始基地址。

    SPI利用DMA发送接收数据:

    void SPI1_ReceiveSendByte(uint16_t num,unsigned char *rx,unsigned char *tx)
    {
        DMA_Channel2->CNDTR=num;//设置发送数据字节数
        DMA_Channel2->CMAR=(uint32_t)rx;//DMA内存地址寄存器
    
        DMA_Channel3->CNDTR=num;//设置发送数据字节数
        DMA_Channel3->CMAR=(uint32_t)tx;//DMA内存地址寄存器
    
        DMA_Channel3->CCR |= 0x0001;//启动DMA
        DMA_Channel2->CCR |= 0x0001;
    
        while((DMA1->ISR & (1<<9)) == 0);//等待DMA传送完成
        while((DMA1->ISR & (1<<5)) == 0);
    
        DMA1->IRCR |= (1<<5)|(1<<9);//清标志位
    
        DMA_Channel3->CCR &= ~(1<<0);//关闭DMA
        DMA_Channel2->CCR &= ~(1<<0);
    }
  • 相关阅读:
    前端异常上报
    前端异常解析:Source Map
    前端操作剪切板不完全指北
    多系统之间模块相互引用的引发的深思
    浅谈vue原理(四)
    浅谈vue原理(三)
    浅谈vue原理(二)
    浅谈vue原理(一)
    vue中路由嵌套的作用
    常用的学习网站和小工具
  • 原文地址:https://www.cnblogs.com/zpehome/p/2957088.html
Copyright © 2020-2023  润新知