搜索
bottom↓
回复: 38

stm32 spi dma 写flash第一字节写不进去

[复制链接]

出0入0汤圆

发表于 2014-10-29 14:20:03 | 显示全部楼层 |阅读模式
写flash 刚开始我用spi硬件方式读写是没有问题的,但是当我用spi dma 方式写,然后用硬件方式读,发现有错误!
比如我定义两个数组
u8 rvc[10];   
const u8 send[10] = {0x01,0x02,0x03.0x04,0x05,0x06,0x07,0x08,0x09,0x0a};
用dma写,然后用硬件读,然后打印发现
rvc[0] =0xff
rvc[1] =0x01
rvc[2] =0x02
rvc[3] =0x03
rvc[4] =0x04
rvc[5] =0x05
rvc[6] =0x06
rvc[7] =0x07
rvc[8] =0x08
rvc[9] =0x0a
就是往右移了一位,不知道是为什么,我之前怀凝是DMA字节对齐问题,但是查不出结果,想问一下,有哪位朋友是不是也遇到类似问题了,怎么解决的?
DMA相关写的部分程序:
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPI_MASTER_DR_Base;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)0;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 0xffff;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_InitStructure);

SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
DMA_ITConfig(DMA1_Channel3,DMA_IT_TC,ENABLE);

