ST意法半导体
直播中

钟晶

7年用户 183经验值
私信 关注
[问答]

SPI从机模式出现故障

SPI从机模式出现故障

以上来自于谷歌翻译


以下为原文



SPI slave mode malfunctioning

回帖(2)

钟晶

2019-7-11 12:11:00
嗨,
 
 
我们在从机模式下使用STM8S208 SPI。配置如下:
- 全双工
- MSBFirst
- CPOL:0
- CPHA:1
 
SPI配置代码:
 
码:
 
void SPI_Init(void)
{
 / *将SPI外设寄存器取消初始化为其默认复位值* /
 SPI-> CR1 = SPI_CR1_RESET_VALUE;
 SPI-> CR2 = SPI_CR2_RESET_VALUE;
 SPI-> ICR = SPI_ICR_RESET_VALUE;
 SPI-> SR = SPI_SR_RESET_VALUE;
 SPI-> CRCPR = SPI_CRCPR_RESET_VALUE;
 
 / * CLK_PCKENR1配置为hw_Init()中的SPI的门控时钟* /
 
 / *空闲时时钟极性为0 /
 SPI-> CR1 | =(u8)(SPI_CLOCKPOLARITY_LOW);
 
 / *时钟相位 - 第二个时钟转换是第一个数据捕获边缘* /
 SPI-> CR1 | =(u8)(SPI_CLOCKPHASE_2EDGE);
 
 / *从属模式配置* /
 SPI-> CR1 | =(u8)(SPI_MODE_SLAVE);
 
 / *帧格式:MSB优先* /
 SPI-> CR1 | =(u8)(SPI_FIRSTBIT_MSB);
 
 / * RX缓冲区不空中断使能* /
 SPI-> ICR | =(u8)(RX_BUF_NE_INT);
}
 
 
在主方面,我们有微芯片的主板。由主机发送的数据(MOSI,CLK和CS的所有输入波形)在CRO上验证其真实性和安全性。定时。
 
正如STM8S参考手册所述,主机配置的时钟极性和相位设置与从机相同。
 
STM8S SPI ISR如下:
 
