作者 主题:STM32 - 使用SPI具有圆形DMA (Read 1516 times)

0会员和1位客人正在查看此主题。

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
STM32 - 使用SPI与圆形DMA
« on: 4月18日,2021年,07:23:49»
我想使用STM32F303从现有设备接收同步串行数据流。源设备提供

- 一个5 MHz时钟,总是活跃,
- 定期变高的选通信号,表示有效数据的突发(突发长度始终是恒定的),并且
- 二进制数据流,在门控信号期间是有效/相关的。

所以我以为我'd set up a "slave, RX only"SPI通道,其硬件NSS输入连接到我的门控信号。然后为此SPI通道配置圆形DMA,具有缓冲长度,其等于数据突发的长度。我希望只需要将其设置一次,然后保持运行,没有任何中断或需要重新启动SPI接收。

(该软件不需要在接收周期完成时的确切时间点。它可以简单地假设DMA内存缓冲区随时包含最近接收的数据突发。读取新的数据缓冲区突发接收也可以。)

第一个问题:这项工作可以像上面勾勒出来,或者我忽略/误解了什么?

我的第二个问题是指正确的DMA配置。我正在使用最新的Cubeide版本(1.6.1)与图形设备配置工具。已配置SPI1如上所述,将SPI1_RX DMA请求分配给DMA1,通道2,并要求具有自动递增存储器地址的循环缓冲区。我有代码生成设置以使用HAL驱动程序。

DMA的生成初始化代码如下所示。它建立了一个我不的中断'需要(并且可以简单地删除,假设我的一般概念是有意义的)。但它在哪里设置了循环缓冲操作的DMA,并且还需要做些什么来实际启用DMA?似乎奇怪的是图形配置工具似乎未使用的信息(循环缓冲区,自动增量步长)。应该自动生成更多代码吗?

或者,如果我需要手动添加它:究竟是怎么回事? hal_spi_receive_dma(spihandle,spibuffer,spi_buffer_size) 可能是我想要的 - 但我在哪里指定循环缓冲区(因此自动,连续操作)?必须需要其他一些呼叫来设置DMA?

感谢您通过长期阅读,谢谢任何有用的提示!

代码: [选择]
static void MX_DMA_Init(void)
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
}
 


 在线的 Siwastaja.

  • 超级贡献者
  • ***
  • 帖子:3718
  • 国家:  FI.
Re:STM32 - 使用圆形DMA的SPI
« 回复#2开: 4月18日,2021年,08:43:53»
你的方法在第一眼听起来就是正确的。问题看似是文库和自动化,声称更容易的东西,但显然使一切难以置信,因为没有他们,你'D在更短的时间内测试过这一点,而不是写论坛帖子。

所以打开参考手册。至于DMA,假设F303具有与F3,F4,F7,H7 MCU具有相同的DMA发动机,我已经使用(F0设备具有不同,甚至更简单的DMA),不多配置它:设置M0AR ,PAR,NDTR,CR,通过LIFCR清除中断标志,并通过CR启用通道。

代码: [选择]
DMA2_Stream1->M0AR = (uint32_t)&databuf[0];
DMA2_Stream1->PAR = (uint32_t)&SPIwhatever->RXDR;
DMA2_Stream1->NDTR = 1234;
DMA2_Stream1->CR = 0UL<<25 /* the channel number, see the table in refman*/ |
0b01UL<<16 /*med prio*/ | 0b01UL<<13 /*16-bit mem*/ | 0b01UL<<11 /*16-bit periph*/ |
1UL<<10 /*mem increment*/ | 0b00UL<<6 /*periph-to-mem*/ | 0b110 /*err interrupts*/ | 1UL<<8 /*circular*/;
DMA_CLEAR_INTFLAGS(DMA2, 1);
DMA2_Stream1->CR |= 1UL; // enable it!

dma_clear_intflags()是我创建的帮助程序:
代码: [选择]
#define DMA_CLEAR_INTFLAGS(_dma_, _stream_) do{                   \
if     ((_stream_) == 0) (_dma_)->LIFCR = 0b111101UL<<0;  \
else if((_stream_) == 1) (_dma_)->LIFCR = 0b111101UL<<6;  \
else if((_stream_) == 2) (_dma_)->LIFCR = 0b111101UL<<16; \
else if((_stream_) == 3) (_dma_)->LIFCR = 0b111101UL<<22; \
else if((_stream_) == 4) (_dma_)->HIFCR = 0b111101UL<<0;  \
else if((_stream_) == 5) (_dma_)->HIFCR = 0b111101UL<<6;  \
else if((_stream_) == 6) (_dma_)->HIFCR = 0b111101UL<<16; \
else if((_stream_) == 7) (_dma_)->HIFCR = 0b111101UL<<22; \
}while(0)

大学教师't forget to
*使时钟使DMA能够
*使时钟使SPI
*使用正确的AF编号设置替代函数模式的SPI引脚
*查找DMA CR寄存器的正确DMA通道号,将正确的SPI映射到DMA
*在外设中启用DMA模式位(在本例中,SPI)配置

