
近期在做CH376的驱动,由于官方提供了参考手册,和驱动程序,在稍加移植后测试了简单的U盘读写函数,获取设备信息等功能并测试了读取文件的速度。由于之前移植了FATFS读写SD卡,想对比一下二者读写速度如何,于是采用内部RTC测时间加UART输出结果的方式测量了一下读文件的速度,测试结果CH376读取U盘速度约260KB/s(采用SPI接口,时钟为18MHz),SPI读取SD卡11M的MP3文件约330KB/s左右(SPI时钟为18MHz),后来优化了一下读SD卡的函数,速度提升390KB/s。可还是觉得速度不够快,于是考虑用DMA方式读取。好了,上面废话了那么多,下面进入正题。2 K5 o+ |) i0 P. }4 B5 W; q SPI既可以用工作于DMA发送方式,也可以工作于DMA接收方式。SPI 采用DMA发送时一般没什么问题,然而接收时则出问题了。虽然都配置好了SPI_RX的DMA通道,也将SPI->CR2里的RXDMAEN置位了,但始终接收不到SD卡的数据,程序始终在等待DMA传输完成位置位。虽然知道SPI只有在DR写入数据开始发送时才会输出时钟,但在做DMA接收时认为时钟是自动输出的,于是始终解决不了问题,后来在网上找了很久,终于找到一个帖子,里面说的情况跟我遇到的类似,从中了解到SPI在DMA接收时并没有时钟输出,后来想想,这种SPI DMA接收应该是工作在从机模式的吧,因为主机会发送时钟。如果需要工作在主机接收模式,则还是要靠写DR来发送时钟,为此可以在开启接收DMA的同时开启发送DMA,并且接收DMA的优先级高于发送DMA,发送DMA配置为内存到外设,内存地址不自增,发送字节数与接收字节数相同,并且始终发送0xFF,这样发送通道的DMA每发送完一字节,RXNE置位,触发接收通道DMA,由于接收通道DMA优先级高于发送DMA,于是接收DMA接收一字节,而后TXE置位,又触发发送DMA,像这样循环,从而实现了SPI 的DMA连续接收数据。下面附上移植的FATFS里的rcvr_mmc()数据读函数:! _4 l$ L: s6 ~" F; G# X /*-----------------------------------------------------------------------*/ /* Receive bytes from the card (bitbanging) */: U% }% n3 m( f- n5 e6 w /*-----------------------------------------------------------------------*/ unsigned char g_SPIDMASEND=0xFF; static unsigned char DMA_Config_Flag=0;' z {3 z# s3 N8 G) l/ c static void rcvr_mmc (4 A5 j0 H6 H I) y9 b. Z BYTE *buff, /* Pointer to read buffer *// e% R* J5 G/ A- s7 P+ C UINT bc /* Number of bytes to receive */) S) i- S% j- m ) { if(bc>=50)7 S' ?/ {: r1 I1 o+ `# D1 Z {* B4 _+ |1 ?5 ~" d6 K if(DMA_Config_Flag==0) {% R. F5 p/ {* _( P' t8 m MYDMA_Config(DMA1_Channel4,(u32)&SPI2->DR,(u32)buff,bc,0x2080); //SPI2_DMA_RX MYDMA_Config(DMA1_Channel5,(u32)&SPI2->DR,(u32)&g_SPIDMASEND,bc,0x1010);//SPI2_DMA_TX DMA_Config_Flag=1; }4 e, z- o+ V$ Y/ E! Y5 {2 A9 I else {( v! f$ R3 p" d3 L. G( f! v DMA1_Channel4->CNDTR=bc;7 ~: ^1 Y3 n ^% x DMA1_Channel4->CMAR=(u32)buff;0 d B$ U4 x* s1 R DMA1_Channel5->CNDTR=bc;, f1 D1 w, S( e* @% f" A ]1 e/ U6 U, \ }$ L0 a0 p9 {1 e! |" ]) @ while((SPI2->SR&2)==0); SPI2->DR; SPI2->CR2|=3; //enable TXDMA,RXDMA MYDMA_Enable(DMA1_Channel4); MYDMA_Enable(DMA1_Channel5);* i, |' E% H( j% P) Q J: _ ////////////////////////////////////////////////////////# i" F( q: R0 i- M# ^: O! T. @ //参考 http://bbs.eeworld.com.cn/thread-250154-1-1.html //////////////////////////////////////////////////////// 7 N5 x4 _+ i- z/ ]6 a while(!(DMA1->ISR&(1DR=0xff; while((SPI2->SR&1)==0);5 H( W4 ~# [% U *buff++ = SPI2->DR; }# a8 _1 ]0 G- K! M: j# u }. j' u% k% s% C: Z5 d: a7 ]$ I" ] } 当读取数据小于50时采用非DMA读写,大于等于50采用DMA读写,以提高效率。这样改写后,再测试读取同一文件的速度达到696KB/s,相比之前提升了近3/4,DMA的速度果然够快。大家也可以尝试一下。 ![]() |
RE:关于SPI的DMA方式读写SD卡
回复:关于SPI的DMA方式读写SD卡
RE:关于SPI的DMA方式读写SD卡
回复:关于SPI的DMA方式读写SD卡
RE:关于SPI的DMA方式读写SD卡
回复:关于SPI的DMA方式读写SD卡
就需要这么一点程序吗 " h1 ~" k$ j3 O0 v6 u7 U' b7 x
& N3 c V" }9 l& V$ D4 h* [. L. Q; f
你好,最近我也在用CH376,也用DMA方式,能不能给个完整的程序,感激不尽啊!邮箱是:1373812024@qq.com
用野火的不行,换了安富莱的驱动就可以了