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);
}

 

posted @ 2013-03-13 20:33  zpehome  阅读(1097)  评论(0编辑  收藏  举报