至于SPI,大多数STM32设备仍然可容纳在它们处理硬件NCS的嘲笑。但是,如果您有真正的长度通信,并且不期待任何沟通错误,就像错过的时钟一样,它将起作用。对于可变长度消息(或强大的系统),使上升NCS重置SPI状态机,这是基础知识的基础,您需要通过exti,然后在该处理程序上编写通过升起的NCS触发的中断处理程序,通过RCC复位寄存器重置整个SPI外设!在最新的STM32型号上,它们已经半修复了此问题,以便您现在可以使用外设重置SPI'自己的启用位,仍然很长的路要走它对。

最后,STM32F303具有SPI FIFO。可能值得考虑不使用DMA,特别是如果您的通信数据包足够短,以完全适合SPI FIFO。在这种情况下,您可以在NCS下降的ISR中启用SPI外设,并读取在NCS上升的NCS中的32位总线中的所有内容;特别是如果您在完整的接收后无论如何处理数据。虽然在您的模式中,使SPI自动更新内存区域,没有同步/原子性问题,这将是额外的开销。
 
以下用户感谢此帖子: eBaster.

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#3开:2021.年4月18日,08:45:29»
谢谢!我的数据包是16个单词@ 20位,我打算读取为16位的20个单词@ 16位,因此来自STM32的两个功率'■透视。但那个线程确认了我的一般想法"autonomous"通过DMA和循环缓冲区的接收应该有效。

我刚刚找到了解决方案"缺少初始化代码的谜团"我相信:有一个自动生成的文件stm32f3xx_hal_msp.c,似乎拥有所有DMA初始化代码(和更多)。哈丁'根本没有注意到;呃......

我仍然需要弄清楚什么时候它是自动调用的,或者我仍然需要在我的用户代码中添加什么。需要等待几天 - 我设法昨天杀死了我的st-link克隆,通过在目标上缩短一些东西。所以'今天园艺而不是微控制器。 ;-)
 

 在线的 Siwastaja.

  • 超级贡献者
  • ***
  • 帖子:3718
  • 国家:  FI.
Re:STM32 - 使用圆形DMA的SPI
« 回复#4开: 4月18日,2021年,08:48:08»
请注意,DMA初始化代码如此简单,小,您应该在紧急情况下实际执行它,在必要时,IMHO。它也只需几个时钟周期,所以您可以轻松"initialize"DMA中断,或无论您需要什么。

限制自己初始化DMA一次"MCU initialization"步骤真的是限制性的。
 
以下用户感谢此帖子: eBaster.

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#5: 4月18日,2021年,09:35:07»
谢谢,Siwastaja!

同意,每次栅极信号变高,通过ISR重新初始化16×20位分组的DMA传输更加稳健。我在撕裂"auto-magical"背景方法和对每个传输周期重新同步的鲁棒性增加......

源是一个硬连线(TTL),缩小的图灵模型'S先导王牌计算机,顺便说一句。 ACE设计完全依赖于在串行数据流通过其延迟线存储器循环时从不缺少拍打:所有地址都是相对于先前指令时间,并且所有延迟线都需要始终保持同步。因此,我可以相信源以保持同步并发送恒定长度数据包。只要STM32 SPI不会错过一个击败,就应该是罚款。  ;)
 

 离线 戴维尔岛

  • 频繁的贡献者
  • **
  • 帖子:532
  • 国家:  es.
Re:STM32 - 使用圆形DMA的SPI
« 回复#6开启:2021.年4月18日,11:36:51»
hal_spi_receive_dma(spihandle,spibuffer,spi_buffer_size)
为你做一切。启用DMA,设置Spibuffer地址和SPI_Buffer_Size。
容易的。
« 上次编辑:4月18日,2021年,11:39:22 AM由Davidalfa »
STM32焊站固件: //github.com/deividAlfa/stm32_soldering_iron_controller
想要支持你的董事会吗?将详细信息放在论坛中并准备好进行测试。问题?在报告之前,始终闪烁最新的GitHub FW并完全重置。
请使用论坛,唐't PM me!
 
以下用户感谢此帖子: eBaster.

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#7:2021.年4月18日,11:46:27»
hal_spi_receive_dma(spihandle,spibuffer,spi_buffer_size)
为你做一切。启用DMA,设置Spibuffer地址和SPI_Buffer_Size。
容易的。

谢谢!正如我的第二篇文章所述,我现在对它感觉更好"missing"初始化代码 stm32f3xx_hal_msp.c..。见下文 - 那's all the stuff I "told"图形配置工具和无法't在生成的代码中查找。

与这些细节包含在初始化代码中,我可以看到如何 hal_spi_receive_dma. can do its thing...  :-+

代码: [选择]

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
[...]
   /* SPI1 DMA Init */
    /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA1_Channel2;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_spi1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      Error_Handler();
    }
 

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#8开:2021.年4月21日,05:32:17 AM»
我是"back in business"现在,用一个工作的st-link v2加密狗 - 但可以'似乎通过圆形DMA获得这种SPI接收来工作。  :(

