请选择 进入手机版 | 继续访问电脑版

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

关于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管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版