英文:
STM32 I2C Receive Function Size Parameter Problem
问题
我正在使用STM32G474RET6 MCU的I2C从机模式。我想使用DMA进行轮询模式,但问题是我不知道接收数据的长度。每次都可能不同。但是'HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)'函数需要大小参数。
我尝试将大小参数设置为缓冲区大小。例如,我将20作为参数传递,但只获取了5个字节的数据。当我这样做时,它将所有数据放入缓冲区,但hi2c状态保持繁忙,并且没有进入RxCompltdCallback而是进入ErrorCallback。
我尝试将大小设置为1,并逐个获取数据。它会获取数据,但会覆盖缓冲区本身的同一列中的数据,最终我只能获取最后一个字节。而且再次进入ErrorCallback。
有没有办法在不知道大小参数的情况下进行通信?
英文:
I am working on STM32G474RET6 MCU in i2c slave mode. I want to make a polling mode with DMA but the problem is i don't know the receiving data's length. Every time it can be different. But 'HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)' function takes size parameter.
I tried to give the size parameter buffer size. And for example i gave 20 as a parameter but get 5 byte data.When i do that, it takes the whole data to the buffer but hi2c state stays busy and it does get into ErrorCallback instead of RxCompltdCallback.
I tried to give the size 1 and takes the data one by one. It takes the data. But it overwrites the data in the same column of the buffer itself and in the end i can only take the last byte. And also again it goes into ErrorCallback.
Is there any way I can communicate without knowing the size parameter?
答案1
得分: 1
在这种情况下使用DMA是可能的,但正如建议的,你将需要一种I2C中断来判断最后一个字节何时到达,而不必让CPU实际逐个查看每个传入的字节,否则DMA有何意义,你可以选择使用中断(这可能是一个完全有效的选项)。
你的问题可以归结为:“我作为I2C从机每次接收任意数量的字节,我如何知道传输何时结束”。
我将以STM32F103(在Blue Pills和Nucleo板上使用)作为示例,因为我手头有它的文档。它的I2C有一个STOPF位,在从机模式下充当停止事件检测位,它可以触发中断 - 正是我们所需要的。
我提出以下逻辑:
- 配置I2C为DMA接收,DMA传输长度为0xFFFFFFFF(最大值)
- 配置I2C事件中断
- 让DMA接收 n 个字节(任意数量)
- 在I2C事件中断处理程序中(由于检测到I2C从机的STOP位而触发),你检查剩余的DMA传输数据长度(例如0xFFFFFFFD),这意味着你接收了0xFFFFFFFF - 0xFFFFFFFD = 2个字节 = n。
- 处理 n 个字节,将DMA传输长度重置为最大值。
英文:
Using DMA in this situation is possible, but, as suggested, you will need some kind of I2C interrupt as well. The problem is to say when the last byte arrived without having CPU actually look at every incoming byte one by one, otherwise what's the point of DMA, you can go with interrupts (could be perfectly valid option)
Your problem boils down to "I receive arbitrary number of bytes at a time as I2C slave, how do I know the transmission has ended".
I will use STM32F103 (used in Blue Pills and Nucleo boards) as an example, since I have its documentation at hand. Its I2C has STOPF bit, which in slave mode serves as stop event detection bit, and it can trigger an interrupt - exactly what we need.
I propose the following logic:
- Configure I2C with DMA reception, DMA transfer length 0xFFFFFFFF (maximum)
- Configure I2C event interrupts
- Let DMA receive n bytes (arbitrary)
- In I2C event interrupt handler (triggered by detecting STOP bit as I2C slave) you check the remaining DMA transfer data length (e.g. 0xFFFFFFFD), which means you received 0xFFFFFFFF - 0xFFFFFFFD = 2 bytes = n.
- Process n bytes, reset DMA transfer length to max value.
答案2
得分: 0
你需要在同一段代码中混合使用I2C中断和DMA。
你需要有一个I2C中断处理程序来等待NACK、START和STOP事件,然后你就知道传输已经完成了。DMA驱动程序不会提供这个信息,因为它只会在所有(或/和[如果启用了半中断]半中断)预期的字节都被传输时触发中断。
英文:
You need to mix I2C interrupts and DMA in the same code.
You need to have I2C interrupt handler waiting for NACK, START and STOP events and then you know that the transmission has finished. DMA driver will not provide you with this information as it triggers the interrupt if all (or/and [if half interrupts are enabled] half) expected bytes have been transferred.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论