目标是让μC通过SPI持续接收十六个20位单词的突发,并通过DMA将它们放入存储器缓冲器中。突发的持续时间由外部选择信号表示,该信号周期性低。这里's我在cubemx中设置了什么:
  • SPI1是仅接收从站,硬件NSS,数据大小10位。
  • SPI1_RX DMA已启用:循环模式,自动递增半单词的内存地址。
  • SPI和DMA中断被禁用。
  • 超出自动生成的代码,我通过hal_spi_receive_dma启动DMA( &hspi1,dma_buf,我的main.c中的sizeof(dma_buf)。然后,主循环定期显示连接显示器上DMA_BUF的内容。
我得到的是以下内容:启动后,第一个 字节 接收缓冲区的变化 一次 。写入那里的字节以某种方式取决于我饲养的MOSI数据,虽然它不是我期望的。如果启动时SPI时钟和NSS信号不存在,则只有在我打开那些信号时才会发生缓冲器更改。 (它们来自外部功能发生器进行测试。)

但之后没有别的变化。缓冲区中没有进一步的字节受到影响,如果我更改MOSI数据和/或关闭SPI时钟并重新打开,则第一个字节不会进一步改变。它看起来像SPI接口或DMA已经自己旋转或以某种方式锁定。

会有一些错误条件(框架吗?)导致这个?我不'需要在中断处理程序中定期重新启用任何内容,对右?因此,应该可以保持SPI和DMA中断禁用吗?还有什么我能忽视什么?

我是stumped... Many thanks for your ideas!
 

 在线的 Siwastaja.

  • 超级贡献者
  • ***
  • 帖子:3718
  • 国家:  FI.
Re:STM32 - 使用圆形DMA的SPI
« 回复#9: 4月21日,2021年,08:40:06»
通常:

将问题减少到最小代码再现问题,然后在此发布它。

显然这是不可能的,因为立方体自动化将10行实际代码膨胀为100或者知道它是多少,可能是1000个总数。没有人可以看一下,所以我们猜测。

删除,删除,删除,直到您有最小案例。基本上,您在SPI外设和DMA中的4-6中写入2-3寄存器。 SPI外设有一些选项可以致电"trap bits" like when you 大学教师 't 使用硬件ncs(通常不行't because it doesn't work) you need to 知道 to set "SSI"误合了1,否则SPI外围设备自动关闭自动关闭它非常无用,因为他们认为一些从未见过的奇怪屁股"multi-master SPI" is the 默认配置 and it's normal to "lose arbitration"在spi,去图。当我们不'知道你的实际注册配置'很难看出问题可能是哪里。
« 上次编辑:4月21日,2021年,08:43:43 AM由Siwastaja »
 

 离线 特鲁斯

  • 常规贡献者
  • *
  • 帖子:81
  • 国家:  GB.
Re:STM32 - 使用圆形DMA的SPI
« 回复#10: 4月21日,2021年,09:26:26»
不确定这是否有帮助。

I'm使用cubeeide v1.5.0和i'm肯定在cubemx(设备配置工具)中,如下"Parameter Settings"用于SPI的选项卡,SPI数据大小只有8位和16位选项。
您如何为数据大小设置10位?

无论如何,我认为HAL图书馆只支持8和16bits。
« 上次编辑:2021年4月21日,09:28:40 AM由Tru »
 

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#11开:2021.年4月21日,09:33:00»
I'm使用cubeeide v1.5.0和i'm肯定在cubemx(设备配置工具)中,如下"Parameter Settings"用于SPI的选项卡,SPI数据大小只有8位和16位选项。
您如何为数据大小设置10位?

我认为HAL库仅支持8和16bits,因此对于您的16 x 20位数据包,可能将SPI设置为8位数据大小,并使用16 x 3 = 48字节的数据缓冲区。

谢谢你的想法,但我不'认为这是问题。不同STM32芯片的SPI功能在这方面有所不同。某些支持只支持8个或16位字,其他人允许在4..16位之间的任何值之间。我使用的STM32F303确实提供了灵活的设置,而Cubemx和Hal库似乎支持那个很好的 - 所创建的寄存器设置看起来很合理。

(实际上我不相信奇怪的单词长度,昨天晚上尝试了8位;没有't help...)
 

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#12: 4月21日,2021年,09:38:05»
通常:
将问题减少到最小代码再现问题,然后在此发布它。

显然这是不可能的,因为立方体自动化将10行实际代码膨胀为100或者知道它是多少,可能是1000个总数。没有人可以看一下,所以我们猜测。

删除,删除,删除,直到您有最小案例。基本上,您在SPI外设和DMA中的4-6中写入2-3寄存器。

我猜 - 从没有Cubemx的划痕开始的意思是 - 这对我来说似乎是介绍许多新错误的好方法。 ;) 我希望避免这种情况,但如果我不'T在另一轮盯着代码和调试器今晚的进步,这可能是最后的度假村...... 
 

 离线 特鲁斯

  • 常规贡献者
  • *
  • 帖子:81
  • 国家:  GB.
Re:STM32 - 使用圆形DMA的SPI
« 回复#13开启: 4月21日,2021年,09:53:10»
谢谢你的想法,但我不'认为这是问题。不同STM32芯片的SPI功能在这方面有所不同。某些支持只支持8个或16位字,其他人允许在4..16位之间的任何值之间。我使用的STM32F303确实提供了灵活的设置,而Cubemx和Hal库似乎支持那个很好的 - 所创建的寄存器设置看起来很合理。

(实际上我不相信奇怪的单词长度,昨天晚上尝试了8位;没有't help...)
啊,我看到了这样的其他筹码确实支持它,我错了,请忽略我关于HAL支持的评论。  I'VE仅使用HAL库与DMA设置为循环缓冲区和16位的SPI数据大小,在向HAL_SPI_RECEIVE_DMA函数发送呼叫后持续接收。 SPI中断被禁用,但启用了全局DMA中断(这被锁定,我无法在Cubemx中关闭它)。 注意,我不使用硬件nss't help in this part.
 
以下用户感谢此帖子: eBaster.

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#14:2021.年4月21日,10:05:18 AM»
I'VE仅使用HAL库与DMA设置为循环缓冲区和16位的SPI数据大小,在向HAL_SPI_RECEIVE_DMA函数发送呼叫后持续接收。 SPI中断被禁用,但启用了全局DMA中断(这被锁定,我无法在Cubemx中关闭它)。 注意,我不使用硬件nss't help in this part.

嗯,两个要尝试改变的东西,谢谢!

DMA中断确实是"forced on"默认情况下,cubemx。在NVIC部分中,您可以取消选中"强制DMA通道中断"复选框在对话框的顶部;然后,您可以单独激活或取消激活这些中断。我以为我应该禁用DMA IRQ,因为我不会使用它;但也许这是一个坏主意,在默认的IRQ处理程序中发生了一些有用的东西?我今晚会尝试恢复默认值。 - 您是否在代码中提供了IRQ处理程序?

我试图始终将NSS拉低以避免从该方面产生影响,但会尝试整个今晚完全禁用硬件NSS。
 

 离线 特鲁斯

  • 常规贡献者
  • *
  • 帖子:81
  • 国家:  GB.
Re:STM32 - 使用圆形DMA的SPI
« 回复#15:2021.年4月21日,10:51:52»
您是否在您的代码中提供了IRQ处理程序?
不,我没有't在我自己的IRQ处理程序中添加,但在HAL预定义回调函数中添加以处理每个SPI数据接收:
void hal_spi_rxcpltcallback(spi_handletypedef * hspi){
......
}
 
以下用户感谢此帖子: eBaster.

 离线 Aandrew

  • 频繁的贡献者
  • **
  • 帖子:251
  • 国家:  加利福尼亚州
Re:STM32 - 使用圆形DMA的SPI
« 回复#16开:2021.年4月21日,05:50:10 PM»
将问题减少到最小代码再现问题,然后在此发布它。

显然这是不可能的,因为立方体自动化将10行实际代码膨胀为100或者知道它是多少,可能是1000个总数。没有人可以看一下,所以我们猜测。

大学教师't be daft. I'm no cube或hal库的粉丝,但这不是'T火箭科学。他们所需要的只是粘贴调用init(),粘贴mspinit()并粘贴调用hal_spi_receive_dma()函数的循环的代码。如果他们没有't得到了回调'LL也希望粘贴他们的hal_spi_rxcpltcallback()。 HAL代码没有'需要粘贴,但知道他们的哈尔的哪个版本're using would help.
 

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#17开:2021.年4月21日,06:08:00 PM»
感谢您的评论,Aandrew。如果我可能会有几个问题:

[...]呼叫HAL_SPI_RECEIVE_DMA()函数的循环。

挂断 - 我应该在a中调用hal_spi_receive_dma() 环形 当如果确实需要,它将解释为什么我没有进一步的行动。但如上所述,在SPI从设备中,我在循环模式下使用DMA。 isn.'这一点,这一直在继续和打开,只需一个呼叫hal_spi_receive_dma()?

引用
如果他们没有't得到了回调'LL也希望粘贴他们的hal_spi_rxcpltcallback()。

对不起,你在那里失去了我。你的意思是写的"If they 收到回调,粘贴hal_spi_rxcpltcallback()"?

引用
了解他们的哪个版本're using would help.

如OP中所述,我正在使用STMCubeide 1.6.1,这是Windows的最新版本版本。如果hal有单独的版本号,我会在哪里找到这个?我选中的HAL源文件没有其标题中的任何版本号。

谢谢!
 

 离线 Aandrew

  • 频繁的贡献者
  • **
  • 帖子:251
  • 国家:  加利福尼亚州
Re:STM32 - 使用圆形DMA的SPI
« 回复#18开启:2021.年4月21日,08:04:17 PM»
一般来说,圆形DMA它只是意味着它可以在又一遍地再次重新使用缓冲区,但是仍需要手动或通过定时器或其他方式触发DMA请求。我不'确切地知道你的方式'因为我避风港而恢复事情'看到您的代码,最重要的是,通往SPI init()的代码,然后是实际配置外设的mspinit()。

我知道它听起来很逆向直观,但没有,如果你'Re *不是*使用回调,然后您必须覆盖弱链接的哈尔函数hal_spi_rxcpltcallback(),默认情况下绝对没有。如果您使用回调,则必须使用驱动程序注册rxcallback函数。 HAL曾经没有回调功能,因此您唯一的选择是覆盖弱功能,但他们在最近的HAL中更改的一部分是它们'介绍了在运行时更改回调函数的能力。它'S总是在内部回调,现在他们只是给您更高的可见性和可配置性。个人我不'看到好处,但它's there.

至于HAL版本,您通常会看到它"管理嵌入式软件包" window under Cube's Help menu item.
 
以下用户感谢此帖子: eBaster.

 离线 特鲁斯

  • 常规贡献者
  • *
  • 帖子:81
  • 国家:  GB.
Re:STM32 - 使用圆形DMA的SPI
« 回复#19: 4月21日,2021年,09:09:08»
嗯,那是'T解释为什么HAL驱动器存在正常和循环模式,因为都使用相同的HAL_SPI_RECEIVE_DMA(SPIHandle,Spibuffer,SPI_BUFER_SIZE)和Spibuffer需要传递。

好的,刚尝试了一些测试,我想我'在Cubemx中找到了一个错误!

我确认使用循环缓冲模式,您不会在循环中反复调用hal_spi_receive_dma(),只需一次调用一次。 与普通缓冲模式相比,您必须在循环中反复调用它。

但是,有一个似乎阻止它的错误。 如果我最初将SPI设置为全双工主模式并添加2x DMA流:
1. SPI的DMA流接收并设置为圆形
2. SPI的DMA流传输并设置为正常

HAL_SPI_RECEIVE_DMA()函数接收一次但是挂起(我的意思是HAL_SPI_RXCPLTCALLBACK()再也也不调整)! 就像ebaster说的那样。

如果我回到Cubemx并设置DMA流以便传输到循环,现在HAL_SPI_RECEIVE_DMA()函数工作并连续接收 - 错误消失了。

现在,下一个问题是,当我回到Cubemx并更改SPI以仅接收主模式时,它自动删除发送的DMA流(仅作为模式),因此离开DMA接收完整。

但是,HAL_SPI_RECEIVE_DMA()函数仅接收一次,然后挂起!

但如果我回到Cubemx并将圆形扭转到正常,然后返回通知。 然后hal_spi_receive_dma()函数工作!

男子!!
« 上次编辑:4月21日,2021年,09:18:55由Tru »
 
以下用户感谢此帖子: eBaster.

 离线 Aandrew

  • 频繁的贡献者
  • **
  • 帖子:251
  • 国家:  加利福尼亚州
Re:STM32 - 使用圆形DMA的SPI
« 回复#20开:2021.年4月21日,09:26:59»
没有折扣你的剩余信息,但如果你'重新使用全双工WORN'您使用hal_spi_rxcpltcallback()?
 

 离线 Aandrew

  • 频繁的贡献者
  • **
  • 帖子:251
  • 国家:  加利福尼亚州
Re:STM32 - 使用圆形DMA的SPI
« 回复#21开: 4月21日,2021年,09:51:24 PM»
只是看着SPI驱动程序,我在顶级文档中看到了这一点:

       循环模式限制:
     (#)在这些模式下配置SPI时,不能使用DMA循环模式:
         (##)主rxonly master 2lines
         (##)Master 1line Rx


是你的'或许不支持之后?
 
以下用户感谢此帖子: eBaster.

 离线 特鲁斯

  • 常规贡献者
  • *
  • 帖子:81
  • 国家:  GB.
Re:STM32 - 使用圆形DMA的SPI
« 回复#22: 4月21日,2021年,晚上10:02:19»
没有折扣你的剩余信息,但如果你'重新使用全双工WORN'您使用hal_spi_rxcpltcallback()?
是的,我在这两种情况下都使用hal_spi_rxcpltcallback(),该情况仅包含闪存LED的代码,以及我'm不是在那里发送hal_spi_receive_dma()。  I didn'T打算在循环模式下使用全双工测试,但由于我通过修改现有的项目来开始使用DMA以正常模式进行全双工,因此我忘了改变它。

有趣的是,我看到它有局限性 - 我认为是,不支持某些配置。

来自"STM32F446XX AdvancedARM®的32位MCUSv6.0"参考手册I确认DMA请求在循环模式下连续(最后一句)。
引用
循环模式可用于处理循环缓冲器和连续数据流量(例如,
ADC扫描模式)。可以使用DMA_SXCR中的CIRC位启用此功能
登记。
当激活圆形模式时,要传输的数据项数量是
自动重新加载在流配置期间编程的初始值
阶段,DMA请求继续供应。
« 上次编辑:4月21日,2021年,10:11:07由tru »
 

 离线 Aandrew

  • 频繁的贡献者
  • **
  • 帖子:251
  • 国家:  加利福尼亚州
Re:STM32 - 使用圆形DMA的SPI
« 回复#23开:2021.年4月21日,晚上10:07:45»
也许只是使用Bidir模式(它吃另一个DMA频道,但它'可能不是问题),设置您的SPI MOSI GPIO所以它's *不是*使用正确的af(所以它不起作用'T实际传输)并将TX缓冲区指向到焦点的存储器。那'可能是一个很好的解决方法'LL为您提供圆形RX转移。
 

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#24开: 4月22日,2021年,05:54:43»
非常感谢您挖掘它,Tru和Aandrew!由于我一直在尝试使用循环DMA使用唯一的模式,因此您发现的限制可能是相关 - 尽管司机评论似乎仅表明主模式中的限制,但我使用从属模式。

不幸的是,切换到全双工从模式和添加圆形TX DMA没有改变我的设置的行为。我仍然被抓住了只接受一个(Mangled?)字节。

更有可能不是,我在某个地方做了一个完全愚蠢的错误......我会把这个项目放在一边,再读取μc和hal文件,然后回到调试器。我弄清楚什么时候我会更新这个线程'正在继续(或者我放弃的时候  ::))。到目前为止,谢谢你的帮助!
« 上次编辑:2021年4月22日,06:15:02 AM由Ebaster »
 

 离线 特鲁斯

  • 常规贡献者
  • *
  • 帖子:81
  • 国家:  GB.
Re:STM32 - 使用圆形DMA的SPI
« 回复#25 on:2021.年4月22日,09:30:11 AM»
我认为你们误解了我的测试,SPI DMA循环模式在全双工上工作,只能在主模式下接收。
限制可能是较旧的MCU陈述 - 肯定是它't apply to the MCU I'm使用STM32F446(核O64 STM32F446RE)。

啊,我认为我可能已经发现了你的问题。  I'在早期的帖子中注意到,你说DMA被设置为半字(16位),然后启动一次:hal_spi_receive_dma(&HSPI1,DMA_BUF,SIZEOF(DMA_BUF))

HAL驱动程序误标记了大小参数 - 更好的名称是传输计数。  传输48 * 16位的正确用法的示例是:
代码: [选择]
uint16_t DMA_buf[48];
hal_spi_receive_dma.(&hspi1, (uint8_t*)DMA_buf, 48);
sizeof(dma_buf)将返回96,这将要求DMA传输96 *半字= 96 * 16位。
« 上次编辑:2021年4月22日,09:33:05 AM由Tru »
 
以下用户感谢此帖子: eBaster.

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#26:2021.年4月22日,10:16:40»
啊,我认为我可能已经发现了你的问题。  I'在早期的帖子中注意到,你说DMA被设置为半字(16位),然后启动一次:hal_spi_receive_dma(&HSPI1,DMA_BUF,SIZEOF(DMA_BUF))

HAL驱动程序误标记了大小参数 - 更好的名称是传输计数。  

英雄所见略同! ;) 

在昨天早上我在淋浴时发生了同样的想法。我完全有信心这将是问题 - 我一定是在咆哮的是错误的树上几天,SPI和DMA实际上很好,但我要求RX DMA超过缓冲区限制,因此拍摄我的计划下。立即前往长凳(嗯,我确实干燥并穿着,但肯定会跳过早餐) - 但唉,没有变化。

在哪一点,我开始怀疑我是否正在犯下其他地方的完全愚蠢的错误,甚至与SPI和DMA有关。几天后,我将返回并重新审视我的代码和cubemx设置。可能最好用最小的解决方案而没有连接。 (使用另一个SPI港口,可能为我造成了一些交叉的精神电线......)我现在需要冷却时间!  ;)
 

 离线 Aandrew

  • 频繁的贡献者
  • **
  • 帖子:251
  • 国家:  加利福尼亚州
Re:STM32 - 使用圆形DMA的SPI
« 回复#27:2021.年4月22日,01:40:29 PM»
这篇文章现在几天历史悠久,仍然没有init(),mspinit(),dma_start()和回调()代码发布......为什么不这样做,所以我们aren'在黑暗中拍摄?
 

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#28 on:2021.年4月22日,01:50:17 PM»
这篇文章现在几天历史悠久,仍然没有init(),mspinit(),dma_start()和回调()代码发布......为什么不这样做,所以我们aren'在黑暗中拍摄?

很高兴有责任!我现在正在工作,但今天晚些时候会发布。到目前为止,我是不情愿的,因为Siwastaja'初步评论是,HAL开销会使这太乱通过,因为我也有唠叨的感觉,我的问题在其他地方谎言......

提前感谢您愿意查看代码!
 

 在线的 Siwastaja.

  • 超级贡献者
  • ***
  • 帖子:3718
  • 国家:  FI.
Re:STM32 - 使用圆形DMA的SPI
« 回复#29开: 4月22日,2021年,03:44:58»
别处?

重点是,如果你发布所有代码,问题 具有 在代码中在那里。

非常广泛接受的论坛协议是提供 最低示例再现问题 但是,立方体废话是不可能的。仍然,如果你不'T感觉像摆脱多维数据集并编写最小案例,重现问题 - 这应该是大约10行,我已经早些时候发布了它的主要部分 - ,最好张贴所有的多维数据集代码。也许有人可以想到一些看它的东西,即使很长。

没有代码,我们只能猜到。它'如果尝试在没有原理图的情况下尝试排除模拟电子问题。

坦率地说,您将在现在许多次从头开始写入DMA和SPI初始化。作为副作用,您将理解这些外围设备的工作方式(通过阅读手册)。
« 最后编辑:4月22日,2021,03:46:55 PM由Siwastaja »
 

 离线 Aandrew

  • 频繁的贡献者
  • **
  • 帖子:251
  • 国家:  加利福尼亚州
Re:STM32 - 使用圆形DMA的SPI
« 回复#30:2021.年4月221日,03:48:46»
他的代码(不是多维数据集代码)将很小。事实上,自他'使用HAL我会认为他的代码比你的代码小于你的代码,从这里的粘贴来看。他没有'T必须发布多维数据集代码,但告诉我们他的哪个版本他'使用会有所帮助。
 

 离线 戴维尔岛

  • 频繁的贡献者
  • **
  • 帖子:532
  • 国家:  es.
Re:STM32 - 使用圆形DMA的SPI
« 回复#31开:2021.年4月22日,04:41:50 PM»
尝试使用从站仅接收模式,并禁用NSS。
然后发送几个字节....我的赌注是在NSS管理中
STM32焊站固件: //github.com/deividAlfa/stm32_soldering_iron_controller
想要支持你的董事会吗?将详细信息放在论坛中并准备好进行测试。问题?在报告之前,始终闪烁最新的GitHub FW并完全重置。
请使用论坛,唐't PM me!
 

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#32开启:2021.年4月22日,06:21:14 PM»
好吧,这里去......

我已删除其他SPI(驱动显示器),而是仅在alh_spi_rxcpltcallback函数中切换GPIO,以查看SPI接收是否还活着。输出只能切换一次,而我希望它会定期切换,每次32 * 10位。

希望我没有'T在条带期间引入任何错误。这是介绍回调的正确方法吗?我的原始代码根本没有任何rxcpltcallback,但只是异步地从dma_buf读取数据。 (编辑:测试输出切换只有在从外部信号发生器上打开SPI时钟,所以我确实似乎观察一个且只有一个SPI / DMA循环。)

如果有任何缺失,请告诉我。非常感谢您的评论!

main.c摘录(删除了系统时钟和GPIO的init代码)
代码: [选择]
#include "main.h"

SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;

// DMA data buffer. 16*2 16-bit values, each used for 10 bits of data, low half-word first
#define DMA_BUF_LEN 32
uint16_t DMA_buf [DMA_BUF_LEN];

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
static void MX_DMA_Init(void);

/* Private user code ---------------------------------------------------------*/

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi)
{
HAL_GPIO_TogglePin (TESTOUT_GPIO_Port, TESTOUT_Pin);
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_DMA_Init();

  // Initialize SPI1 receive DMA with circular buffer
  HAL_SPI_Receive_DMA (&hspi1, (uint8_t *)DMA_buf, DMA_BUF_LEN);

  while (1)
  {
  }
}

static void MX_SPI1_Init(void)
{
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_SLAVE;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
  hspi1.Init.DataSize = SPI_DATASIZE_10BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_LSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
}

hal_spi_mspinit.
代码: [选择]
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hspi->Instance==SPI1)
  {
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PB3     ------> SPI1_SCK
    PB4     ------> SPI1_MISO
    PB5     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* SPI1 DMA Init */
    /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA1_Channel2;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_spi1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);
  }
}
« 上次编辑:2011年4月22日,06:38:39 PM由Ebaster »
 

 离线 戴维尔岛

  • 频繁的贡献者
  • **
  • 帖子:532
  • 国家:  es.
Re:STM32 - 使用圆形DMA的SPI
« 回复#33开:2021.年4月221日,09:12:15 PM»
用8位数据进行测试。可能是一个错误或任何东西。你检查了stm32 errata吗?
我暂时尝试了自己,它在仅适用于从站接收模式和HAL_SPI_RECEIVE_DMA中完美的工作。
8和16位尺寸。我的STM32都没有精细的SPI框架尺寸调整。
« 最后编辑:2021年4月23日,01:37:20 AM由Davidalfa »
STM32焊站固件: //github.com/deividAlfa/stm32_soldering_iron_controller
想要支持你的董事会吗?将详细信息放在论坛中并准备好进行测试。问题?在报告之前,始终闪烁最新的GitHub FW并完全重置。
请使用论坛,唐't PM me!
 
以下用户感谢此帖子: eBaster.

 离线 特鲁斯

  • 常规贡献者
  • *
  • 帖子:81
  • 国家:  GB.
Re:STM32 - 使用圆形DMA的SPI
« 回复#34开: 4月22日,2021年,下午11:03:58»
这里'我的工作代码进行比较 - 也许你可以发现一些东西。 它正在使用SPI设置的Nucleo64 F446RE DEV板,以接收主模式,8位,DMA循环模式(我试图剥离大多数Cubemx评论等):
代码: [选择]
#include "main.h"

#define DMA_BUF_LEN 32
uint8_t* m_dma_buf[DMA_BUF_LEN];
uint32_t m_toggle_counter = 0;

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SPI1_Init(void);

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI1_Init();

  HAL_SPI_Receive_DMA(&hspi1, (uint8_t*)m_dma_buf, DMA_BUF_LEN);
 
  while (1)
  {
  }
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 180;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 15;
  RCC_OscInitStruct.PLL.PLLR = 2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Activate the Over-Drive mode
  */
  if (HAL_PWREx_EnableOverDrive() != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */
}


/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA2_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);

}

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

  /*Configure GPIO pin : PC13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PA5 */
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