// NumByteToWrite<256
void Flash_WritePage(uint8_t* pBuffer, u32 WriteAddr, uint16_t NumByteToWrite)
{
            sFLASH_WriteEnable();
            sFLASH_WaitForWriteEnd();
            sFLASH_CS_LOW();
            sFLASH_SendByte(sFLASH_CMD_WRITE);
            sFLASH_SendByte((WriteAddr&0xFF0000)>>16);               
            sFLASH_SendByte((WriteAddr&0xFF00)>>8);
            sFLASH_SendByte(WriteAddr&0xFF);
//    if(NumByteToWrite>256)
//    {
//       NumByteToWrite=256;            
//    }
//    while(NumByteToWrite--)
//    {                                                                                                                                         
//      sFLASH_SendByte(*pBuffer);
//       pBuffer++;
//    }
           DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pBuffer;
            DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;   
            DMA_InitStructure.DMA_BufferSize = NumByteToWrite;  
        DMA_Init(DMA1_Channel3, &DMA_InitStructure);
        DMA_Cmd(DMA1_Channel3,ENABLE);
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2014-10-29 14:53:01 | 显示全部楼层
楼主,你应该试试简单扼DMA几个字节的搬运是否正确,先不要使用SPI,对寄存器简单走个吧搬运看看是否成功

出0入10汤圆

发表于 2014-10-29 15:06:35 | 显示全部楼层
我还没开始研究写,楼主读有没有问题?我读有问题,能帮忙解决一下吗
http://www.amobbs.com/thread-5601954-1-1.html

出0入0汤圆

 楼主| 发表于 2014-10-29 15:45:22 | 显示全部楼层
qufuta 发表于 2014-10-29 14:53
楼主,你应该试试简单扼DMA几个字节的搬运是否正确,先不要使用SPI,对寄存器简单走个吧搬运看看是否成功 ...

可以的,uart dma 和I2C dma我都调通了,就是这个spi遇到这种问题!

出0入0汤圆

发表于 2014-10-29 16:26:54 | 显示全部楼层
用示波器看看时序

出0入0汤圆

发表于 2014-10-29 16:29:01 | 显示全部楼层
写不进去很有可能是芯片坏了,

出0入0汤圆

 楼主| 发表于 2014-10-29 16:32:21 | 显示全部楼层
kuailekuaiming 发表于 2014-10-29 16:29
写不进去很有可能是芯片坏了,

用硬件方式是可以的!

出0入0汤圆

 楼主| 发表于 2014-10-29 16:54:09 | 显示全部楼层
比特 发表于 2014-10-29 16:26
用示波器看看时序

好像是第一字节没有了!

出0入0汤圆

 楼主| 发表于 2014-10-29 22:16:04 | 显示全部楼层
bias 发表于 2014-10-29 15:06
我还没开始研究写,楼主读有没有问题?我读有问题,能帮忙解决一下吗
http://www.amobbs.com/thre ...

读也有问题的,因为读的时候,必须用两个DMA的,一个写一个读!写搞不定呀

出0入0汤圆

发表于 2014-10-29 22:33:44 来自手机 | 显示全部楼层
bias 发表于 2014-10-29 15:06
我还没开始研究写,楼主读有没有问题?我读有问题,能帮忙解决一下吗
http://www.amobbs.com/thre ...

我那好像有读的代码,明天找找

出0入10汤圆

发表于 2014-10-30 08:40:16 | 显示全部楼层
ysu533 发表于 2014-10-29 22:33
我那好像有读的代码,明天找找

万分感谢

出0入0汤圆

发表于 2014-10-30 08:56:05 | 显示全部楼层



这代码不是我写的, 但是我测试过是能用的. 原出处是csdn上的一篇文章. 您可以是搜搜.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2014-10-30 09:37:13 | 显示全部楼层
ysu533 发表于 2014-10-30 08:56
这代码不是我写的, 但是我测试过是能用的. 原出处是csdn上的一篇文章. 您可以是搜搜. ...

您那有没有用DMA写的呀,貌似写的不正常,读也不正常的!

出0入0汤圆

发表于 2014-10-30 09:44:56 | 显示全部楼层
515999271 发表于 2014-10-30 09:37
您那有没有用DMA写的呀,貌似写的不正常,读也不正常的!

读不正常吗? 这个我记得读肯定是正常的. 写的, 我自己也写过, 应该不难的. 一会我有空的话, 找块板子调试下

出0入10汤圆

发表于 2014-10-30 10:06:31 | 显示全部楼层
ysu533 发表于 2014-10-30 09:44
读不正常吗? 这个我记得读肯定是正常的. 写的, 我自己也写过, 应该不难的. 一会我有空的话, 找块板子调试 ...

读的数据总是有误,我已经在启动dma读spi flash之前将spi1设置为RxOnly了。

出0入0汤圆

 楼主| 发表于 2014-10-30 10:19:03 | 显示全部楼层
ysu533 发表于 2014-10-30 09:44
读不正常吗? 这个我记得读肯定是正常的. 写的, 我自己也写过, 应该不难的. 一会我有空的话, 找块板子调试 ...

您那是不是用硬件的方式去写然后用DMA读是吧,还是都是用DMA读与写呀,我用硬件方式是正常的,加了DMA就不正常了,向右移了一位!对了,我用的FLASH是W25X16,如果方便的话发下SOURCE CODE到我邮箱:515999271@qq.com.谢谢!

出0入0汤圆

发表于 2014-10-30 10:56:13 | 显示全部楼层
本帖最后由 ysu533 于 2014-10-30 10:57 编辑
bias 发表于 2014-10-30 10:06
读的数据总是有误,我已经在启动dma读spi flash之前将spi1设置为RxOnly了。


读已经确认是正常的, 写还有问题

你看我的测试截图.


我已经人工检视全部256个数据是正确的. DMA写的代码, 现在没空调试. 现在我主要写PC程序. 我看看我晚上有时间整理下不.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入10汤圆

发表于 2014-10-30 12:04:24 | 显示全部楼层
我的读数据已经好了,我取消RxOnly模式了,还是按照全双工,用另外一个DMA通道不停写dummy byte.

出0入0汤圆

 楼主| 发表于 2014-10-30 12:34:59 | 显示全部楼层
bias 发表于 2014-10-30 12:04
我的读数据已经好了,我取消RxOnly模式了,还是按照全双工,用另外一个DMA通道不停写dummy byte.
...

你的写和读都是用DMA吗,能否共享一下代码呀!

出0入0汤圆

 楼主| 发表于 2014-10-30 12:35:54 | 显示全部楼层
bias 发表于 2014-10-30 12:04
我的读数据已经好了,我取消RxOnly模式了,还是按照全双工,用另外一个DMA通道不停写dummy byte.
...

共享下DMA那部分就好了!

出0入10汤圆

发表于 2014-10-30 13:09:28 | 显示全部楼层
515999271 发表于 2014-10-30 12:34
你的写和读都是用DMA吗,能否共享一下代码呀!

没有,我没有用dma写flash,我刚刚尝试了一下,不行,直接死循环,不知道哪儿设置问题

出0入0汤圆

 楼主| 发表于 2014-10-30 13:42:17 | 显示全部楼层
bias 发表于 2014-10-30 13:09
没有,我没有用dma写flash,我刚刚尝试了一下,不行,直接死循环,不知道哪儿设置问题

...

我的不会呀,就是错位,我发我的代码给你看看!#include "mcu_spi.h"
#include "stdio.h"

#define sFLASH_CS_LOW()      GPIO_ResetBits(GPIOA, GPIO_Pin_2)
#define sFLASH_CS_HIGH()      GPIO_SetBits(GPIOA, GPIO_Pin_2)

#define sFLASH_CMD_WRSR                0x01
#define sFLASH_CMD_WRITE         0x02  
#define sFLASH_CMD_READ                0x03
#define sFLASH_CMD_DISWR        0x04
#define sFLASH_CMD_RDSR                0X05
#define sFLASH_CMD_ENWR                0x06
#define sFLASH_DUMMY_BYTE        0xFF
#define sFLASH_CMD_BE                0xc7
#define sFLASH_CMD_SE                0xd8
#define sFLASH_CMD_RDID                0x9f

#define sFLASH_IDADDR                0x14

#define sFLASH_SPI_PAGESIZE        0x100 //one page 256 byte
#define sFLASH_W25X16_ID     0x3015

u8 Rvcbuf2[10];
u8 Sendbuf2[10]= {
0x01,0x02,0x03,0x04,
0x05,0x06,0x07,0x08,
0x09,0x0a
};
#define SPI_MASTER_DR_Base   0x4001300C       
DMA_InitTypeDef         DMA_InitStructure;

void SPI1_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|
        RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO|\
        RCC_APB2Periph_SPI1, ENABLE);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
          GPIO_Init(GPIOA , &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
          GPIO_Init(GPIOA, &GPIO_InitStructure);
        //spi enable pin
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
          GPIO_Init(GPIOA, &GPIO_InitStructure);


          DMA_DeInit(DMA1_Channel2);
          DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPI_MASTER_DR_Base;
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Rvcbuf2;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
          DMA_InitStructure.DMA_BufferSize = 0xffff;
          DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
          DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
          DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
          DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
          DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
          DMA_Init(DMA1_Channel2, &DMA_InitStructure);

            DMA_DeInit(DMA1_Channel3);  
            DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Sendbuf2;
            DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
            DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
            DMA_Init(DMA1_Channel3, &DMA_InitStructure);

        SPI_Cmd(SPI1, DISABLE);
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
          SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
          SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
          SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
          SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
          SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
          SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
          SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
          SPI_InitStructure.SPI_CRCPolynomial = 7;
          SPI_Init(SPI1, &SPI_InitStructure);
        SPI_Cmd(SPI1, ENABLE);

        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);

        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_Init(&NVIC_InitStructure);

          NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
          NVIC_Init(&NVIC_InitStructure);

        DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);
        DMA_ITConfig(DMA1_Channel3,DMA_IT_TC,ENABLE);

        DMA_Cmd(DMA1_Channel2, DISABLE);
        DMA_Cmd(DMA1_Channel3, DISABLE);
}

