完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
我使用PIC16F1887作为模式1中的SPI从,即空闲时的时钟低,高到低过渡的数据。它是中断驱动的,我使用CLC来生成一个“后退”信号,它在SPI时钟高电平上设置,并且在中断读写SPI数据时被清除。除了这一个非常奇怪的情况外,大多数情况下都很好。如果软件缓冲区是空的,而奴隶想写一些东西,我想把它直接写入SSPBUF寄存器,而不是把它添加到缓冲器中,等待下一个时钟,以避免浪费垃圾。如果奴隶想对主人进行第一次传送,情况总是这样。当然,有可能发生碰撞,即师父在我写SSPBUF时开始计时。所以在我的写例程中,我会写信给SSPBUF,如果设置了冲突标志,我会清除它并把数据添加到缓冲器中,因为我知道中断很快就会被调用。因此,我希望中断中的“后退”线清晰,但永远不会。我的数字分析器没有什么特别之处——在一些随机的时间之后,这条线就永远不会清除。经过大量的分析和调试之后,我有点怀疑它可能是硅酮设计问题。在最后一次写入失败的地方,我发现如下:1)在函数开始时,时钟测量高(在PIC)。2)中断使能标志清除。3)我写到SSPBUF。没有检测到冲突。4)中断启用标志设置。5)时钟引脚测量低(在PIC)。6)“后退”引脚保持高&中断;不调用?这意味着在SSPBUF写入期间,时钟从高到低转换(即采样数据引脚),而不会引起冲突,也不会引起中断。如果我删除了我直接写到SSPBUF的特殊情况,它的工作就完美无缺,除了我有一个额外的垃圾字节。有人遇到过这个问题或者有什么建议吗?
以上来自于百度翻译 以下为原文 I am using a PIC16F18857 as SPI slave in mode 1, i.e. clock low when idle, data on high-to-low transition. It is interrupt driven and I am using CLC to generate a "back off" signal for the master, which is set on SPI clock high and cleared when the interrupt has read and written the SPI data. This mostly works fine, except for this one very weird case... If the software buffer is empty and the slave wants to write something, I want to write it straight to the SSPBUF register instead of adding it to the buffer and waiting for the next clock, as to avoid clocking out rubbish. This will always be the case if the slave wants to do the very first transmit to the master, for example. Of course there's the possibility of a collision, i.e. the master starts clocking just as I'm writing to SSPBUF. So in my write routine, I'll write to SSPBUF and if the collision flag is set, I'll clear it and just add the data to the buffer, since I know the interrupt will be called soon. As a result I expect the "back off" line to clear in the interrupt, but it never does. My digital analyser shows nothing unusual - the line just never clears after some random time. After tonnes of analysis and debug, I'm getting this slight suspicion that it might be a silicone design problem. In the last write where it fails, I find the following: 1) At the start of the function, clock measures high (in PIC). 2) Interrupt Enable flag cleared. 3) I write to SSPBUF. No collision is detected. 4) Interrupt Enable flag set. 5) Clock pin measures low (in PIC). 6) "Back off" pin stays high -> interrupt not called? This means that the clock transitioned from high to low (i.e. sampled the data pin) somewhere during the SSPBUF write without causing a collision and also not causing an interrupt. If I remove the special case where I write directly to SSPBUF, it works flawlessly, except that I have one extra rubbish byte. Has anyone come across this or have any suggestions? |
|
相关推荐
19个回答
|
|
|
我不遵循所有的逻辑,但听起来像某种种族条件。如果你手动设置“回退”信号,然后再对SSPBUF做最初的写?
以上来自于百度翻译 以下为原文 I'm not following all of the logoic, but it sounds like some sort of race condition. What about if you manually set the "back off" signal before doing this initial write to SSPBUF? |
|
|
|
|
|
@ QuyB:设置“后退”信号并不保证在我写到SSPBUF之前,主将看到并响应它,所以这将是一个竞赛条件。我已经取得了进步,因为一些有趣的发现……我在SSPBUF写入和范围内提出了一个PIN。我可以看到写在最后一个SPI时钟下发生。这使我认为SSPBUF写入发生在数据有效之后,但在中断之前。也许这会使PIC放弃读取数据而不引发中断?然后,在中断完成之后,在主机发出下一个时钟之前,我只修改写入函数以写入SSPBUF。这工作了99%,但却带来了一个更奇怪的例外…有时写就像主机为下一个字节提高SPI时钟而数据混乱一样。第一个比特来自以前的SSPBUF写,剩下的是第一个(MSB)到我尝试写入的数据的第七位。我看到的下一个字节是这个新字节的正确版本,这使我得出结论,我的函数看到了一个碰撞并将它添加到缓冲器中,但是碰撞并不能阻止数据被同步到SSPBUF中。显然是一个很大的混乱,不知道如何修复它。MSB应该像下面的字节一样低。前一个字节是0xFF。
以上来自于百度翻译 以下为原文 @qɥb: Setting the "back off" signal does not guarantee that the master will see and respond to it before I write to SSPBUF, so this would be a race condition. I have made progress since, along with some interesting discoveries... I raised a pin for the duration of the SSPBUF write and scoped it. I can see that the write happens during the very last SPI clock down. This makes me think that the SSPBUF write happens after the data becomes valid, but before the interrupt goes off. Perhaps this makes the PIC discard the read data and not raise the interrupt? I then modified the write function only to write to SSPBUF after the interrupt is done, but before the master raises the next clock. This worked 99%, but renders an even more bizarre exception... Sometimes the write happens JUST as the master raises the SPI clock for the next byte and the data is a mess. The first bit is from the previous SSPBUF write and the rest are the first (MSB) to seventh bit of the data I just tried to write. The next byte I see is the correct version of this new byte, which leads me to conclude that my function saw a collision and added it to the buffer, but the collision didn't prevent the data from being clocked into SSPBUF. Obviously a big mess and not sure how to fix it. Glitch shown in the picture below. The MSB is supposed to be low like in the following byte. The previous byte was 0xFF. |
|
|
|
|
|
您是否正在采样SCK引脚并使用它触发ISR写入到SPI缓冲器的中断?如果你这样做,你可能需要改变你的逻辑,因为如果你在奴隶上有一个非常慢的SPI时钟和一个非常快的CPU时钟,那么它可能就没有足够的时间来正常工作。如果它必须这样做,但这也假定主控器在写入到它的SPI缓冲区之前,将它远远落在足够远的位置上,以便使从属器完全反应。一个更好的方案可能是使用从主到从属的单独的行,以触发从属器的写入到SPI缓冲器,以便T。他完全控制了“请求”和交换开始之间的时间(它应该真正使用的是SS),它似乎总是在你所显示的图像中是低的。也许最可靠的是“双交换”协议或类似的东西-主机发送一个逗号。D向奴隶说“读取”,然后在适当的暂停之后执行第二次交换以接收奴隶数据。即使是一个连续的交换序列,使得奴隶在每个交换完成后都将其当前数据放入其SPI缓冲区将更好。
以上来自于百度翻译 以下为原文 Are you sampling the SCK pin and using it to trigger an interrupt with the ISR writing to the SPI buffer? If you then you will probably need to change your logic as there will probably not be enough time for this to work correctly unless you have a very slow SPI clock and a very fast CPU clock on the slave. It would be better to have the master drop the SS line to the slave and have the slave use that if it has to, but this also assumes that the master drops the SS line far enough ahead of when it writes to its SPI buffer for the slave to fully react. A better scheme would probably be to use a separate line from the master to the slave to trigger the slave's writing to the SPI buffer so that the master has complete control over the timing between the "request" and the start of the exchange (which should really use the SS - it seems to always be low in the image you have shown). Probably the most reliable is the 'double exchange' protocol or something similar - the master sends a command to the slave to say 'read' and then performs a second exchange after a suitable pause to receive the slaves data. Even a continuous sequence of exchanges such that the slave will put its current data into its SPI buffer after each exchange completes would be better. Susan |
|
|
|
|
|
嗨,苏珊。不,我不使用SCK引脚来产生一个中断。这都是由SPI外围设备本身使用它的标准中断机制完成的。当我的写入函数(通常只写入缓冲区)试图直接写入SSPBUF时,问题就发生了。为了解决这些问题,当SS处于活动状态时,我目前正在阻止奴隶直接写入SSPBUF。这应该正常。如果奴隶想在不活动的情况下向主人发送东西,那么对SSPBUF进行写入是安全的,然后放弃“后退”线。我不想依赖奴隶理解像“读”命令那样的东西,因为如果有什么故障,整个协议就被破坏了。此外,速度在这个应用中是至关重要的,所以我不能做不必要的通信。我仍然担心的是,PIC是如何在一定条件下融合两个字节的。这真的不应该发生。
以上来自于百度翻译 以下为原文 Hi Susan. No, I'm not using the SCK pin to generate an interrupt. This is all done by the SPI peripheral itself using its standard interrupt mechanisms. The problem happens when my write function, which normally only writes to the buffer, tries to write directly to SSPBUF. To get around these issues, I am currently blocking the slave from directly writing to SSPBUF when SS is active. This should be okay normally. If the slave wants to send the master something out-of-turn while SS is inactive, it is safe to write to SSPBUF and then drop the "back off" line. I don't want to rely on the slave understanding something like a "read" command, because if something glitches, the whole protocol is busted. Also, speed is crucial in this application, so I can't do unnecessary communication. What does still worry me, is how the PIC fuses two bytes together under certain conditions. This really should not happen, methinks. |
|
|
|
|
|
我认为现在是(过去)时间,你展示了你所有的代码,包括配置设置。这是否意味着奴隶试图告诉主人有或没有数据可用,或者什么?我不知道你的意思是PIC(主人还是奴隶?)融合两个字节-也许你可以解释多一点。苏珊
以上来自于百度翻译 以下为原文 I think it is (well past) time that you showed us all of your code, including the config settings. Also can you please explain exactly what you mean by "back off"? Does this mean that the slave is trying to tell the master that there is or is not data available, or what? I'm not sure what you mean by the PIC (the master or the slave?) fusing two bytes - perhaps you could explain this a bit more. Susan |
|
|
|
|
|
苏珊,我已经附加了我目前的SPI代码和寄存器设置。我的SPI代码已经被更早地描述了,所以写函数只写在SSPBUF上,如果从属选择是不活动的,或者从从属写的唯一模式(写入=1)。Xchange,因为PIC没有任何SPI FIFO。在传输时,它可以用来控制主控器——这是由主从来决定的。我已经在线程中较早地描述了融合,但要重申:“第一个比特来自先前的SSPBUF写入,其余的是第一个(MSB)到我试图写入的数据的第七位。”汉克斯
C(4.96 KB)-下载60次 以上来自于百度翻译 以下为原文 Susan, I have attached my current SPI code and register settings. My SPI code has been changed as described earlier, so that the write function only writes to SSPBUF if the slave select is inactive or in slave write-only mode (writing=1). The "back off" line tells the master not to clock the SPI and is used by the slave to give it enough time to process the last exchange, since the PIC does not have any SPI FIFO. It could be used to throttle the master when either is transmitting - it's up to the slave to decide. I have described the fusion earlier in the thread, but to recap: "The first bit is from the previous SSPBUF write and the rest are the first (MSB) to seventh bit of the data I just tried to write." Thanks Attachment(s) spi1.c (7.45 KB) - downloaded 65 times mcc.c (4.96 KB) - downloaded 60 times |
|
|
|
|
|
有两件事:“……你所有的代码”并不意味着2个文件——我已经看过了这些文件,但它们并没有告诉整个故事,尤其是关于CLC配置的。我必须承认,我真的不喜欢MCC生成的代码,当你尝试修改它时,它只会变得更糟。——“WRITI”NG变量总是1(至少在我所能看到的代码文件中),因此它似乎只是使你的代码复杂化了——我假设你不调用“SPI1Exchange 8BIT”和“SPI1Exchange 8BITBASH”函数(虽然我看到你似乎已经修改了第一个我认为我可以破译你要做的事情,但我怀疑你过于复杂了。我不知道CLC增加了什么价值,所以我忽略了下面的内容,这是我提出的建议。首先,除了TX环缓冲器之外,使用一个直接与主机对话的LAT位来告诉我们当我们准备好去的时候,我假设0意味着我们什么都没有,而1兆欧。NS我们已经加载了一个值。创建一个函数,用下面的伪代码发送一个字符:然后您可以沿着一条线创建一个ISR:这也假定主用户在每次交换开始时使用s\行重新同步从MSSP。我将把错误处理留给您,但是它应该如果WOCK不能从PIN信号的上升沿触发,那么这将是很好的,但是一个电平触发器也会起作用。苏珊
以上来自于百度翻译 以下为原文 A couple of things: - "...all of your code" does not mean 2 files - I've looked at those but they don't tell the whole story, especially with respect to the CLC configuration - I must admit that I really dislike MCC generated code and it just gets worse when you try to modify it yourself. - the 'writing' variable is always 1 (at least as far as I can see in the code files provided) and so it seems to just complicate some of your code - I *assume* that you don't call the 'SPI1_exchange8bit' and 'SPI1_Exchange8bitBuffer' functions (although I see you appear to have modified the first one with some CLC code) I *think* I can decipher what you are tying to do but I suspect that you are over complicating things. I've no idea what value the CLC is adding so I've ignored it in what follows, which is my suggestion to make things work. Firstly, in addition to the TX ring buffer, use a LAT bit that talks directly to the master to tell it when we are ready to go - I'll assume a 0 means we have nothing and a 1 means we have loaded a value. Create a function to send a character with the following pseudocode: SPI_write(tx_value) { if(LAT bit is 0) { // Load the value. ready for the next exchange SPIBUF = tx_value set the LAT bit to 1 that tells the master we have a value loaded and ready to exchange } else { add tx_value to the tx ring buffer } } You can then create an ISR along the lines of: SPI_ISR() { IF = 0 // Clear the IF flag Clear the LAT bit that tells the master we have a value to exchange as we don't as yet Save/discard the Rx'd character if(the Tx ring buffer has a character) { SPIBUF = next Tx ring buffer character set the LAT bit to 1 that tells the master we are ready for an exchange } // Else nothing more to do } This also assumes that the master is using the SS line to re-sync the slave MSSP at the start of each exchange. I'll leave error handling to you but it should be minor as WCOL will not be set. If the master can be triggered off the rising edge of the pin signal then that would be great, but a level trigger will work as well. Susan |
|
|
|
|
|
-我为有限的代码道歉,但我不想分享我的所有代码,因为它大部分是专有的。我已经附上了CLC代码,但我想很难在脑子里翻译。早期的跟踪可能会让你知道它是如何工作的。-是的,自动生成的代码非常糟糕,默认的USAT代码也有bug。我所包含的代码也有点混乱,因为它处于调试-道歉的中间。-“写入”变量现在被使用并且很重要。代码还远远没有完成。我所描述的问题是用“写”设置为0。-正确,“SPI1Exchange 8BIT”和“SPI1Exchange 8BITBASH”函数不再被使用。-您描述的LAT位听起来像我的“后退”线。但是它太慢了,因为我的奴隶在中断中花费了大量的时间,这意味着不能保证ISR能够在主时钟下一个字节之前清除LAT位。这就是为什么我使用CLC,它的响应速度比任何ISR都快。只要我有“写=1”,它就工作得很好。我唯一的异议是,似乎有一个硬件错误导致了我所描述的熔断。
CLC2.C(3.25 KB)-下载39次 以上来自于百度翻译 以下为原文 - I apologize for the limited code, but I don't want to share all my code, since the bulk of it is proprietary. I have attached the CLC code, but I imagine it's hard to translate in one's head. The earlier trace probably gives you the best ideas of how it works. - Yes, the auto-generated code is terrible and there's a bug in the default USART code as well. The code I included is also still a bit messy, since it's in the middle of being debugged - apologies. - The "writing" variable is now used and is important. The code is far from finished. The problem I described is produced with "writing" is set to 0. - Correct, the 'SPI1_exchange8bit' and 'SPI1_Exchange8bitBuffer' functions are no longer used. - The LAT bit you describe sounds like my "back off" line. It would be too slow, however, because my slave spends a lot of time in interrupts, which means there's no guarantee that the ISR could clear the LAT bit before the master clocks the next byte. This is why I'm using CLC, which responds faster than any ISR could. It is working nicely now as long as I have "writing=1". The only objection I have is that there seems to be a hardware bug that causes the fusing I described. Attachment(s) clc1.c (3.43 KB) - downloaded 37 times clc2.c (3.25 KB) - downloaded 39 times |
|
|
|
|
|
重新使用LAT引脚开始“太慢”。如果在主控器上使用边沿触发器,那么这将不是一个因素。遗憾的是,您使用的是PIC16设备,因为它只有一个中断级别。PIC18设备有2个级别,所以你可以把MSSP中断放在更高的水平上。但是这确实引起了我的疑问:如果你在ISR中花费了这么多时间,你不能及时地为其他中断服务,那么你是否编写了你的其他ISR代码,那么你可能是HA。错了“设计模式”。ISRS的目的是快速的“进出”代码,要么为主线设置标志来进行处理,要么执行一些非常简单的操作(例如将值复制到/从环形缓冲区中复制)。
以上来自于百度翻译 以下为原文 Re the use of the LAT pin begin "too slow". If you use the edge trigger on the master then that would not be a factor. It is a pity you are using the PIC16 device as it only has a single interrupt level. The PIC18 devices have 2 levels so you could put the MSSP interrupt at the higher level. However that does lead to the question in my mind: have you written your other ISR code properly if you are spending so much time in the ISR that you cannot service other interrupts in time, then you probably have the wrong 'design pattern'. ISRs are intended to be fast "get in and out" code that either sets a flag for the mainline to do the processing, or performs some very simple operation (such as copy a value to/from a ring buffer). Susan |
|
|
|
|
|
为什么需要这样做:当(SSP1STATBITS.BF== SpIrrxInIn进程)时,看起来像是对我的困惑,只使用0或false。SSP1STATBITS BF);
以上来自于百度翻译 以下为原文 Why do you need that: while(SSP1STATbits.BF == SPI_RX_IN_PROGRESS); Looks like a load of confusion to me, Just use 0 or false. Or while(!SSP1STATbits.BF); |
|
|
|
|
|
从属SPI缓冲器应该已经包含了为主机准备好的数据。不应该有任何冲突,只有1个主和1个从属。使用命令结构,以便主机向从属发送命令,例如从内存位置X发送10字节。
以上来自于百度翻译 以下为原文 The slave spi buffer should already contain the data ready for the master. You should not get any collisions, there is only 1 master and 1 slave. Use a command structure, so that the master sends a command to the slave such as send me 10 bytes from memory location x. |
|
|
|
|
|
问题不是主机太慢,而是奴隶一旦收到一个字节就太慢以至于不能断言PIN。我想我可以绕过一个中断级别的问题,在我进入某些选择的可中断中断的时候启用中断。然而,这仍然不允许在字节之间调用足够的时间来调用中断并切换LAT引脚。虽然CLC的想法很好,但是罪魁祸首ISR是高度优化的,但是应用程序的要点是PIC以尽可能快的速度进行采样和处理,所以我不能将处理移动到主循环。
以上来自于百度翻译 以下为原文 The problem is not the master being too slow, but the slave being too slow to assert the pin once a byte is received. I think I can get around the single interrupt level problem by enabling interrupts the moment I enter into certain chosen interruptible interrupts. However, that still doesn't allow enough time between bytes to call the interrupt and toggle the LAT pin. The CLC idea is working very well, though. The culprit ISR is highly optimized, but the point of the application is for the PIC to sample-and-process as fast as possible, so I can't move the processing to the main loop. |
|
|
|
|
|
GoRT:缓冲器只有1字节长。主不知道奴隶何时将第二字节放入缓冲区,因此不知道何时继续计时。除非你做了一些特别的事情,比如实现一个附加的控制线。碰撞是指在主控时钟开始一个字节而不是物理冲突之后,试图将一个字节写入SPI缓冲区。
以上来自于百度翻译 以下为原文 @Gort: The buffer is only 1 byte long. The master doesn't know when the slave has placed the second byte into the buffer, so it doesn't know when to continue clocking. Unless you do something special such as implementing an additional control line. The collision refers to trying to write a byte into the SPI buffer after the master has started clocking a byte, not a physical collision. |
|
|
|
|
|
|
|
|
|
|
|
这就是应该引起WCOL错误标志的确切情况。如果没有,或者还有别的事情发生,那就给Microchip加一张罚单,因为可能会有硅臭虫。苏珊
以上来自于百度翻译 以下为原文 That is the exact situation that is supposed to give rise to the WCOL error flag. If it is not or there is something else happening, then raise a ticket with Microchip as there could be a silicon bug. Susan |
|
|
|
|
|
除非使用协议,否则不应将任何东西放入从缓冲区。(握手)1。奴隶有一些数据准备中断到主人。2。M可以发送一个命令从S读取一个标志,看看有哪些数据可用。3。M发送命令来读取数据。4。S发送数据。5。M发送命令以清除S中断,以便S可以再次中断。(在中断标志被清除之前,从属者不能再中断)6。M可以睡觉,在中断时醒来,没有时间或延迟问题。
以上来自于百度翻译 以下为原文 You should not put anything into the slave buffer unless requested if using a protocol. (hand shaking) 1. The slave has some data ready - interrupt to master. 2. M can send a command to read a flag from S to see what data is available. 3. M sends command to read data. 4. S sends data. 5. M sends command to clear S interrupt so that S can interrupt again. (slave can not interrupt again until interrupt flag is cleared) 6. M can sleep, wakes up on interrupt. No timing or delay issues. |
|
|
|
|
|
在我看来,我们以前已经经历过很多次了。在PIC16/PIC18的情况下,没有办法让主机知道什么时候发送一个字节到SPI奴隶,这会导致从写到读的问题。为每个字节传输(由一些代码辅助,但不是完全由软件驱动),或者使用延迟,交叉手指和希望,或者提出一个协议来保证,如果你把时钟拨回给奴隶,它会以某种方式恢复。m所有的碰撞和错过的传输,你就能找出坏的好传输。我还没有看到那个协议。
以上来自于百度翻译 以下为原文 Seems to me we've been through this a number of times before. With the PIC16/PIC18, there's no way for the master to know when it's ok to send out a byte to the SPI slave which causes issues with both writing to and reading from the slave. You either have to generate a hardware handshake back to the master for each byte transfer (assisted by some code, but not totally software driven), or throttle the master using delays, crossing your fingers and hoping, or come up with a protocol that will guarantee that if you clock out transfers back to back to the slave it will somehow be able to recover from all the collisions and missed transfers and you'll be able to figure out the good transfers from the bad. I haven't seen that protocol yet. |
|
|
|
|
|
你看不远,这不是火箭科学。协议是必不可少的SPI COM。碰撞发生在写得很烂的代码。
以上来自于百度翻译 以下为原文 You have not looked far then and it's not rocket science. A protocol is essential in spi coms. Collisions occur in badly written code. |
|
|
|
|
|
它可能不是火箭科学,但它不像你说的那么容易。在赛后17号的赛跑区域的数量取决于时间。在适当的情况下,该代码将失败。如果你说你的代码对于主从定时的所有条件都有100%的作用,请务必发布它。
以上来自于百度翻译 以下为原文 It may not be rocket science, but it's not as easy as you say it is. There are a number of race conditions in post #17 that ARE timing dependent. That code will fail given the proper circumstances. If you say you have code that works 100% for all conditions of master/slave timing, by all means please post it. |
|
|
|
|
只有小组成员才能发言,加入小组>>
MPLAB X IDE V6.25版本怎么对bootloader和应用程序进行烧录
501 浏览 0 评论
5811 浏览 9 评论
2350 浏览 8 评论
2237 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3543 浏览 3 评论
1159浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
1120浏览 1评论
我是Microchip 的代理商,有PIC16F1829T-I/SS 技术问题可以咨询我,微信:A-chip-Ti
888浏览 1评论
MPLAB X IDE V6.25版本怎么对bootloader和应用程序进行烧录
501浏览 0评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-13 10:20 , Processed in 1.450689 second(s), Total 110, Slave 93 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
812