void hal_spi_rxcpltcallback(spi_handletypedef * hspi){
if(hspi->Instance == SPI1){
if((m_toggle_counter / 1000) % 2)
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
else
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

m_toggle_counter++;
}
}

呼叫后续程序HAL_SPI_RXCPLTCALLBACK()闪烁一个测试LED GPIO PA5,该PA5确认DMA请求是连续的,因为它一直被称为。  I've使用了一个柜台,一个大部门慢慢地减慢闪烁。 对不起,cubemx或我的董事会没有'T支持DMA以半字和SPI 10位,所以我不能像你一样靠近你,也不能'T有一个时钟源来测试SPI接收从动模式,但Davidalfa确认他获得了从属模式工作。
« 上次编辑:4月22日,2021年4月22日,由Tru PM下午11:06:05 »
 
以下用户感谢此帖子: eBaster.

 离线 特鲁斯

  • 常规贡献者
  • *
  • 帖子:81
  • 国家:  GB.
Re:STM32 - 使用圆形DMA的SPI
« 回复#35开启:2021.年4月22日,晚上11:09:26»
嗯,只是注意到你的cubemx代码没有'T有一个SPI波特率预分频器设置,或者也许芯片只有默认值?
 

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#36开启: 4月23日,2021年,05:01:13 AM»
嗯,只是注意到你的cubemx代码没有'T有一个SPI波特率预分频器设置,或者也许芯片只有默认值?

