STM32 SPI DMA例程


#include "sd_hardware.h"
#include "SPI1_DMA.h"

static SPI_InitTypeDef  SPI_InitStructure;

//=============================================================================
//芯片外设初始化
//=============================================================================
void sd_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(    SPI1_CLK, ENABLE );
    RCC_APB2PeriphClockCmd(    SPI1_CLK|SPI1_CS_CLK|SPI1_SCK_CLK|SPI1_MISO_CLK|SPI1_MOSI_CLK, ENABLE );
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

    GPIO_InitStructure.GPIO_Pin = SPI1_CS_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SPI1_CS_PORT, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = SPI1_SCK_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SPI1_SCK_PORT, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = SPI1_MISO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SPI1_MISO_PORT, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = SPI1_MOSI_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SPI1_MOSI_PORT, &GPIO_InitStructure);

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;        //设置SPI工作模式:设置为主SPI
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;        //设置SPI的数据大小:SPI发送接收8位帧结构
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;        //选择了串行时钟的稳态:时钟悬空高
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;    //数据捕获于第二个时钟沿
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;        //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;        //定义波特率预分频的值:波特率预分频值为256
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
    SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值计算的多项式
    SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

    SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE);
    SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,ENABLE);
    
    SPI_Cmd(SPI1, ENABLE);//使能SPI
    
    SPI1_DMA_Configuration();
}

//=============================================================================
//=============================================================================
void SD_SPI_ReadWriteBlock(u8 *dat,unsigned short len)
{
    SPI1_ReceiveSendBlock(dat,len);
}

//=============================================================================
//=============================================================================
u8 SD_SPI_ReadWriteByte(u8 TxData)
{        
    while (SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SD_SPI, TxData);
    
    while (SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET);
    return SPI_I2S_ReceiveData(SD_SPI);
}

//=============================================================================
//SPI1设置速度
//=============================================================================
void SPI1_SetSpeed(u8 SpeedSet)
{
    SPI_InitStructure.SPI_BaudRatePrescaler = SpeedSet ;
  SPI_Init(SPI1, &SPI_InitStructure);
    SPI_Cmd(SPI1,ENABLE);
}

#include "SPI1_DMA.h"
                              
/*******************************************************************************
* Function Name  : SPI1_DMA_Configuration
* Description    : 配置SPI1_RX的DMA通道2,SPI1_TX的DMA通道3
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/

void SPI1_DMA_Configuration( void )
{
    unsigned char SPI1_RX_Buff[1];
    unsigned char SPI1_TX_Buff[1];
    
  RCC->AHBENR |= 1<<0 ;                     //DMA1时钟使能

    /*------------------配置SPI1_RX_DMA通道Channel2---------------------*/

  DMA1_Channel2->CCR &= ~( 1<<14 ) ;        //非存储器到存储器模式
    DMA1_Channel2->CCR |=    2<<12   ;        //通道优先级高
    DMA1_Channel2->CCR &= ~( 3<<10 ) ;        //存储器数据宽度8bit
    DMA1_Channel2->CCR &= ~( 3<<8  ) ;        //外设数据宽度8bit
    DMA1_Channel2->CCR |=    1<<7    ;        //存储器地址增量模式
    DMA1_Channel2->CCR &= ~( 1<<6  ) ;        //不执行外设地址增量模式
    DMA1_Channel2->CCR &= ~( 1<<5  ) ;        //执行循环操作
    DMA1_Channel2->CCR &= ~( 1<<4  ) ;        //从外设读

    DMA1_Channel2->CNDTR &= 0x0000   ;        //传输数量寄存器清零
    DMA1_Channel2->CNDTR = 1 ;                //传输数量设置为buffersize个

    DMA1_Channel2->CPAR = (u32)&SPI1->DR ;    //设置外设地址,注意PSIZE
    DMA1_Channel2->CMAR = (u32)SPI1_RX_Buff ; //设置DMA存储器地址,注意MSIZE

    /*------------------配置SPI1_TX_DMA通道Channel3---------------------*/

    DMA1_Channel3->CCR &= ~( 1<<14 ) ;        //非存储器到存储器模式
    DMA1_Channel3->CCR |=    0<<12   ;        //通道优先级最低
    DMA1_Channel3->CCR &= ~( 3<<10 ) ;        //存储器数据宽度8bit
    DMA1_Channel3->CCR &= ~( 3<<8 )  ;        //外设数据宽度8bit
    DMA1_Channel3->CCR |=    1<<7    ;        //存储器地址增量模式
    DMA1_Channel3->CCR &= ~( 1<<6 )  ;        //不执行外设地址增量模式
    DMA1_Channel3->CCR &= ~( 1<<5 ) ;         //不执行循环操作
    DMA1_Channel3->CCR |=    1<<4    ;        //从存储器读

    DMA1_Channel3->CNDTR &= 0x0000   ;        //传输数量寄存器清零
    DMA1_Channel3->CNDTR = 1 ;                //传输数量设置为buffersize个
    
    DMA1_Channel3->CPAR = (u32)&SPI1->DR ;    //设置外设地址,注意PSIZE
    DMA1_Channel3->CMAR = (u32)SPI1_TX_Buff ; //设置DMA存储器地址,注意MSIZE                 
}

//=============================================================================
//=============================================================================
void SPI1_ReceiveSendBlock( u8 *dat , u16 num )
{
    DMA1_Channel2->CNDTR = 0x0000   ;           //传输数量寄存器清零
    DMA1_Channel2->CNDTR = num ;                         //传输数量设置为buffersize个
    DMA1_Channel2->CMAR = (u32)dat ;                         //设置DMA存储器地址,注意MSIZE

    DMA1_Channel3->CNDTR = 0x0000   ;           //传输数量寄存器清零
    DMA1_Channel3->CNDTR = num ;                         //传输数量设置为buffersize个
    DMA1_Channel3->CMAR = (u32)dat ;                         //设置DMA存储器地址,注意MSIZE

    DMA1->IFCR |= 0xF0 ;                        //清除通道3的标志位
    DMA1->IFCR |= 0xF00 ;                       //清除通道3的标志位

    SPI1->DR ;                                                                    //接送前读一次SPI1->DR,保证接收缓冲区为空
    while( ( SPI1->SR & 0x02 ) == 0 );
    
    DMA1_Channel3->CCR |= 1 << 0 ;              //开启DMA通道3
    DMA1_Channel2->CCR |= 1 << 0 ;              //开启DMA通道2    

    while( ( DMA1->ISR & DMA1_FLAG_TC2 ) == 0 );

    DMA1_Channel3->CCR &= ~( 1 << 0 ) ;         //关闭DMA通道3
    DMA1_Channel2->CCR &= ~( 1 << 0 ) ;         //关闭DMA通道2
}
 

驱动SD卡成功

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值