码:
 
 
@near @interrupt void SPI_IRQHandler(void)
{
 
 if(SPI-> SR& SPI_SR_RXNE)/ *检查是否设置了接收缓冲区非空标志* /
 {
 开关(SPI-> DR)
 {
 案例0x12:
 GPIOH-> ODR ^ = GPIO_PIN_3; / *切换LED1 * /中断;
 
 案例0x24:
 GPIOH-> ODR ^ = GPIO_PIN_2; / *切换LED2 * /
 打破;
 
 案例0x36:
 GPIOH-> ODR ^ = GPIO_PIN_1; / *切换LED3 * /
 打破;
 
 案例0x48:
 GPIOH-> ODR ^ = GPIO_PIN_0; / *切换LED4 * /
 打破;
 }
 
 
 
这里有一种特殊的情况。
 
由主机顺序发送这4个数据总线,所有LED间歇性地发光较少。但是,如果发送的数据包是0x24,0xAA,0xFF& 0x55,然后只识别第一个数据字节并且相应的LED发光。所有其他数据字节在长时间后被识别,因此永远不会识别出0xFF。因此,其他LED不会经常发光。
 
当使用调试器检查时,我们观察到OVR标志(有时是BSY标志)持续开启。我们尝试了与SPI主设备(500 KHZ和1MHz)不同的低频率,并且还在连续数据字节之间设置了延迟。但这并没有太大的不同。
 
请告诉我们我们缺少什么?还有什么我们需要照顾的吗?
 
问候,
-su

以上来自于谷歌翻译


以下为原文




Hi,


We are using STM8S208 SPI in slave mode. Configuration as follows:  
- Full Duplex  
- MSBFirst  
- CPOL: 0  
- CPHA: 1  

SPI configuration code:  

Code:



void SPI_Init(void)  
{  
/* Deinitialize the SPI peripheral registers to their default reset values */  
SPI->CR1 = SPI_CR1_RESET_VALUE;  
SPI->CR2 = SPI_CR2_RESET_VALUE;  
SPI->ICR = SPI_ICR_RESET_VALUE;  
SPI->SR = SPI_SR_RESET_VALUE;  
SPI->CRCPR = SPI_CRCPR_RESET_VALUE;  

/* CLK_PCKENR1 is configured for gate clock for SPI in hw_Init() */  

/* Clock polarity 0 when idle */  
SPI->CR1 |= (u8)(SPI_CLOCKPOLARITY_LOW);  

/* Clock phase – the second clock transition is the first data capture edge */  
SPI->CR1 |= (u8)(SPI_CLOCKPHASE_2EDGE);  

/* Slave mode configuration */  
SPI->CR1 |= (u8)(SPI_MODE_SLAVE);  

/* Frame format: MSB first */  
SPI->CR1 |= (u8)(SPI_FIRSTBIT_MSB);  

/* RX buffer not empty interrupt enable */  
SPI->ICR |= (u8)(RX_BUF_NE_INT);  
}  


On the master side, we have microchip's board. The data(all input waveforms for MOSI, CLK & CS) send by the master is verified on a CRO for its autheticity & timing.  

As the STM8S ref manual says, the master is configured with the same settings for clock polarity and phase as done on the slave.  

The STM8S SPI ISR is as follows:  

Code:




@near @interrupt void SPI_IRQHandler(void)  
{  

if(SPI->SR & SPI_SR_RXNE) /* Check if Receive buffer not empty flag is set */  
{  
switch(SPI->DR)  
{  
case 0x12 :  
GPIOH->ODR ^= GPIO_PIN_3; /* Toggle LED1 */ break;  

case 0x24 :  
GPIOH->ODR ^= GPIO_PIN_2; /* Toggle LED2 */  
break;  

case 0x36 :  
GPIOH->ODR ^= GPIO_PIN_1; /* Toggle LED3 */  
break;  

case 0x48 :  
GPIOH->ODR ^= GPIO_PIN_0; /* Toggle LED4 */  
break;  
}  



There is a peculiar situation here.  

With these 4 databytes sent sequentially by the master, all LEDs glow less intermittently. However if the databytes sent are 0x24, 0xAA, 0xFF & 0x55, then only the first databyte is recognized and corresponding LED glows. All the other databytes are recognized after long durations, infact 0xFF is never recognized. Thus other LEDs don't glow often.  

When checked using debugger, we observe the OVR flag(& sometimes the BSY flag) is continously on. We tried differently low frequecies from SPI master(500 KHZ and 1MHz) and also put delays between successive data bytes. But this doesn't make much differnce.  

Please let us know what are we missing? Is there anything else that we need to take care of?  

Regards,  
-SU
举报

陈畅妮

2019-7-11 12:21:26
嗨Sandeep,
 
 
在全双工通信中,主设备施加时钟频率。
 
代码行为:
在SPI从机中断中,您需要在主文件中执行一些步骤(开关循环),因为当SPI主机连续发送数据时,SPI从机接收SPI数据寄存器中的第一个数据字节,然后执行中断。从机执行中断,在数据寄存器中接收但未读取OVR标志的其他数据被置位,从机停止接收数据,直到清除OVR标志。
 
解决方法1:
在代码中使用全局变量并仅在中断向量中保持跟随:
@near @interrupt void SPI_IRQHandler(void)
{
 data_received = SPI-> DR;
}
 
溶液2:
使用GPIO在主机和从机之间进行同步:在接收数据字节后,从机设置I / O以指示它在发送下一个字节之前接收到I / O上主机白色的另一侧的数据
 
Solution3:
检测到溢出中断时清除OVR标志;在这种情况下,您丢失了数据
 
问候
mozra

以上来自于谷歌翻译


以下为原文




Hi Sandeep,


In full duplex communication the master impose the clock frequency.  

Code behavior:  
In the SPI slave interrupt you have some steps (switch loop) that should be done in the main file because when the SPI Master send data in continuous the SPI slave receive the first data byte in the SPI data register and then execute the interrupt, when the slave execute the interrupt an other data received in the data register but not read the OVR flag is set and the slave stop receiving data until clearing the OVR flag.  

Solution1:  
Use global variable in your code and keep only following in interrupt vector:  
@near @interrupt void SPI_IRQHandler(void)  
{  
data_received = SPI->DR;  
}  

Solution2:  
Use GPIO to synchronize between master and slave: after receiving data byte the slave set I/O to indicate that it received the data in the other side the master whiting on the I/O before sending the next byte  

Solution3:  
Clear the OVR flag when detecting an overrun interrupt; in this case you lost data  

Regards  
mozra
举报

更多回帖

发帖
×
20
完善资料,
赚取积分