u8 sFLASH_SendByte(u8 dat)
{
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
        SPI_I2S_SendData(SPI1,dat);
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
        return SPI_I2S_ReceiveData(SPI1);
}

void sFLASH_WriteEnable(void)
{
  sFLASH_CS_LOW();

  sFLASH_SendByte(sFLASH_CMD_ENWR);

  sFLASH_CS_HIGH();
}

void sFLASH_WaitForWriteEnd(void)
{
  uint8_t flashstatus = 0;
  sFLASH_CS_LOW();

  sFLASH_SendByte(sFLASH_CMD_RDSR);
  do
  {
    flashstatus = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
  }
  while ((flashstatus & 0x01) == SET);
  sFLASH_CS_HIGH();
}

void Flash_WritePage(uint8_t* pBuffer, u32 WriteAddr, uint16_t NumByteToWrite)
{
    sFLASH_WriteEnable();
    sFLASH_WaitForWriteEnd();
    sFLASH_CS_LOW();
    sFLASH_SendByte(sFLASH_CMD_WRITE);
    sFLASH_SendByte((WriteAddr&0xFF0000)>>16);               
    sFLASH_SendByte((WriteAddr&0xFF00)>>8);
    sFLASH_SendByte(WriteAddr&0xFF);
//hard mode write
//    if(NumByteToWrite>256)
//    {
//       NumByteToWrite=256;            
//    }
//    while(NumByteToWrite--)
//    {                                                                                                                                         
//      sFLASH_SendByte(*pBuffer);
//       pBuffer++;
//    }
//DMA mode write
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pBuffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;   
    DMA_InitStructure.DMA_BufferSize = NumByteToWrite;  
    DMA_Init(DMA1_Channel3, &DMA_InitStructure);
    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
    DMA_Cmd(DMA1_Channel3,ENABLE);                                                          
}