BAUK率预分频器仅在SPI主模式下活动,我认为,因为从站没有生成时钟。如果我在cubemx中切换到主模式,它会提供预分频器设置,从而在从模式下选择选项。
 

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#37 on: 4月23日,2021年,05:14:09»
用8位数据进行测试。可能是一个错误或任何东西。你检查了stm32 errata吗?
我暂时尝试了自己,它在仅适用于从站接收模式和HAL_SPI_RECEIVE_DMA中完美的工作。
8和16位尺寸。我的STM32都没有精细的SPI框架尺寸调整。

在调试我的完整代码时,我也试图回到8位帧,这没有解决问题。我会再次尝试使用最少的代码来确保。

我没有检查勘误表'F303到目前为止,但刚刚这样做了。不幸的是't找到任何相关的SPI或DMA问题。
 

 离线 特鲁斯

  • 常规贡献者
  • *
  • 帖子:81
  • 国家:  GB.
Re:STM32 - 使用圆形DMA的SPI
« 回复#38 on: 4月23日,2021年,06:35:39»
BAUK率预分频器仅在SPI主模式下活动,我认为,因为从站没有生成时钟。如果我在cubemx中切换到主模式,它会提供预分频器设置,从而在从模式下选择选项。
啊,是的,愚蠢的我忘记了从事模式!
还忘了从其他文件添加MSP初始部分:
代码: [选择]
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hspi->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PA6     ------> SPI1_MISO
    PB3     ------> SPI1_SCK
    */
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* SPI1 DMA Init */
    /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA2_Stream0;
    hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }

}
 

 在线的 eBaster.

  • 超级贡献者
  • ***
  • 帖子:3913
  • 国家:  德
