你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103+SPI FLASH 25Q 之16位SPI+DMA读写+模拟U盘

[复制链接]
歹徒兄弟 提问时间:2020-3-19 22:23 /
近来诸事不顺,做什么都磕磕绊绊,从来都没体验过一蹴而就的感觉。终于这个不走寻常路的我还是再次掉入泥坑。情况是这样的我想通过模拟U盘的方式直接向SPI FLASH写入一些相关的文件,如:字库和一些显示用的图片等。由于设置了2个盘符同时还可以通过U盘IAP升级固件岂不美哉。
奈何天公不作美,废了老大的劲才算搞定了IAP,接着又开始调试SPI的16位DMA读写.前后花了得有3天时间终于把SPI FLASH的16位DMA读写都调通了。在此说一下感想吧:DMA读SPI FLASH还是很简单的没什么特别要注意的地方,关键DMA写SPI FLASH有个地方一定要注意:在DMA传输完成后其实SPI并没有发完数据此时SPI正处于移位寄存器中正在往外发数据且寄存器DR中也还有一个数据待发,此时如果将CS脚拉高则会丢失这两个数据,并且W25Q也会丢弃前面发的数据而不会写入。解决方案是在DMA传输完成后增加SPI的两个标志位判断:
        while((SPI3->SR & SPI_I2S_FLAG_TXE) == (uint16_t)RESET || (SPI3->SR & SPI_I2S_FLAG_BSY) != (uint16_t)RESET){}

如此便能保证SPI数据的完整传输。
      经过单独测试后发现W25QXX FLASH已经可以正常读写了,于是接入USB模拟U盘无奈新的问题又出现了,单片机对W25QXX FLASH格式化后电脑可以正常识别但却不能通过电脑写入否则格式化的内容都会被破坏变成不能识别了,我有用逻辑分析仪看过电脑写入的数据发现完全是一堆乱码找不到任何规律(可能我的装备也不太行逻辑分析仪是100块钱的翻新货数据量一大就装死,而且抓电脑读写U盘的数据很凌乱,光修改个卷名的数据都多到看不过来),但奇怪的是如果采用轮询的8位SPI模式则电脑读写都正常模拟U盘可以正常读写。崩溃中,求高人指点。 Udisk.zip (538.91 KB, 下载次数: 68)
收藏 评论4 发布时间:2020-3-19 22:23

举报

4个回答
radio2radio 回答时间:2020-3-21 23:31:16
恰好我看到一个现成的,不一定对你有用:

http://github.com/dword1511/stm32-vserprog

http://github.com/dword1511/serprog-stm32vcp

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

STMWoodData 回答时间:2020-3-20 10:42:03
提示: 作者被禁止或删除 内容自动屏蔽
歹徒兄弟 回答时间:2020-3-20 17:56:38
流水源 发表于 2020-3-20 10:42
你试试在W25QXX FLASH写入函数里面打印写入的数据和写入地址看看。

感谢兄台回复,确实是个好提议我调试时都还没用过串口打印的方式
歹徒兄弟 回答时间:2020-3-21 20:23:12
跟大家说一声25Q系列FLASH的16位SPI读写今天总算调通了,感觉对模拟U盘的读写速度有所提升。最主要的好处是可以通过DMA直接将数据传给16位FSMC的LCD这是最让我兴奋的地方显示速度一下子提升数倍,并且连读写容器的缓存都不用了,还可以结合文件系统直接打开图片文件再也不用做内存搬运工了,这里其实有个问题:f_read在读文件的时候缓存指针一直在增加而此时如果指向我们的LCD写数据地址则指向的就不再是一个固定值,但只要每次读数据的地址范围不会太大让RS脚电平跳变就不会有问题,拿我的程序来说我用的是FSMC_A16脚做LCD的RS信号,定义LCD_REG为(0x60000000|0x1FFFE),LCD_RAM范围为0x60020000~0x6002FFFF或0x60000000~0x6000FFFF都可以正常显示。下面我把这段神奇的代码分享给大家:

void PrintPictureFile(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,const TCHAR* path)
{
        FIL fil;
        if (FR_OK==f_open(&fil,path,FA_READ|FA_OPEN_EXISTING))
        {
                UINT rbs=1,desire_size=(x2-x1)*(y2-y1)*2;
                LCD_SetWindows(x1,y1,x2-1,y2-1);
                for (uint32_t i=0;rbs!=0 && i<desire_size;i+=rbs)
                {
                        f_read(&fil,&LCD->LCD_RAM,FF_MAX_SS,&rbs);//簇最好设置大一点让单次读取的数据更多                                     }                                                                           //以减少循环寻址次数速度将更快,我的
                f_close(&fil);                                                          //簇是4096,扇区不要用512写文件会很慢
        }                                                                                   //改成4096速度可以提升好几倍
        else Print8x16String(x1,y1,RED,BLACK,"Error!");
}


美中不足的是写FLASH还是没能用上DMA原因不详,不知道这算不算是一种强迫症这个小遗憾曾让我寝食难安。下面我将贴上相关代码忘路过的大神帮忙分析一下:

void SFLASH_WritePage(uint16_t* pBuffer, uint32_t WriteAddr,uint16_t len)
{
        /* Write FLASH Page Use DMA:Start*/
        SFLASH_WriteEnable();len >>= 1;
        SPI3_CS_ENABLE;
        SPI3_WriteByte(SFLASH_WRITE_PAGE);
        SPI3_WriteByte((uint8_t)(WriteAddr>>16));
        SPI3_WriteByte((uint8_t)(WriteAddr>>8));
        SPI3_WriteByte((uint8_t)WriteAddr);
        DISABLE_SPI3;
        SPI3->CR1 |= SPI_DataSize_16b;
        ENABLE_SPI3;
        for(uint16_t i=0;i<len;i++)
        {
                while((SPI3->SR & SPI_I2S_FLAG_TXE) == RESET);
                SPI3->DR = *((u16*)pBuffer+i);
                while((SPI3->SR & SPI_I2S_FLAG_RXNE) == RESET);
                SPI3->DR;
        }
        //下面是DMA方式被我注释了,否则就会写入失败。但是我移植FATFS调用格式化函数“f_mkfs”采用下面的DMA写入又可以成功格式化,并且插上电脑后可以正常识别U盘。实在让人摸不着头脑了。
        /*SPI3->CR2 |= SPI_I2S_DMAReq_Tx;
        DMA2_Channel2->CCR &= ~(1<<0);
        DMA2->IFCR |= (1<<5);
        DMA2_Channel2->CMAR = (uint32_t)pBuffer;
        DMA2_Channel2->CNDTR = 128;
        DMA2_Channel2->CCR |= (1<<0);
        ENABLE_SPI3;
        while((DMA2->ISR&(1<<5))==RESET){}
        DMA2_Channel2->CCR &= ~(1<<0);
        while((SPI3->SR & SPI_I2S_FLAG_TXE) == (uint16_t)RESET
                        || (SPI3->SR & SPI_I2S_FLAG_BSY) != (uint16_t)RESET){}
        *//* Write FLASH Page Use DMA:End*/
        SPI3_CS_DISABLE;
        ResetSPI3DataSize8b();
        SFLASH_WaitForNoBusy();
}
现在是只要采用了下面的DMA插上电脑后读可以只要有修改当时貌似都没问题,但你拔掉USB重新插入就又提示格式化了并且格式化后也会提示无法格式化。


关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版