u8 sFLASH_ReadByte(void)
{
  return (sFLASH_SendByte(sFLASH_DUMMY_BYTE));
}

//hard mode read
void sFLASH_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead)
{
          sFLASH_CS_LOW();

          sFLASH_SendByte(sFLASH_CMD_READ);

          sFLASH_SendByte((ReadAddr & 0xFF0000) >> 16);

          sFLASH_SendByte((ReadAddr& 0xFF00) >> 8);

          sFLASH_SendByte(ReadAddr & 0xFF);

          while (NumByteToRead--)
          {

                  *pBuffer++ = sFLASH_ReadByte();
          }
}

void  sFLASH_BulkErase(void)
{
    sFLASH_WriteEnable();
    sFLASH_WaitForWriteEnd();
    sFLASH_CS_LOW();
    sFLASH_SendByte(sFLASH_CMD_BE);               
    sFLASH_CS_HIGH();
    sFLASH_WaitForWriteEnd();
}

void DMA1_Channel2_IRQHandler(void)
{
       
        if(DMA_GetFlagStatus(DMA1_IT_TC2) != RESET)
        {
                DMA_ClearFlag(DMA1_IT_GL2);       
                DMA_Cmd(DMA1_Channel2, DISABLE);        }               
}

void DMA1_Channel3_IRQHandler(void)
{
       
        if(DMA_GetFlagStatus(DMA1_IT_TC3) != RESET)
        {
                DMA_ClearFlag(DMA1_IT_GL3);       
                DMA_Cmd(DMA1_Channel3, DISABLE);
        }               
}

