2015-04-30 54 views
0

我正在编写代码以在需要从另一个器件接收2个字节(16位)数据的PIC18F2680单片机的中断服务程序中接收SPI数据微控制器。 PIC只接收数据(被动收听),并且不向发送者返回任何内容。这两条数据线在设备上使用MISO和SCLK。在SPI通信中没有使用从机选择,而MOSI对于收听命令不是必需的,只有从机响应。我在设计时并没有意识到SPI数据包一次发送16位,否则我会使用不同的微控制器。PIC18F SPI从器件中断在4 MHz时接收多个字节问题

我想知道是否有办法在SPI ISR中读取两个连续的字节而不会丢失任何数据。我目前的实现:

OpenSPI(SLV_SSOFF,MODE_00,SMPMID); 

    //***********************************SPI ISR********************************* 
#pragma code InterruptVectorHigh = 0x08 
void InterruptVectorHigh (void) 
{ 
    _asm 
    goto InterruptHandlerHigh //jump to interrupt routine 
    _endasm 
} 

//---------------------------------------------------------------------------- 
// High priority interrupt routine 

#pragma code 
#pragma interrupt InterruptHandlerHigh 
void InterruptHandlerHigh() { 
    unsigned int next; 
    //the interrupt flag is set for SPI 
    if(PIR1bits.SSPIF ==1){ 
     spiByte1 = SSPBUF; 
     while(SSPSTATbits.BF != 0); 
     spiByte2 = SSPBUF; 
    } 
    PIR1bits.SSPIF = 0; 
} 

但是,这似乎得到了一些正确的数据,但失去了很多其他字节。有没有更好的方法来完成这个任务,还是我使用8位MCU的SOL?

谢谢

约翰

+0

while循环中的条件不是错误的吗?你不应该等到缓冲区满了(BF是1)吗?现在它等待直到BF == 0,这应该立即成立(即不等待)。 –

回答

0

SPI总线的本质是对称的,意味着SPI端口上的每个数据传输同时是变速器和主的前台。发送在MOSI线上的位和从设备读取它,而从设备在MISO线上发送一位数据,主设备读取它。即使只有单向数据传输的目的,这个序列仍然保持。

我已经实现了8,12和16位数据传输,但不作为中断代码,我觉得把它在一个纯粹的中断可能会有点棘手,但可能我

阅读是从以下当我无法理解SPI总线时,Microchip PIC对我非常有帮助。
Overview and Use of the PICmicro Serial Peripheral Interface

如果有帮助,我将与您分享一些代码,用于从连接到PIC的MAX6675 SPI器件读取12位温度值。这不是在一个中断中完成的,它只是你可以拥有的数百万个应用程序中的一个,我只是把它用得很方便,我在这里介绍它,因为如果你研究它,它可能会有一些帮助。

unsigned int spi_temp(void)   // Read the temp from MAX6675 connected to SPI output is (12bit) 
{ 
unsigned int spi_12bit;    // specify an int so can hold the 12bit number 
CHIP_EN = 0 ;      // Enable SPI on MAX6675. (When Low enables the Max6675 and stops any conversion process) 
__delay_ms(1);      // Small delay required by MAXX6675 after enabling CS (Chip Select) 
SSPIF = 0;      // Clear Master Synchronous Serial Port Flag 
spi_12bit = SSPBUF;     // Read Buffer to clear it and to reset the BF Flag 
SSPBUF = 0b10101010;    // Loading the Buffer with some data junk to start transmision (We're not sending them anywhere) 

while (!SSPIF) continue;   // wait until data is clocked out 
spi_12bit = (0b01111111 & SSPBUF)<<8; // Read the Buffer with the fresh first 8bit DATA from MAX6675 
             // disregard MSB bit of unimportant data and shift it left 
SSPIF = OFF;      // Clear Flag to get ready for the next 8bit DATA 

SSPBUF = 0b10101010;    // Load the Buffer with more junk data 
while (!SSPIF) continue;   // wait until data is clocked out 
SSPIF = OFF;      // Clear the Flag 

spi_12bit = spi_12bit | SSPBUF;  // Read the Buffer with the other 8bit data and keep it as a 16bit variable 
spi_12bit = spi_12bit >>3;   // We disregard the leftmost 3 bits on unimportant Data according to Datasheet 
CHIP_EN = 1 ;      // disabling CS (Chip Select). Let MAX6675 continue conversion processreading 
delay_200ms(1);      // Small delay required by MAXX6675 to do conversion typ 0.2sec 
spi_12bit = (int)(spi_12bit * 0.25);//(reading in 12bit * 1024 total steps/4096; 
return spi_12bit; 

} // spi_temp 

这只是一个例子,希望能对SPI的工作原理有所帮助。