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

关于STM32H7的SPI-DMA传输问题

[复制链接]
wenwutan 提问时间:2020-3-24 17:16 /
主芯片是 STM32H743X,SPI-FLASH是 W25Q256,使用HAL库(V1.8)。    如果SPI不使用DMA模式,则 W25Q256 数据读写正确。如果SPI使用DMA模式,则不正确,例如反复读取 W25Q256 的ID,只有第一次能正确读到,后续都只能读取到0。

    SPI初始化代码如下:
    spiFlash1Handle.Init.Mode = SPI_MODE_MASTER;          //设置SPI工作模式,设置为主模式
    spiFlash1Handle.Init.Direction = SPI_DIRECTION_2LINES;//设置SPI单向或者双向的数据模式:SPI设置为双线模式
    spiFlash1Handle.Init.DataSize = SPI_DATASIZE_8BIT;    //设置SPI的数据大小:SPI发送接收8位帧结构
    spiFlash1Handle.Init.CLKPolarity = SPI_POLARITY_LOW; //串行同步时钟的空闲状态为低电平 电路中下拉
    spiFlash1Handle.Init.CLKPhase = SPI_PHASE_1EDGE;      //串行同步时钟的第一个跳变沿(上升或下降)数据被采样
    spiFlash1Handle.Init.NSS = SPI_NSS_HARD_OUTPUT;       //NSS信号由软件管理
    spiFlash1Handle.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;//NSS信号脉冲失能
    spiFlash1Handle.Init.IOSwap = SPI_IO_SWAP_DISABLE;//SPI_IO_SWAP_ENABLE;
    spiFlash1Handle.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
    spiFlash1Handle.Init.MasterInterDataIdleness = SPI_MASTER_SS_IDLENESS_02CYCLE;
    spiFlash1Handle.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;  //SPI主模式IO状态保持使能
    spiFlash1Handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;//定义波特率预分频的值:波特率预分频值为64
    spiFlash1Handle.Init.FirstBit = SPI_FIRSTBIT_MSB;     //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
    spiFlash1Handle.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;      //1个字节的FIFO
    spiFlash1Handle.Init.TIMode = SPI_TIMODE_DISABLE;     //关闭TI模式
    spiFlash1Handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
    spiFlash1Handle.Init.CRCPolynomial = 7;               //CRC值计算的多项式


    经过几天的测试,发现是SPI模块的FIFO在作怪。在HAL库中,函数 HAL_SPI_TransmitReveive_DMA( ) 中操作过程是:配置RXDMA -> 设置 CFG1.RXDMAEN -> 配置TXDMA -> 设置 CFG1.TXDMAEN -> 设置 CR1.SPE -> 设置 CR1.CSTART。
    这个过程看起来没有错,但在实际运行时,到“设置 CFG1.TXDMAEN”后,对应DMA的 SR.HTIF 和 SR.TCIF 立即被置上,并进了相应的DMA完成中断。而此时“设置 CR1.SPE” 和 “设置 CR1.CSTART”都还没执行,MOSI、SCK上也没有波形输出,当执行完 “设置 CR1.CSTART”之后,时钟、数据才有波形输出,之后进入RXDMA完成中断。
    而到了第二次,同样的处理过程,到“设置 CFG1.TXDMAEN”后,会同时进TXDMA完成中断 和 RXDMA完成中断,导致接收到的数据全为0,因为此时并没有实际收发数据,执行完 “设置 CR1.CSTART”之后,数据才真正发送出去。
    根据以上现象,我的推测结果是,一设置 CFG1.TXDMAEN,SPI模块就会把Txduf中的数据搬到SPI的TXFIFO中,致使产生TXDMA完成中断,数据实际并没有被发出去,直到 “设置 CR1.CSTART”后,才开始将TXFIFO中的数据发送出去。之所以第二次及以后会同时产生TXDMA和RXDMA中断,是因为SPI的RXFIFO被SPI模块认为没读空(实际已经被DMA读走),RXFIFO显示内部有数据(SPI寄存器SR.RXWNE 和 RXPLVL不为0),使得后续只要一设置 CFG1.TXDMAEN,就发生RXDMA完成中断。
    根据猜测,进行了大于16字节(SPI模块FIFO的大小)的测试,发现使用DMA方式时,只能发送16字节的数据,例如DMA设置为40个字节,“设置 CFG1.TXDMAEN”后,对应DMA的 SR.HTIF 和 SR.TCIF 立即被置上,但 “设置 CR1.CSTART”后,MOSI和SCK上的波形,只有16个字节的宽度。
    无论我将FIFO阈值(CFG1.FTHVL)设置为多少,现象都是一样,CFG1.TXDMAEN之后,就会DMA数据传输到TXFIFO中,并且最多只能发16个字节。
    各位大神,有没有知道怎么解决这个问题,我想把SPI模块的FIFO禁止了,但没找到办法,资料没写,寄存器里也没有。

收藏 评论2 发布时间:2020-3-24 17:16

举报

2个回答
butterflyspring 回答时间:2020-4-17 17:02:38
不应该只能发送16个字节的,否则没法用了呀。官方有个例程,用DMA的,试试,可已发送的
STM32Cube_FW_H7_V1.7.0\Projects\NUCLEO-H743ZI\Examples\SPI\SPI_FullDuplex_ComDMA\EWARM
myspi 回答时间:2020-9-22 11:08:36
你好,楼主,我最近调试这个发现了跟你一模一样的问题,请问一下你那边问题解决了吗

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版