如何设置DMA方式python读取txt指定行SPI上指定地址的数据到内存

【K60】在memory和SPI2之间使用DMA传数据,总是丢失数据! 求助!(已解决) - ARM Cortex-M系列产品 - 恩智浦技术社区
后使用快捷导航没有帐号?
查看: 3212|回复: 6
【K60】在memory和SPI2之间使用DMA传数据,总是丢失数据! 求助!(已解决)
该用户从未签到主题帖子积分
新手上路, 积分 18, 距离下一级还需 32 积分
新手上路, 积分 18, 距离下一级还需 32 积分
打算在内存和SPI2之间使用DMA,将内存中的数据通过DMA发送给SPI2,然后由SPI2发送出去。
将DMA和SPI2初始化之后,周期性地启动DMA(周期性调用dmaStart()函数)。
当前的问题是,每次启动DMA,只能够传输一小部分数据,相当大一部分数据会丢掉。按照代码中的设置,每次启动DMA,大概只有五分之一的数据DMA收到并发送了,一般最前面几个数据是正确的,后面便会丢失多个数据后有一个正确的数据被SPI2发送出去。我是通过逻辑分析仪来查看数据的。
芯片:MK60DN512VLQ10
开发环境:IAR 6.4 WORKBENCH,使用MQX的库twrk60d100m.
主要代码有SPI的初始化、DMA的初始化,以及DMA启动这几个函数。附在下文。
Void SPI_Init(void)
SPI_MemMapPtr BaseAdd = SPI2_BASE_PTR;
SIM_SCGC3 |= SIM_SCGC3_SPI2_MASK;
PORTD_PCR13 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK;//SOUT
PORTD_PCR12 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK;//SCK
SPI_MCR_REG(BaseAdd) = 0
| SPI_MCR_CLR_TXF_MASK
| SPI_MCR_CLR_RXF_MASK
| SPI_MCR_PCSIS_MASK
| SPI_MCR_HALT_MASK
//| SPI_MCR_CONT_SCKE_MASK //continuous clock.
| SPI_MCR_MSTR_MASK;
SPI_CTAR_REG(BaseAdd,0) = 0
| SPI_CTAR_DBR_MASK
| SPI_CTAR_FMSZ(0x0F)
| SPI_CTAR_PDT_MASK//DELAY FACTOR IS 7
//| SPI_CTAR_PDT(0)
| SPI_CTAR_BR(0)
//| SPI_CTAR_CPOL_MASK
//| SPI_CTAR_CPHA_MASK
| SPI_CTAR_LSBFE_MASK
| SPI_CTAR_PBR(0);
SPI_SR_REG(BaseAdd) = SPI_SR_EOQF_MASK
//| SPI_SR_TFUF_MASK
| SPI_SR_TFFF_MASK
//| SPI_SR_RFOF_MASK
| SPI_SR_RFDF_MASK
SPI_RSER_REG(BaseAdd) = SPI_RSER_TFFF_RE_MASK | SPI_RSER_TFFF_DIRS_MASK
| SPI_RSER_RFDF_DIRS_MASK | SPI_RSER_RFDF_RE_MASK ;
SPI_MCR_REG(BaseAdd) &= ~SPI_MCR_HALT_MASK;
/*******************************
DMA的配置及初始化。
********************************/
void DMA_Init(void)
//时钟配置
SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;//打开DMA通道多路复用器时钟
SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;//打开DMA模块时钟
//通道配置,配置寄存器DMAMUX_CHCFG_REG:使能、触发、源设置
//通道有16个,源64个. 源21为SPI2发送。
DMAMUX_CHCFG5 = 0x00;//clear.
DMAMUX_CHCFG5 = DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_TRIG_MASK | DMAMUX_CHCFG_SOURCE(21);
//其他寄存器配置
DMA_CR = DMA_CR_EMLM_MASK | DMA_CR_CLM_MASK | DMA_CR_EDBG_MASK;//32位,CX(取消传输),EMLM(Enable minor loop mapping)
//DMA_ERQ = DMA_ERQ_ERQ5_MASK;//使能请求。enableDMA request n(0,1,2,。。。,15)。DMA相应通道的请求信号使能
DMA_CDNE = 0x05;//清除传输完成bit
DMA_CINT = 0x05;//清除中断
DMA_TCD5_SADDR = (uint32)memForDMA1; //4 bytes.
DMA_TCD5_SOFF = 4; //源地址每次4个字节的偏移
DMA_TCD5_ATTR = DMA_ATTR_SSIZE(2) | DMA_ATTR_DSIZE(2); //传输宽度8 bits, 16 bits,32 bits,对应着0,1,2
DMA_TCD5_DADDR = (uint32)SPI2_BASE_PTR + 0x; //PUSHR寄存器地址0x400AC034u。
DMA_TCD5_DOFF = 0;//目的地址要一直保持不变(PUSHR的地址)。
DMA_TCD5_DLASTSGA = 0; //最后一个地址后的目的地址处理。
DMA_TCD5_CSR = DMA_CSR_INTMAJOR_MASK; //major loop 完成后,产生一个中断。[ACTIVE][START][DONE][INT_MAJ][INT_HALF]
//添加DMA_CSR_BWC(2)后,每屏传到SPI上的数据增加了一些。
//添加DMA_CSR_INTHALF_MASK后似乎无影响。用于PING-PING buffer。
//DREQ bit is SET,then 主迭代完成时将ERQ位清零。
DMA_TCD5_CSR |= DMA_CSR_BWC(1) | DMA_CSR_DREQ_MASK;
//Minor loop mapping is enabled(CR[EMLM]=1) & Minor loop offset enabled(SMLOE or DMLOE=1)
DMA_TCD5_NBYTES_MLOFFYES = 1024;;//
DMA_TCD5_CITER_ELINKNO = 4; //current major interation count.当前主迭代剩余次数。
DMA_TCD5_BITER_ELINKNO = 4; //starting major interation count.与上一个变量的数值时钟相等。主迭代次数。
DMA_TCD5_SLAST = -4096; //到最后一个minor loop后的源地址处理处理
void DMA_Load(void)
DMAMUX_CHCFG5 &= ~DMAMUX_CHCFG_ENBL_MASK;//clear the ENBL bit.
DMAMUX_CHCFG5 |= DMAMUX_CHCFG_ENBL_MASK;
DMA_TCD5_CSR |= DMA_CSR_START_MASK;//(Should be written last after all other fields have been initialized)
Void dmaStart(void)
SPI_MemMapPtr BaseAdd = SPI2_BASE_PTR;
SPI_SR_REG(BaseAdd) = (SPI_SR_EOQF_MASK
| SPI_SR_TFUF_MASK
| SPI_SR_TFFF_MASK
| SPI_SR_RFOF_MASK
| SPI_SR_RFDF_MASK
SPI_MCR_REG(BaseAdd) |= SPI_MCR_CLR_RXF_MASK
| SPI_MCR_CLR_TXF_MASK;
DMA_Load();
该用户从未签到主题帖子积分
新手上路, 积分 18, 距离下一级还需 32 积分
新手上路, 积分 18, 距离下一级还需 32 积分
RE:【K60】在memory和SPI2之间使用DMA传数据,总是丢失数据! 求助!
希望各位大神小神多帮帮忙,我保证在问题解决后,将答案在这里公布出来。
该用户从未签到主题帖子积分
回复:【K60】在memory和SPI2之间使用DMA传数据,总是丢失数据! 求助!
回复第 2 楼 于 15:18:06发表:
希望各位大神小神多帮帮忙,我保证在问题解决后,将答案在这里公布出来。
给你一个K系列的DMA例程,你可以对照检查一下,还有问题在论坛中讨论。
(201.08 KB, 下载次数: 117)
10:56 上传
点击文件名下载附件
该用户从未签到主题帖子积分
新手上路, 积分 18, 距离下一级还需 32 积分
新手上路, 积分 18, 距离下一级还需 32 积分
RE:【K60】在memory和SPI2之间使用DMA传数据,总是丢失数据! 求助!
谢谢,我下下来看看。在内存与内存之间使用DMA是没有问题的。
该用户从未签到主题帖子积分
RE:【K60】在memory和SPI2之间使用DMA传数据,总是丢失数据! 求助!
好的,有问题再交流!!
该用户从未签到主题帖子积分
回复:【K60】在memory和SPI2之间使用DMA传数据,总是丢失数据! 求助!
你可以参考以下120MHz主频的spi例程。
这是最近更新的一篇中文例程,你可以参考下:
该用户从未签到主题帖子积分
注册会员, 积分 83, 距离下一级还需 117 积分
注册会员, 积分 83, 距离下一级还需 117 积分
回复:【K60】在memory和SPI2之间使用DMA传数据,总是丢失数据! 求助!(已解决)
解决了吗?这个东西寄存器好多的样子
站长推荐 /3
NXP官方IDH的米尔电子隆重推出的NXP i.MX6ULL系列开发板,只要你的想法足够优秀,你的创意足够新鲜,就来免费申请你的开发板吧!将项目帖分享到论坛中,更有机会获得500京东券的创意奖!
φ(>ω<*) 金豆是NXP社区于日发布的新币种,用户可通过回答问题帖、发布原创帖获取,每10枚金豆可兑换10元京东券一份( o ?ωo? )?
Cortex-M 从零开始学!经典图书免费下载,总有一本适合你?(^?^*)?(^?^*)(*^▽^*)
Tel: 3-8069
ICP经营许可证&&苏B2-&&&&苏州灵动帧格网络科技有限公司 版权所有.
Powered by以下试题来自:
单项选择题在DMA方式下,外设数据输入到内存的路径是()。
A.外设&CPU&DMAC&内存
B.外设&DMAC&内存
C.外设&存储器
D.外设&数据总线&存储器
为您推荐的考试题库
您可能感兴趣的试卷
你可能感兴趣的试题
A.上升沿触发
B.下降沿触发
C.高电平触发
D.低电平触发以下试题来自:
单项选择题在DMA方式下,数据从内存传送到外设经过的路径是______。A.内存→数据总线→外设 B.内存→DMAC→外设C.内存→CPU→总线→外设 D.外设→内存
为您推荐的考试题库
你可能感兴趣的试题
1A.3 B.2.5 C.2.4 D.22A.1/2 B.1/1024 C.1/65536 D.1/1310723A.200MB/s B.400MB/s C.600MB/s D.800MB/s4A.0x00FFFFE4 B.0x00FFFFE6 C.0x00FFFFEA D.0x00FFFFEC5A.Ⅰ和Ⅲ B.Ⅱ和Ⅲ C.Ⅰ和Ⅳ D.Ⅱ和Ⅳ
热门相关试卷
最新相关试卷spi在dma模式下读写sd卡==www.ic37.com
热门型号:
&&&当前位置:
spi在dma模式下读写sd卡
用户名:jynkelan
注册时间: 15:51:00
spi在dma模式下读写sd卡
请教大家,/****************************************************************************Desripton:readblockindmamodeFuctionname:ReadBlockInDMA()Input:NoneReturn:None*****************************************************************************/u8ReadBlockInDMA(u8*pBuffer,u32ReadAddr,u16NumByteToRead){//u32i=0;DMA_InitTypeDefDMA_InitSu8rvalue=MSD_RESPONSE_FAILURE;/*MSDchipselectlow*/MSD_CS_LOW();/*initialdmachannel2*/DMA_DeInit(DMA_Channel2);DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)SPI1_DR_ADMA_InitStructure.DMA_MemoryBaseAddr=(u32)pBDMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;DMA_InitStructure.DMA_BufferSize=NumByteToRDMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_DDMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_EDMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_BDMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_BDMA_InitStructure.DMA_Mode=DMA_Mode_NDMA_InitStructure.DMA_Priority=DMA_Priority_VeryHDMA_InitStructure.DMA_M2M=DMA_M2M_DDMA_Init(DMA_Channel2,&DMA_InitStructure);SPI_DMACmd(SPI1,SPI_DMAReq_Rx,ENABLE);/*SendCMD17(MSD_READ_SINGLE_BLOCK)toreadoneblock*/MSD_SendCmd(MSD_READ_SINGLE_BLOCK,ReadAddr,0xFF);if(!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)){/*Nowlookforthedatatokentosignifythestartofthedata*/if(!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)){DMA_Cmd(DMA_Channel2,ENABLE);while(!DMA_GetFlagStatus(DMA_FLAG_TC2)){}}}/*GetCRCbytes(notreallyneededbyus,butrequiredbyMSD)*/MSD_ReadByte();MSD_ReadByte();/*Setresponsevaluetosuccess*/rvalue=MSD_RESPONSE_NO_ERROR;DMA_Cmd(DMA_Channel2,DISABLE);/*MSDchipselecthigh*/MSD_CS_HIGH();/*Senddummybyte:8Clockpulsesofdelay*/MSD_WriteByte(DUMMY);/*Returnsthereponse*/}/******************************************************************************:WritebyteindmamodeFuctionname:WriteBlockInDMA(u8*pBuffer,u32WriteAddr,u16NumByteToWrite)Input:pBuffer--databufferforsendWriteAddr--addresstowriteNumByteToWrite--datalengthofthedatatowriteOutput:None*********************************************************************************/u8WriteBlockInDMA(u8*pBuffer,u32WriteAddr,u16NumByteToWrite){//u32i=0;DMA_InitTypeDefDMA_InitSu8rvalue=MSD_RESPONSE_FAILURE;/*MSDchipselectlow*/MSD_CS_LOW();/*initialthespi1inwritemode*//*initialdmachannel3*/DMA_DeInit(DMA_Channel3);DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)SPI1_DR_ADMA_InitStructure.DMA_MemoryBaseAddr=(u32)pBDMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;DMA_InitStructure.DMA_BufferSize=NumByteToWDMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_DDMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_EDMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_BDMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_BDMA_InitStructure.DMA_Mode=DMA_Mode_NDMA_InitStructure.DMA_Priority=DMA_Priority_HDMA_InitStructure.DMA_M2M=DMA_M2M_DDMA_Init(DMA_Channel3,&DMA_InitStructure);SPI_DMACmd(SPI1,SPI_DMAReq_Tx,ENABLE);//SPI_Cmd(SPI1,ENABLE);MSD_SendCmd(MSD_SET_BLOCKLEN,512,0x00);MSD_ReadByte();MSD_ReadByte();/*SendCMD24(MSD_WRITE_BLOCK)towritemultipleblock*/MSD_SendCmd(MSD_WRITE_BLOCK,WriteAddr,0xFF);/*CheckiftheMSDacknowledgedthewriteblockcommand:R1response(0x00:noerrors)*/if(!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)){/*Sendadummybyte*/MSD_WriteByte(DUMMY);/*Sendthedatatokentosignifythestartofthedata*/MSD_WriteByte(0xFE);/*WritetheblockdatatoMSD:writecountdatabyblock*/DMA_Cmd(DMA_Channel3,ENABLE);while(!DMA_GetFlagStatus(DMA_FLAG_TC3));/*PutCRCbytes(notreallyneededbyus,butrequiredbyMSD)*/MSD_ReadByte();MSD_ReadByte();/*Readdataresponse*/if(MSD_GetDataResponse()==MSD_DATA_OK){rvalue=MSD_RESPONSE_NO_ERROR;}}/*MSDchipselecthigh*/MSD_CS_HIGH();/*Senddummybyte:8Clockpulsesofdelay*/MSD_WriteByte(DUMMY);DMA_Cmd(DMA_Channel3,DISABLE);/*Returnsthereponse*/}这是分别用dma读写sd卡的读和写一个block的程序,在程序中调用到这俩个程序时,dma读子程序在while(!DMA_GetFlagStatus(DMA_FLAG_TC2)){}这一直等待,也就是说dma传输没有完成。而调用写子程序是完全没问题的,也就是dma时钟等问题以不是问题,不知道还有什么没考虑到的?????郁闷!!!!!
用户名:jynkelan
注册时间: 11:21:00
&帮主帮忙分析一下,是不是卡的响应时钟与DMA时钟匹配有问题????
用户名:jynkelan
注册时间: 14:40:00
&&难道是时钟同步问题?因为我们知道读sd卡时每从SPI总线上读一个字节的数据都要先进行时钟同步,这点从MSD_ReadByte()函数可以看出。也就是读一个字节数据前得向spi总线发数据0xff,这是必须的,如果省掉这一步,读数据是不能成功的。问题是不是出在这,也就是说当我们用dma来读SPI-&gtDR中的数据时,这是dma硬件并没有向spi总线发送同步信号,而在SPI-&gtDR中得不到正确的读数而导致dma读取不成功??
用户名:jynkelan
注册时间: 14:45:00
&而向sd卡写数据时并不需要额外的时钟同步,所以dma写能正确进行。
用户名:jynkelan
注册时间: 15:54:00
&看来我的理解还是有误,发0xff只是为了启动时钟clock,而实质上dma也是可以启动时钟的。。。。。。问题还是找不到啊。。。。
用户名:lidawei1
注册时间: 16:44:00
不发的话无时钟信号,怎么能收到?
用户名:jynkelan
注册时间: 12:46:00
&&&这个spi的dma应该硬件能开启时钟,也就是说DMA_Cmd(DMA_Channel2,ENABLE);后spi就会有时钟信号,但在我这事实却不是这样,开启dma通道2后spi1并没有时钟信号。????
用户名:lidawei1
注册时间: 19:09:00
SPI收发是同时进行的,共用一个时钟,主模式发时会开启时钟,收时不会,与DMA无关。DMA只是在接收缓冲区非空或发送缓冲区空时传数据。主模式SPI数据发送过程从“当一字节写进发送缓冲器时,发送过程开始”,即要启动主模式SPI传输,应有一字节写进发送缓冲器,对于发送的DMA操作,当设置好DMA后,因SPI的txe为1,故会触发DMA传一个字节到DR,此操作会开启主模式SPI的发送及接收过程,故“写子程序是完全没问题的”,但对于读操作,如果只设置读的DMA,因触发读DMA的条件是rxne为1,即必须接收缓冲区非空,此条件在只设置读DMA的情况下无法达到,因没有一个字节写进发送缓冲器,也就没有数据收到了,故出现“dma读子程序在while(!DMA_GetFlagStatus(DMA_FLAG_TC2)){}这一直等待”的情况,可见,要完成读DMA操作,也应先写数据到DR中,可通过同时开启另一个DMA通道用于SPI的发送来完成。
用户名:jynkelan
注册时间: 9:29:00
&&&&但这样的话也就是在DMA读时,如果我要连续读512字节,也得发512次0xff作为时钟信号。这样用dma还会有速度优势吗?&&
用户名:jynkelan
注册时间: 9:49:00
&&感谢10楼,程序修改如下,接受成功,但在11楼提到的问题还是可以继续讨论一下。/****************************************************************************Desripton&&&:read&block&in&dma&modeFuctionname&:ReadBlockInDMA()Input&&&&&&&&:NoneReturn&&&&&&:None*****************************************************************************/u8&ReadBlockInDMA(u8&*pBuffer,&u32&ReadAddr,&u16&NumByteToRead){&&&&u32&i&=&0;&&&&DMA_InitTypeDef&&DMA_InitS&&&&u8&rvalue&=&MSD_RESPONSE_FAILURE;&&&&&&/*&MSD&chip&select&low&*/&&&&MSD_CS_LOW();&&&&&&&&/*initial&dma&channel&2*/&&&&DMA_DeInit(DMA_Channel2);&&&&DMA_InitStructure.DMA_PeripheralBaseAddr&=&(u32)SPI1_DR_A&&&&DMA_InitStructure.DMA_MemoryBaseAddr&=&(u32)pB&&&&DMA_InitStructure.DMA_DIR&=&DMA_DIR_PeripheralSRC;&&&&DMA_InitStructure.DMA_BufferSize&=&NumByteToR&&&&DMA_InitStructure.DMA_PeripheralInc&=&DMA_PeripheralInc_D&&&&DMA_InitStructure.DMA_MemoryInc&=&DMA_MemoryInc_E&&&&DMA_InitStructure.DMA_PeripheralDataSize&=&DMA_PeripheralDataSize_B&&&&DMA_InitStructure.DMA_MemoryDataSize&=&DMA_MemoryDataSize_B&&&&DMA_InitStructure.DMA_Mode&=&DMA_Mode_N&&&&DMA_InitStructure.DMA_Priority&=&DMA_Priority_VeryH&&&&DMA_InitStructure.DMA_M2M&=&DMA_M2M_D&&&&DMA_Init(DMA_Channel2,&&DMA_InitStructure);&&&&&&&&&&&&SPI_DMACmd(SPI1,&SPI_DMAReq_Rx,&ENABLE);&&&&&&&/*&Send&CMD17&(MSD_READ_SINGLE_BLOCK)&to&read&one&block&*/&&&&&&&&&&&&MSD_SendCmd(MSD_READ_SINGLE_BLOCK,&ReadAddr,&0xFF);&&&&if&(!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))&&&&{&&&&/*&Now&look&for&the&data&token&to&signify&the&start&of&the&data&*/&&&&&&&&&&&&&&&&if&(!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&DMA_Cmd(DMA_Channel2,ENABLE);&&&&&&&&&&&&for(i=0&;i&ltNumByteToR&i++)&&&&&//发时钟信号,接收同时进&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//行&&&&&&&&&&&&{&&&&&&&&&&&&&&&&SPI1-&gtDR&=&0&&&&&&&&&&&&&&&&while(_SPI_GetFlagStatus(SPI1,SPI_FLAG_TXE)&==&RESET);&&&&&&&&&&&&&}&&&&&&&&&&&&while(!DMA_GetFlagStatus(DMA_FLAG_TC2))&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&}&&&&/*&Get&CRC&bytes&(not&really&needed&by&us,&but&required&by&MSD)&*/&&&&&&MSD_ReadByte();&&&&MSD_ReadByte();&&&&/*&Set&response&value&to&success&*/&&&&rvalue&=&MSD_RESPONSE_NO_ERROR;&&&&DMA_Cmd(DMA_Channel2,&DISABLE);&&&&/*&MSD&chip&select&high&*/&&&&MSD_CS_HIGH();&&&&/*&Send&dummy&byte:&8&Clock&pulses&of&delay&*/&&&&MSD_WriteByte(DUMMY);&&&&/*&Returns&the&reponse&*/&&&&return&}
用户名:lidawei1
注册时间: 15:56:00
使用DMA并不是为了获得速度,而是充分利用等待的空闲时间,所以我前面说再开启另一个DMA通道用于SPI的发送,发送的同时接收的DMA通道也在工作,完成数据的接收,不需CPU干预,CPU可完成其他任务。要说速度,我就算不用DMA,也照样可在约18026个CPU时钟周期内将512byte数据传到SD卡,或在17234(最快曾达到16401)个CPU时钟周期内将512byte数据从SD卡读到内存,此时速度约为512/(.049(m/s)、512/(.13(m/s),已非常接近2.25m/s的理论值。顺便说一下,SD卡的读写速度,除了与此处CPU与SD卡交换数据的速度有关外,还与以下2个操作密切相关:读时:&&&&/*&Now&look&for&the&data&token&to&signify&the&start&of&the&data&*/&&&if&(!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))写时:&&&&/*&Read&data&response&*/&&&&if&(MSD_GetDataResponse()&==&MSD_DATA_OK)此2操作花费的时间是惊人的,读时约需等10xxxCPU时钟,接近传512byte数据时间的2/3,写时约需等1xxxxx周期,是传512byte数据时间的10倍以上!仔细思考一下也是合理的,因写时会执行擦除操作,闪存的擦除时间是以ms计的。
用户名:jynkelan
注册时间: 18:19:00
&&楼上的说得很有道理,通过逻辑分析议抓数据后可以看到&&/*&Now&look&for&the&data&token&to&signify&the&start&of&the&data&*/&&&if&(!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))写时:&&&&/*&Read&data&response&*/&&&&if&(MSD_GetDataResponse()&==&MSD_DATA_OK)确实占用较长的时间,不过接近读512字节的2/3时间还得看不同的卡,但是如果在dma开启后有dma控制器产生时钟信号好像很合理吧,因为放开速度不说,这样在dma开启后还得靠cpu发512字节的时钟信号,这样的操作好像并没有节省多少cpu时间,只有在开启dma后由dma控制器主动发时钟信号,这样在读512字节的数据时完全可以不用cpu来干预,因而才能真正地达到用cpu来处理其它任务的目的,不知道芯片设计的时候是怎么考虑的,当然如果存在其它编程算法而不是像12楼上那种方法来实现那到是有可能的?
用户名:lidawei1
注册时间: 20:45:00
SPI发送时,开DMA通道2用于将数据从内存搬到DR,SPI接收时,开DMA通道3用于将数据从DR搬到内存,再开DMA通道2用于将DUMMY搬到DR,此2个DMA一开,数据便源源不断从SPI读入内存,不用CPU干预,更不用&&&&&&&&&&&&for(i=0&;i&ltNumByteToR&i++)&&&&&//发时钟信号,接收同时进&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//行&&&&&&&&&&&&{&&&&&&&&&&&&&&&&SPI1-&gtDR&=&0&&&&&&&&&&&&&&&&while(_SPI_GetFlagStatus(SPI1,SPI_FLAG_TXE)&==&RESET);&&&&&&&&&&&&&}
用户名:jynkelan
注册时间: 9:09:00
&&&就是收的时候并不是只开一个通道2,而是通道2和通道3一起开,发送则只开一个通道即可。
用户名:jynkelan
注册时间: 11:08:00
u8&ReadBlockInDMA(u8&*pBuffer,&u32&ReadAddr,&u16&NumByteToRead){&&&&//u32&i&=&0;&&&&//u16&j&=&0;&&&&&DMA_InitTypeDef&&DMA_InitS&&&&u8&rvalue&=&MSD_RESPONSE_FAILURE;&&&//&u16&*Enp1Addr&=&NULL;&&&/*断点1地址*/&&&&/*&MSD&chip&select&low&*/&&&&MSD_CS_LOW();&&&&&&&&/*initial&dma&channel&2*/&&&&DMA_DeInit(DMA_Channel2);&&&&DMA_DeInit(DMA_Channel3);&&&&DMA_InitStructure.DMA_PeripheralBaseAddr&=&(u32)SPI1_DR_A&&&&DMA_InitStructure.DMA_MemoryBaseAddr&=&(u32)pB&&&&DMA_InitStructure.DMA_DIR&=&DMA_DIR_PeripheralSRC;&&&&DMA_InitStructure.DMA_BufferSize&=&NumByteToR&&&&DMA_InitStructure.DMA_PeripheralInc&=&DMA_PeripheralInc_D&&&&DMA_InitStructure.DMA_MemoryInc&=&DMA_MemoryInc_E&&&&DMA_InitStructure.DMA_PeripheralDataSize&=&DMA_PeripheralDataSize_B&&&&DMA_InitStructure.DMA_MemoryDataSize&=&DMA_MemoryDataSize_B&&&&DMA_InitStructure.DMA_Mode&=&DMA_Mode_N&&&&DMA_InitStructure.DMA_Priority&=&DMA_Priority_VeryH&&&&DMA_InitStructure.DMA_M2M&=&DMA_M2M_D&&&&DMA_Init(DMA_Channel2,&&DMA_InitStructure);&&&&&&&&&&&&DMA_InitStructure.DMA_MemoryBaseAddr&=&(u32)DuumyC&&//512字节的dummy&&&&DMA_InitStructure.DMA_DIR&=&DMA_DIR_PeripheralDST;&&&&DMA_InitStructure.DMA_Priority&=&DMA_Priority_L&&&&DMA_Init(DMA_Channel3,&&DMA_InitStructure);&&&&SPI_DMACmd(SPI1,&SPI_DMAReq_Tx,&ENABLE);&&&&&&&SPI_DMACmd(SPI1,&SPI_DMAReq_Rx,&ENABLE);//&&&&DMA_ClearFlag(DMA_FLAG_TC2);&&&&&/*&Send&CMD17&(MSD_READ_SINGLE_BLOCK)&to&read&one&block&*/&&&&&&&&&&&&MSD_SendCmd(MSD_READ_SINGLE_BLOCK,&ReadAddr,&0xFF);&&&&if&(!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))&&&&{&&&&/*&Now&look&for&the&data&token&to&signify&the&start&of&the&data&*/&&&&&&&&&&&&&&&&if&(!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&DMA_Cmd(DMA_Channel3,ENABLE);&&&&&&&&&&&&&&&DMA_Cmd(DMA_Channel2,ENABLE);//&&&&&&&&&&&&&for(i=0;&i&ltNumByteToR&i++)//&&&&&&&&&&&&&{&&//&&&&&&&&&&&&&&&&//&&&&&&&&&&&&&&&&SPI1-&gtDR&=&DUMMY;//&&&&&&&&&&&&&&&&while((SPI1-&gtSR&SPI_FLAG_TXE)&==&(u16)RESET);&&&&&&&&&&&&&&&//&while(SPI_GetFlagStatus(SPI1,SPI_FLAG_TXE)&==&RESET);//&&&&&&&&&&&&&&&&while(SPI_GetFlagStatus(SPI1,SPI_FLAG_RXNE)&==&RESET)//&&&&&&&&&&&&&&&&{////&&&&&&&&&&&&&&&&}//&&&&&&&&&&&&&&&&*pBuffer&=&SPI1-&gtDR;//&&&&&&&&&&&&&&&&&pBuffer++;//&&&&&&&&&&&&&}//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&while(!DMA_GetFlagStatus(DMA_FLAG_TC3));&&&&&&&&&&&&&&&&&&&&&&&&while(!DMA_GetFlagStatus(DMA_FLAG_TC2));&&&&&&&&&&&&&&&&&&&&&&&&DMA_ClearFlag(DMA_FLAG_TC2);&&&&&&&&&}&&&&&&&&}&&&&/*&Get&CRC&bytes&(not&really&needed&by&us,&but&required&by&MSD)&*/&&&&&&MSD_ReadByte();&&&&MSD_ReadByte();&&&&/*&Set&response&value&to&success&*/&&&&rvalue&=&MSD_RESPONSE_NO_ERROR;&&&&DMA_Cmd(DMA_Channel2,&DISABLE);&&&&DMA_Cmd(DMA_Channel3,&DISABLE);&&&&/*&MSD&chip&select&high&*/&&&&MSD_CS_HIGH();&&&&/*&Send&dummy&byte:&8&Clock&pulses&of&delay&*/&&&&MSD_WriteByte(DUMMY);&&&&/*&Returns&the&reponse&*/&&&&return&}&优先级很重要,收应高于发。
用户名:lidawei1
注册时间: 12:04:00
无需512字节,设置为地址不增加
用户名:jynkelan
注册时间: 9:58:00
&&&对,这样简单一点,发送512次就行了,谢谢提醒!
用户名:ifree64
注册时间: 22:15:00
有一个问题请教:在代码中有while(!DMA_GetFlagStatus(DMA_FLAG_TC3));while(!DMA_GetFlagStatus(DMA_FLAG_TC2));两句,意思是DMA传输如果没有完成就继续等待。那么这样DMA的优势是否就没有体现出来呢?DMA的本意应该是把CPU从数据传输的忙等待中解放出来,可以腾出时间来做其他事情,但是如果向上面那样使用不是好像就和直接CPU忙等待读取一样了吗?因为while循环使得CPU还是在等着DMA传输完毕。不知道我说得对不对。是不是DMA要配合操作系统的任务管理加上阻塞才有它该有的性能优势呢?谢谢!
热门型号:

我要回帖

更多关于 python读取文件指定行 的文章

 

随机推荐