void SPI_Flash_Check(void)
{
        Flash_WritePage((u8*)&Sendbuf2,0,10);   
        delay_ms(10);
        sFLASH_CS_HIGH();
        sFLASH_WaitForWriteEnd();
        sFLASH_ReadBuffer((u8*)&Rvcbuf2,0,10);
        delay_ms(100);
        LED_RED_FLASH();

        printf("Rvcbuf2[0]=: %x\n\n\n\n\n",Rvcbuf2[0]);
           printf("Rvcbuf2[1]=: %x\n\n\n\n\n",Rvcbuf2[1]);
        printf("Rvcbuf2[2]=: %x\n\n\n\n\n",Rvcbuf2[2]);
           printf("Rvcbuf2[3]=: %x\n\n\n\n\n",Rvcbuf2[3]);
        printf("Rvcbuf2[4]=: %x\n\n\n\n\n",Rvcbuf2[4]);
           printf("Rvcbuf2[5]=: %x\n\n\n\n\n",Rvcbuf2[5]);
        printf("Rvcbuf2[6]=: %x\n\n\n\n\n",Rvcbuf2[6]);
           printf("Rvcbuf2[7]=: %x\n\n\n\n\n",Rvcbuf2[7]);
        printf("Rvcbuf2[8]=: %x\n\n\n\n\n",Rvcbuf2[8]);
           printf("Rvcbuf2[9]=: %x\n\n\n\n\n",Rvcbuf2[9]);
}
打印信息:
rvc[0] =0xff
rvc[1] =0x01
rvc[2] =0x02
rvc[3] =0x03
rvc[4] =0x04
rvc[5] =0x05
rvc[6] =0x06
rvc[7] =0x07
rvc[8] =0x08
rvc[9] =0x0a
切换回硬件,不用DMA就正常了!






出0入10汤圆

发表于 2014-10-30 13:50:34 | 显示全部楼层
515999271 发表于 2014-10-30 13:42
我的不会呀,就是错位,我发我的代码给你看看!#include "mcu_spi.h"
#include "stdio.h"

void SPI_Flash_Write_DMA_Config(uint8_t *pBuffer,uint16_t NumByteToWrite)
{
        DMA_InitTypeDef DMA_InitStructure;
       
        DMA_DeInit(DMA1_Channel3);
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DR;
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pBuffer;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_BufferSize = NumByteToWrite;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel3, &DMA_InitStructure);

        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
}

void SPI_Flash_Write_DMA(uint8_t *pBuffer,uint16_t NumByteToWrite)
{
        SPI_Flash_Write_DMA_Config(pBuffer,NumByteToWrite);
        DMA_Cmd(DMA1_Channel3, ENABLE);
        while(DMA_GetITStatus(DMA1_IT_TC3) == RESET);
        DMA_ClearITPendingBit(DMA1_IT_TC3);
}




void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
        /* Enable the write access to the FLASH */
        SPI_FLASH_WriteEnable();

        /* Select the FLASH: Chip Select low */
        SPI_FLASH_CS_LOW();
        /* Send "Write to Memory " instruction */
        SPI_FLASH_SendByte(W25X_PageProgram);
        /* Send WriteAddr high nibble address byte to write to */
        SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
        /* Send WriteAddr medium nibble address byte to write to */
        SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
        /* Send WriteAddr low nibble address byte to write to */
        SPI_FLASH_SendByte(WriteAddr & 0xFF);

        if(NumByteToWrite > SPI_FLASH_PerWritePageSize)
        {
                NumByteToWrite = SPI_FLASH_PerWritePageSize;
                //printf("\n\r Err: SPI_FLASH_PageWrite too large!");
        }


#ifdef USE_DMA_WRITE_FLASH
        SPI_Flash_Write_DMA(pBuffer,NumByteToWrite);                //这里不行,卡在这里,所以写我还没有实现
#else
        //如果不用DMA则使用下面的代码
        /* while there is data to be written on the FLASH */
        while (NumByteToWrite--)
        {
                /* Send the current byte */
                SPI_FLASH_SendByte(*pBuffer);
                /* Point on the next byte to be written */
                pBuffer++;
        }
#endif

        /* Deselect the FLASH: Chip Select high */
        SPI_FLASH_CS_HIGH();

        /* Wait the end of Flash writing */
        SPI_FLASH_WaitForWriteEnd();
}

出0入0汤圆

发表于 2014-10-30 13:54:28 | 显示全部楼层
mark 一下,正在研究 W25Q64。

