CC2530(SPI)驱动FLASH芯片W25Qxx(2)-DMA写

本文档介绍了一篇关于使用STM32通过DMA方式读写W25Q64闪存芯片的代码实现。在主函数中,实现了写入数据到Flash和从Flash读取数据的过程。在W25Q64.c文件中,定义了使用SPI接口和DMA进行数据传输的函数。然而,在仿真调试过程中遇到了两个问题:读取数据时第一个字节为0,且DMA接收数据不完整。作者计划进一步研究Flash芯片的手册来寻找解决方案。
摘要由CSDN通过智能技术生成

这是在前篇文章基础上修改的,实现DMA方式写数据到flash芯片W25Q64。

1.主函数:

#include <iocc2530.h>
#include "hal_types.h"
#include "hal_board.h"
#include "hal_mcu.h"
#include "string.h"
#include "W25Qxx.h"
#include "uart.h"
#include "bspDma.h"

#define LED P2_0
#define FLASH_SIZE 160 //FLASH 大小为8M字节
uint16 IDTYPE = 0;//W25QXX器件ID
uint8 string[] =  "uart DMA test!";
//此数据是用来复制到内存的其他区域
uint8 data[] = "W25Q64 R&W test!";
//数据长度
#define DATA_AMOUNT sizeof(data)
//用来保存复制来的数据区域
uint8 copy[DATA_AMOUNT];

void InitClockTo32M(void)
{   
  CLKCONCMD &= ~0x40;              //设置系统时钟源为 32MHZ晶振
  while(!(CLKCONSTA & 0x40));      //等待晶振稳定
  CLKCONCMD &= ~0x47;              //设置系统主时钟频率为 32MHZ
}

void InitLed(void)
{
  P2DIR |= 0x01;
  P2_0   = 0;
}

void main(void)
{
  InitClockTo32M();
  
  InitLed();
  
  W25QXX_Init();
  IDTYPE = W25QXX_ReadID();//IDTYPE = 0xEF16

  while(1)
  {
    //W25Q64读写测试,数据从data写入flash地址,等亮,从flash读取数据放到copy,可以通过电脑串口助手查看串口打印出来的数据
    W25QXX_Write_Page(string,FLASH_SIZE,DATA_AMOUNT);//W25QXX_Read_Byte
    LED = ~LED;
    halMcuWaitMs(1000);
    W25QXX_Read(copy,FLASH_SIZE,DATA_AMOUNT);//W25QXX_Read_Byte
    LED = ~LED;
    halMcuWaitMs(1000);
  }
}

2.W25Q64.c

#define  SPI_DMA


//SPI在一页(0~65535)内写入少于256个字节的数据
//在指定地址开始写入最大256字节的数据
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit或者32bit)
//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!	 
void W25QXX_Write_Page(uint8* pBuffer,uint32 WriteAddr,uint16 NumByteToWrite)
{
  W25QXX_Write_Enable();                  //SET WEL 
  W25QXX_Enable();                            //使能器件 
  SPI_ReadWriteByte(W25X_PageProgram);
#ifdef W25Q256                            //如果是【W25Q256】地址为4字节
  SPI_ReadWriteByte((uint8)((WriteAddr)>>24));//第4字节地址 
#endif
  SPI_ReadWriteByte((uint8)((WriteAddr)>>16));//发送24bit地址 ,//第3字节地址 
  SPI_ReadWriteByte((uint8)((WriteAddr)>>8)); //第2字节地址
  SPI_ReadWriteByte((uint8)WriteAddr);	       //第1字节地址
	

#ifdef  SPI_DMA
  SPI_DMA_TX(pBuffer,NumByteToWrite);
#else
  for(uint16 i=0;i<NumByteToWrite;i++)
  {
    SPI_ReadWriteByte(pBuffer[i]);
  }
#endif  

  W25QXX_Wait_Busy();					   //等待写入结束
  W25QXX_Disable();                            //取消片选 
} 

3.DMA配置

DMA_DESC __xdata dmaConfigTx;// DMA进入工作模式通道1

void NOPn(uint8 temp)
{
  for(uint8 i=0;i<temp;i++)
  {
    NOP();
  }
}

void DMA_Transmission(uint8 channel)
{
  //DMA进入工作模式通道0
  DMAARM |= (1<<channel);//为了任何DMA传输能够在该通道上发生,该位必须置1,对于非重复传输模式,一旦完成传送,该位自动清0
  //一个通道准备工作(即获得配置数据)的时间需要9个系统时钟
  NOPn(9);
  
  DMAIRQ = 0;              //清中断标志    
  
  //DMA通道0传送请求,即触发DMA传送
  DMAREQ |= (1<<channel);//设置为1,激活DMA通道0(与一个触发事件具有相同的效果),当DMA传输开始清除该位
  
  //等待DMA通道0传送完毕
  //for (; !(DMAIRQ & DMAIRQ_DMAIF0););//当DMA通道0传送完成,DMAIRQ:DMAIF1位置1,与上DMAIRQ_DMAIF1(0x01),取非后为0退出循环
  while(!(DMAIRQ&(1<<channel)));    //等待DMA通道0传输结束
  //清除中断标志
  DMAIRQ = ~(1<<channel);  
}

void SPI_DMA_TX(uint8 *tx_buf,uint16 NumByte)
{
  //测试DMA通道,DMA_TRIG_UTX1触发,data数据复制到X_U1DBUF,测试成功,DMA传输无误
  SET_WORD(dmaConfigTx.SRCADDRH, dmaConfigTx.SRCADDRL, tx_buf);//load address of the dma source
  SET_WORD(dmaConfigTx.DESTADDRH, dmaConfigTx.DESTADDRL, &X_U1DBUF);//load address of the dma distanation
  SET_WORD(dmaConfigTx.LENH, dmaConfigTx.LENL, NumByte); //LEN = nmax
  dmaConfigTx.VLEN = DMA_VLEN_USE_LEN; // Transfer number of bytes commanded by n
  dmaConfigTx.WORDSIZE = DMA_WORDSIZE_BYTE; // Each transfer is 8 bits
  dmaConfigTx.TRIG = DMA_TRIG_UTX1;//DMA_TRIG_UTX1;DMA_TRIG_NONE
  dmaConfigTx.TMODE = DMA_TMODE_SINGLE;// Transfer block of data (length len) after each DMA trigger//DMA_TMODE_SINGLE,DMA_TMODE_BLOCK
  dmaConfigTx.SRCINC = DMA_SRCINC_1; // Increase source addr. by 1 between transfers
  dmaConfigTx.DESTINC = DMA_DESTINC_0; // Keep the same dest. addr. for all transfers
  dmaConfigTx.IRQMASK = DMA_IRQMASK_DISABLE;
  dmaConfigTx.M8 = DMA_M8_USE_8_BITS; // Use all 8 bits of first byte in source data to determine the transfer count
  dmaConfigTx.PRIORITY = DMA_PRI_HIGH; // DMA memory access has high priority
  SET_WORD(DMA1CFGH, DMA1CFGL, &dmaConfigTx);
  DMAARM = ABORT;              //停止DMA所有通道进行传输
  DMA_Transmission(1);         //DMA进入工作模式通道1
}

4.仿真调试

 5.待解决:

问题1:读出来到数组的数据第一个是0,从第二个开始才是写入的数据。

问题2:DMA配置接收,接收不到数据,启动DMA前,发送一个空字节,只能读出来第一个地址的数据。

下一步:研读flash芯片数据手册,看是否是flash芯片本身的问题,只能发一读一?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值