STM32 SPI-DMA读写 SPI Flash (只需改动两个函数) +cube配置

最近在项目中遇到了 通过SPI DMA方式读写W25Q256;
网上许多例程都是直接读取flash,读写会占用比较长的时间 ,如果这个SPI上还挂载了其他SPI 器件,如SPI显示屏,就需要通过开启DMA来提升速度了。
在这里记录一下我的调试过程:
一.详细CUBE 配置
1.基础设置,我用的是SPI6.oaramerter
2.DMA设置,并设置中断优先级在这里插入图片描述
3.SPI global interrupt不用开启
然后生成代码;
二,代码。
基础代码是正点原子的SPI flash 函数
基本读写函数没有开启DMA,因为只有单字节读写,所以不用开启DMA,后面两个就是DMA读写函数(hal库操作还是贼简单)

uint8_t SPI6_ReadWriteByte(uint8_t TxData)
{
    uint8_t Rxdata;

    HAL_SPI_TransmitReceive(&hspi6,&TxData,&Rxdata,1, 1000);

    return Rxdata;                      //返回收到的数据
}
void SPI6_WriteDMA(uint8_t *pTxData, uint16_t Size)
{

    HAL_SPI_Transmit_DMA(&hspi6,pTxData,Size);

}
void SPI6_ReadDMA( uint8_t *pRxData, uint16_t Size)
{

    HAL_SPI_Receive_DMA(&hspi6,pRxData,Size);

}

基本读写函数写好了,就只需要去改flash的块读写操作函数即可,中间有一个很容易忽略的问题在后面提出

//读取SPI FLASH  
//在指定地址开始读取指定长度的数据
//pBuffer:数据存储区
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节数(最大65535)
void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)   
{ 
 	u16 i;   										    
	W25QXX_CS=0;                            //使能器件   
    SPI6_ReadWriteByte(W25X_ReadData);      //发送读取命令
    if(W25QXX_TYPE==W25Q256)                //如果是W25Q256的话地址为4字节的,要发送最高8位
    {
        SPI6_ReadWriteByte((u8)((ReadAddr)>>24));
    }
    SPI6_ReadWriteByte((u8)((ReadAddr)>>16));   //发送24bit地址
    SPI6_ReadWriteByte((u8)((ReadAddr)>>8));
    SPI6_ReadWriteByte((u8)ReadAddr);
#ifdef SPI_USE_DMA
    SPI6_ReadDMA(pBuffer,NumByteToRead);
#else
    for(i=0;i<NumByteToRead;i++)
	{ 
        pBuffer[i]=SPI6_ReadWriteByte(0XFF);    //循环读数
    }
    W25QXX_CS=1;
#endif

}  
//SPI在一页(0~65535)内写入少于256个字节的数据
//在指定地址开始写入最大256字节的数据
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!	 
void W25QXX_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
 	u16 i;  
 	u8* rxBuffer;
    W25QXX_Write_Enable();                  //SET WEL 
	W25QXX_CS=0;                            //使能器件   
    SPI6_ReadWriteByte(W25X_PageProgram);   //发送写页命令
    if(W25QXX_TYPE==W25Q256)                //如果是W25Q256的话地址为4字节的,要发送最高8位
    {
        SPI6_ReadWriteByte((u8)((WriteAddr)>>24));
    }
    SPI6_ReadWriteByte((u8)((WriteAddr)>>16)); //发送24bit地址
    SPI6_ReadWriteByte((u8)((WriteAddr)>>8));
    SPI6_ReadWriteByte((u8)WriteAddr);
#ifdef SPI_USE_DMA
    SPI6_WriteDMA(pBuffer,NumByteToWrite);
#else
    for(i=0;i<NumByteToWrite;i++)SPI6_ReadWriteByte(pBuffer[i]);//循环写数
    W25QXX_CS=1;                            //取消片选
#endif

	W25QXX_Wait_Busy();					   //等待写入结束
} 

上面通过宏定义区分是否使用DMA,其中需要注意的就是W25Q64
的片选信号在DMA方式时不能马上取消片选;因为SPI6_WriteDMA函数实际只是打开了DMA,数据并没有发送完成。
当然在这里等待写入完成也是个坑,暂时没想到怎么填,如果SPI上只挂载了flash,就不用等了,可以去干其他的事。所以只能在回调函数中去取消片选。
W25QXX_Wait_Busy(); //等待写入结束在这里插入图片描述

添加回调函数

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
   if(hspi== &hspi6)
   {
       W25QXX_CS=1;
   }

}

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{

    if(hspi== &hspi6)
      {
          W25QXX_CS=1;
      }

}

到这里;DMA方式读写flash才算完成配置了。
总结如下:
1. 配置SPI 及对应Tx RX DMA;
2.改写flash块读写函数;
3.添加回调函数,取消片选;
遗留问题:实际读写速度还需测试 ;考虑等待写入结束怎样处理。

发布了15 篇原创文章 · 获赞 0 · 访问量 289

猜你喜欢

转载自blog.csdn.net/qq_33552551/article/details/104420324