出0入0汤圆

 楼主| 发表于 2014-10-30 15:01:20 | 显示全部楼层
bias 发表于 2014-10-30 13:50
void SPI_Flash_Write_DMA_Config(uint8_t *pBuffer,uint16_t NumByteToWrite)
{
        DMA_InitTypeDef DMA_I ...

你都没有开DMA中断,应该是这while(DMA_GetITStatus(DMA1_IT_TC3) == RESET);有问题吧
你用while(!DMA_GetFlagStatus(DMA1_FLAG_TC3));把它换掉试试!
我这边读可以了,但是写不会死掉,就是第一个还是写不进去的!

出0入10汤圆

发表于 2014-10-30 15:04:27 | 显示全部楼层
515999271 发表于 2014-10-30 15:01
你都没有开DMA中断,应该是这while(DMA_GetITStatus(DMA1_IT_TC3) == RESET);有问题吧
你用while(!DMA_G ...

只是没有使能中断,CPU不会响应吧,中断信号还是置位了,不是吗?难道我理解错了?

出0入0汤圆

 楼主| 发表于 2014-10-30 15:06:35 | 显示全部楼层
bias 发表于 2014-10-30 15:04
只是没有使能中断,CPU不会响应吧,中断信号还是置位了,不是吗?难道我理解错了?
...

你先试一下吧!

出0入10汤圆

发表于 2014-10-30 15:48:45 | 显示全部楼层

void SPI_Flash_Write_DMA(uint8_t *pBuffer,uint16_t NumByteToWrite)
{
        SPI_Flash_Write_DMA_Config(pBuffer,NumByteToWrite);
        LED4 = 0;
        DMA_Cmd(DMA1_Channel3, ENABLE);
        //while(DMA_GetITStatus(DMA1_IT_TC3) == RESET);
        //while(DMA_GetFlagStatus(DMA1_IT_TC3) == RESET);
        while(!DMA_GetFlagStatus(DMA1_FLAG_TC3));
        LED4 = 1;
        DMA_ClearITPendingBit(DMA1_IT_TC3);
}

都不行,确实就是LED4=0亮了,不灭,还是卡在这里...

出0入10汤圆

发表于 2014-10-30 16:06:06 | 显示全部楼层

楼主我的程序没有问题,写入正常,我漏掉了时钟
        /*开启DMA时钟*/
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

加上就ok了,写入的数据没有问题,DMA配置就是上面的程序,加一条时钟即可.

出0入0汤圆

 楼主| 发表于 2014-10-30 16:09:46 | 显示全部楼层
bias 发表于 2014-10-30 16:06
楼主我的程序没有问题,写入正常,我漏掉了时钟
        /*开启DMA时钟*/
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph ...

能发过来一下吗,关于写的部分!

出0入10汤圆

发表于 2014-10-30 16:12:02 | 显示全部楼层
本帖最后由 bias 于 2014-10-30 16:13 编辑

#define USE_DMA_WRITE_FLASH

#ifdef USE_DMA_WRITE_FLASH

/************************************************* DMA 写入 Flash 配置Start ********************************************/
void SPI_Flash_Write_DMA_Config(uint8_t *pBuffer,uint16_t NumByteToWrite)
{
        DMA_InitTypeDef DMA_InitStructure;
       
        /*开启DMA时钟*/
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
       
        DMA_DeInit(DMA1_Channel3);
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DR;
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pBuffer;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_BufferSize = NumByteToWrite;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel3, &DMA_InitStructure);
        //DMA_Cmd (DMA1_Channel3,ENABLE);
        /*使能DMA的中断相应,DMA发送完成后产生中断,不管是否使能,对应通道的DMA_IT_TC都会置位,但是需要使能后CPU才会去响应DMA的中断*/
        //DMA_ITConfig(DMA1_Channel3,DMA_IT_TC,ENABLE);

        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
}

void SPI_Flash_Write_DMA(uint8_t *pBuffer,uint16_t NumByteToWrite)
{
        SPI_Flash_Write_DMA_Config(pBuffer,NumByteToWrite);
        LED4 = 0;
        DMA_Cmd(DMA1_Channel3, ENABLE);
        while(DMA_GetITStatus(DMA1_IT_TC3) == RESET);
        //while(DMA_GetFlagStatus(DMA1_IT_TC3) == RESET);
        LED4 = 1;
        DMA_ClearITPendingBit(DMA1_IT_TC3);
}
/************************************************* DMA 写入 Flash 配置END *********************************************/
#endif

/*******************************************************************************
* Function Name  : SPI_FLASH_Init
* Description    : Initializes the peripherals used by the SPI FLASH driver.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_Init(void)
{
        SPI_InitTypeDef  SPI_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;

        /* Enable SPI1 and GPIO clocks */
        /*!< SPI_FLASH_SPI_CS_GPIO, SPI_FLASH_SPI_MOSI_GPIO,
             SPI_FLASH_SPI_MISO_GPIO, SPI_FLASH_SPI_DETECT_GPIO
             and SPI_FLASH_SPI_SCK_GPIO Periph clock enable */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        /*!< SPI_FLASH_SPI Periph clock enable */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);


        /*!< Configure SPI_FLASH_SPI pins: SCK */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        /*!< Configure SPI_FLASH_SPI pins: MISO */
        //当设置SPI1为主模式的时候,MISO为AF输入,则此处设置的AF PP输出是无效的
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        /*!< Configure SPI_FLASH_SPI pins: MOSI */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        /*!< Configure SPI_FLASH_SPI_CS_PIN pin: SPI_FLASH Card CS pin */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        /* Deselect the FLASH: Chip Select high */
        SPI_FLASH_CS_HIGH();
       
        /* SPI1 configuration */
        // W25X16: data input on the DIO pin is sampled on the rising edge of the CLK.
        // Data on the DO and DIO pins are clocked out on the falling edge of CLK.
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;        //SPI设置为双线双向全双工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                                                //设置为主SPI
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                                        //SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                                                        //时钟悬空高
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                                                //数据捕获于第二个时钟沿(mode 3)
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                                        //内部NSS信号由SSI位控制,这里做GPIO功能用
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;        //SPI速度,72/4=18M,根据不同FLASh速度来设置,有些Flash最大33M,有些最大50M
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                        //MSB在前
        SPI_InitStructure.SPI_CRCPolynomial = 7;                                                        //CRC校验(未启用,在别的地方启用)
        SPI_Init(SPI1, &SPI_InitStructure);

        /* Enable SPI1  */
        SPI_Cmd(SPI1, ENABLE);
}