Re:STM32 - 使用圆形DMA的SPI
« 回复#39开: 4月23日,2021年,07:48:38»
别处?
重点是,如果你发布所有代码,问题 具有 在代码中在那里。

我可以想到源代码外面可能出错的事情:面包板上缺失或糟糕的连接,引导选择的跳线设置不正确,IDE中的一些不知情调试设置,假冒和越野车......我检查并双重检查我想到的方面,但显然可以'排除别的东西可能是错误的。

引用
坦率地说,您将在现在许多次从头开始写入DMA和SPI初始化。作为副作用,您将理解这些外围设备的工作方式(通过阅读手册)。

也许从头开始编码就会更快,或者也许我仍然会试图弄清楚如何设置系统时钟...... ::) 最有可能,我将完全在我现在的位置,因为正确设置寄存器似乎并不是问题。

我想,无需谴责我使用的Hal和Cubemx。我确实有意识地做出了这种选择(而不是没有疑惑 - 实际上的HAL手册 较长 比处理器'S参考手册似乎在某种程度上击败了一定程度的目的......)我多年来一直在裸机水平上编程了各种微控制器,从8051开始,所以我不会从Arduinos直接来。但发现stm32家庭有点压倒并以为我'd give the "modern"方法试试;它肯定有助于我在几个案例中更快地让我的轴承。仍然未定我将在下一个项目上采取的方法。
« 上次编辑:2021年4月23日,09:28:27 AM通过Ebaster »
 


分享我

 掘客    Facebook    诽谤    可口的   Technorati.   推特    谷歌    雅虎
SMF.