完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我的开发板上,STM32H7作为SPI主机需要频繁给FPGA发送数据,目前发现连续发送数据时,第一个数据没问题,第二个接收到的数据就出现了错位。其中,STM32H7的SPI配置如下:
/* config spi4 bus */ cfg.data_width = 8; cfg.max_hz = 20 * 1000 * 1000;//frequency<=20MHz cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_3 | RT_SPI_MSB; rt_spi_configure(spi4_device, &cfg); 采用了CPHA=1,CPOL=1的mode3模式,根据SPI的时序图,本应该为下面这样: 但是我用signaltap II捕捉后发现是下面这样: SCK引脚的时钟在传输完毕后没有及时拉高,一直是低电平。这样就会导致紧接着发送下一个数据时,FPGA会识别错位。 如果在两次发送之间加延时,比如10MS,那么问题可以解决,但是这样就拖慢了系统速度。 我想请问SCK引脚控制不是使用的ST官方的HAL库函数来控制的吗?因为如果是HAL库函数控制,我实验了一下,CS引脚拉高同时会把SCK也拉高的。目前这种情况,还有其他解决办法吗? |
|
相关推荐
4个回答
|
|
可以在drv_spi.c中先看下接口的具体实现,有没有对HAL部分存在使用错误的情况。
|
|
|
|
sck脉冲数量不对,还有许多毛刺,感觉像是引脚使用有冲突,其它地方也操作了sck的gpio引脚
|
|
|
|
那些不是毛刺,是波形图被压缩得太厉害了,所以看起来像。其实图里有48bits的数据传输,我没展开。
|
|
|
|
H7的spi驱动初始化函数, 看看是否有差异:
static rt_err_t stm32_spi_init(struct stm32_spi *spi_drv, struct rt_spi_configuration *cfg) { RT_ASSERT(spi_drv != RT_NULL); RT_ASSERT(cfg != RT_NULL); SPI_HandleTypeDef *spi_handle = &spi_drv->handle; if (cfg->mode & RT_SPI_SLAVE) { spi_handle->Init.Mode = SPI_MODE_SLAVE; } else { spi_handle->Init.Mode = SPI_MODE_MASTER; } if (cfg->mode & RT_SPI_3WIRE) { spi_handle->Init.Direction = SPI_DIRECTION_1LINE; } else { spi_handle->Init.Direction = SPI_DIRECTION_2LINES; } if (cfg->data_width == 8) { spi_handle->Init.DataSize = SPI_DATASIZE_8BIT; spi_handle->TxXferSize = 8; spi_handle->RxXferSize = 8; } else if (cfg->data_width == 16) { spi_handle->Init.DataSize = SPI_DATASIZE_16BIT; } else { return RT_EIO; } if (cfg->mode & RT_SPI_CPHA) { spi_handle->Init.CLKPhase = SPI_PHASE_2EDGE; } else { spi_handle->Init.CLKPhase = SPI_PHASE_1EDGE; } if (cfg->mode & RT_SPI_CPOL) { spi_handle->Init.CLKPolarity = SPI_POLARITY_HIGH; } else { spi_handle->Init.CLKPolarity = SPI_POLARITY_LOW; } if (cfg->mode & RT_SPI_NO_CS) { spi_handle->Init.NSS = SPI_NSS_SOFT; } else { spi_handle->Init.NSS = SPI_NSS_SOFT; } uint32_t SPI_APB_CLOCK; #if defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0) SPI_APB_CLOCK = HAL_RCC_GetPCLK1Freq(); #elif defined(SOC_SERIES_STM32H7) SPI_APB_CLOCK = HAL_RCC_GetSysClockFreq(); #else SPI_APB_CLOCK = HAL_RCC_GetPCLK2Freq(); #endif if (cfg->max_hz >= SPI_APB_CLOCK / 2) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; } else if (cfg->max_hz >= SPI_APB_CLOCK / 4) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; } else if (cfg->max_hz >= SPI_APB_CLOCK / 8) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; } else if (cfg->max_hz >= SPI_APB_CLOCK / 16) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; } else if (cfg->max_hz >= SPI_APB_CLOCK / 32) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; } else if (cfg->max_hz >= SPI_APB_CLOCK / 64) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; } else if (cfg->max_hz >= SPI_APB_CLOCK / 128) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; } else { /* min prescaler 256 */ spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; } LOG_D("sys freq: %d, pclk2 freq: %d, SPI limiting freq: %d, BaudRatePrescaler: %d", HAL_RCC_GetSysClockFreq(), SPI_APB_CLOCK, cfg->max_hz, spi_handle->Init.BaudRatePrescaler); if (cfg->mode & RT_SPI_MSB) { spi_handle->Init.FirstBit = SPI_FIRSTBIT_MSB; } else { spi_handle->Init.FirstBit = SPI_FIRSTBIT_LSB; } spi_handle->Init.TIMode = SPI_TIMODE_DISABLE; spi_handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; spi_handle->State = HAL_SPI_STATE_RESET; #if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32F0) spi_handle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE; #elif defined(SOC_SERIES_STM32H7) spi_handle->Init.Mode = SPI_MODE_MASTER; spi_handle->Init.NSS = SPI_NSS_SOFT; spi_handle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE; spi_handle->Init.NSSPolarity = SPI_NSS_POLARITY_LOW; spi_handle->Init.CRCPolynomial = 7; spi_handle->Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN; spi_handle->Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN; spi_handle->Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE; spi_handle->Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE; spi_handle->Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE; spi_handle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; spi_handle->Init.IOSwap = SPI_IO_SWAP_DISABLE; spi_handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA; #endif if (HAL_SPI_Init(spi_handle) != HAL_OK) { return RT_EIO; } #if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32G0) SET_BIT(spi_handle->Instance->CR2, SPI_RXFIFO_THRESHOLD_HF); #endif /* DMA configuration */ if (spi_drv->spi_dma_flag & SPI_USING_RX_DMA_FLAG) { HAL_DMA_Init(&spi_drv->dma.handle_rx); __HAL_LINKDMA(&spi_drv->handle, hdmarx, spi_drv->dma.handle_rx); /* NVIC configuration for DMA transfer complete interrupt */ HAL_NVIC_SetPriority(spi_drv->config->dma_rx->dma_irq, 0, 0); HAL_NVIC_EnableIRQ(spi_drv->config->dma_rx->dma_irq); } if (spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG) { HAL_DMA_Init(&spi_drv->dma.handle_tx); __HAL_LINKDMA(&spi_drv->handle, hdmatx, spi_drv->dma.handle_tx); /* NVIC configuration for DMA transfer complete interrupt */ HAL_NVIC_SetPriority(spi_drv->config->dma_tx->dma_irq, 0, 1); HAL_NVIC_EnableIRQ(spi_drv->config->dma_tx->dma_irq); } __HAL_SPI_ENABLE(spi_handle); LOG_D("%s init done", spi_drv->config->bus_name); return RT_EOK; } |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
786 浏览 0 评论
4210 浏览 0 评论
如何使用python调起UDE STK5.2进行下载自动化下载呢?
2520 浏览 0 评论
开启全新AI时代 智能嵌入式系统快速发展——“第六届国产嵌入式操作系统技术与产业发展论坛”圆满结束
2926 浏览 0 评论
获奖公布!2024 RT-Thread全球巡回线下培训火热来袭!报名提问有奖!
31442 浏览 11 评论
72894 浏览 21 评论
浏览过的版块 |
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 03:23 , Processed in 0.700911 second(s), Total 76, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号