/*******************************************************************************
* Function Name  : SPI_FLASH_PageWrite  页面编程
* Description    : Writes more than one byte to the FLASH with a single WRITE
*                  cycle(Page WRITE sequence). The number of byte can't exceed
*                  the FLASH page size.
* Input          : - pBuffer : pointer to the buffer  containing the data to be
*                    written to the FLASH.
*                  - WriteAddr : FLASH's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the FLASH,
*                    must be equal or less than "SPI_FLASH_PageSize" value.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
        /* Enable the write access to the FLASH */
        SPI_FLASH_WriteEnable();

        /* Select the FLASH: Chip Select low */
        SPI_FLASH_CS_LOW();
        /* Send "Write to Memory " instruction */
        SPI_FLASH_SendByte(W25X_PageProgram);
        /* Send WriteAddr high nibble address byte to write to */
        SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
        /* Send WriteAddr medium nibble address byte to write to */
        SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
        /* Send WriteAddr low nibble address byte to write to */
        SPI_FLASH_SendByte(WriteAddr & 0xFF);

        if(NumByteToWrite > SPI_FLASH_PerWritePageSize)
        {
                NumByteToWrite = SPI_FLASH_PerWritePageSize;
                //printf("\n\r Err: SPI_FLASH_PageWrite too large!");
        }


#ifdef USE_DMA_WRITE_FLASH
        SPI_Flash_Write_DMA(pBuffer,NumByteToWrite);
#else
        //如果不用DMA则使用下面的代码
        /* while there is data to be written on the FLASH */
        while (NumByteToWrite--)
        {
                /* Send the current byte */
                SPI_FLASH_SendByte(*pBuffer);
                /* Point on the next byte to be written */
                pBuffer++;
        }
#endif

        /* Deselect the FLASH: Chip Select high */
        SPI_FLASH_CS_HIGH();

        /* Wait the end of Flash writing */
        SPI_FLASH_WaitForWriteEnd();
}

出0入0汤圆

 楼主| 发表于 2014-10-30 17:31:24 | 显示全部楼层
bias 发表于 2014-10-30 16:12
#define USE_DMA_WRITE_FLASH

#ifdef USE_DMA_WRITE_FLASH

写可以了,谢谢!
单 独的写或读都可以了,我都用中断来写,要不然DMA就失去意义了!但是如果我用DMA写了之后再用DMA去读也有问题!

出0入0汤圆

 楼主| 发表于 2014-10-30 17:47:41 | 显示全部楼层
同时读写都可以了!看来在这发帖还真有点效果,谢谢各位大侠!

出0入10汤圆

发表于 2014-10-30 21:19:01 | 显示全部楼层
515999271 发表于 2014-10-30 17:31
写可以了,谢谢!
单 独的写或读都可以了,我都用中断来写,要不然DMA就失去意义了!但是如果我用DMA写了 ...

同时读写肯定没问题,我主要是想用来下载bin到flash结果我发现,如果不采用2缓冲区来实现,下载速度都只在7k/s左右,意义不大,主要是写flash的时候要考虑跨页编程

出0入0汤圆

 楼主| 发表于 2014-10-31 10:11:58 | 显示全部楼层
bias 发表于 2014-10-30 21:19
同时读写肯定没问题,我主要是想用来下载bin到flash结果我发现,如果不采用2缓冲区来实现,下载速度都只 ...

是呀Flash是要按页写,我测了一下,好像写完一页还要延时一下,还要读取状态位才能正常写入下一页的!读回来的数据才是正常的!
您说用bin文件下载到Flash,采用双缓冲区,为什么要双缓冲呀!?

出0入0汤圆

发表于 2016-8-16 21:53:48 | 显示全部楼层
515999271 发表于 2014-10-30 17:31
写可以了,谢谢!
单 独的写或读都可以了,我都用中断来写,要不然DMA就失去意义了!但是如果我用DMA写了 ...

不知楼主是否还上此坛,移植此部分代码发现会卡死在这里,不知是何原因,或是哪位有解决的方法,谢谢!
void SPI_Flash_Write_DMA(uint8_t *pBuffer,uint16_t NumByteToWrite)
{
        SPI_Flash_Write_DMA_Config(pBuffer,NumByteToWrite);
        LED4 = 0;
        DMA_Cmd(DMA1_Channel5, ENABLE);
        while(DMA_GetITStatus(DMA1_IT_TC5) == RESET);   //卡死在这里
        //while(DMA_GetFlagStatus(DMA1_IT_TC5) == RESET); //或是卡死在这里,上下两个结果相同
        LED4 = 1;
        DMA_ClearITPendingBit(DMA1_IT_TC5);
}

出0入0汤圆

发表于 2016-8-29 22:43:59 | 显示全部楼层
这个帖子对我有帮助 ,谢谢

出0入0汤圆

发表于 2016-8-30 09:27:10 | 显示全部楼层
同意二楼

出0入0汤圆

发表于 2017-1-24 13:33:20 | 显示全部楼层
515999271 发表于 2014-10-30 17:47
同时读写都可以了!看来在这发帖还真有点效果,谢谢各位大侠!

楼主方不方便放完整源代码?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-20 17:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表