从PIC18中的I2C从协议中的变量写入SSPBUF

时间:2016-08-10 10:11:34

标签: pic i2c slave

我正在为PIC18F25K80编写I2C从机例程,我遇到了一个奇怪的问题。

这是我的惯例:

void interrupt interruption_handler() {
PIE1bits.SSPIE = 0; // Disable Master Synchronous Serial Port Interrupt

if (PIR1bits.SSPIF != 1) {
    //This is not I2C interruption;
    PIE1bits.SSPIE = 1; // Enable Master Synchronous Serial Port Interrupt
    return;
}

//Treat overflow
if ((SSPCON1bits.SSPOV) || (SSPCON1bits.WCOL)) {
    dummy = SSPBUF; // Read the previous value to clear the buffer
    SSPCON1bits.SSPOV = 0; // Clear the overflow flag
    SSPCON1bits.WCOL = 0; // Clear the collision bit
    SSPCON1bits.CKP = 1;
    board_state = BOARD_STATE_ERROR;
} else {
    if (!SSPSTATbits.D_NOT_A) {
        //Slave address
        debug(0, ON);
        //Read address 
        address = SSPBUF; //Clear BF
        while(BF); //Wait until completion
        if (SSPSTATbits.R_NOT_W) {
            SSPCON1bits.WCOL = 0;
            unsigned char a = 0x01;
            SSPBUF = a;//0x01 works //Deliver first byte
            asm("nop");
        }
    } else {
        if (SSPSTATbits.BF) {
            dummy = SSPBUF; // Clear BF (just in case)
            while(BF);
        }
        if (SSPSTATbits.R_NOT_W) {
            //Multi-byte read
            debug(1, ON);
            SSPCON1bits.WCOL = 0;
            SSPBUF = 0x02; //Deliver second byte
            asm("nop");
        } else {
            //WRITE
            debug(2, ON);
        }
    }
    transmitted = TRUE;
    SSPCON1bits.CKP = 1;
    PIR1bits.SSPIF = 0;

    PIE1bits.SSPIE = 1; // Enable Master Synchronous Serial Port Interrupt
}
}

如果我在SSPBUF上设置常量值,它就像一个魅力。例如,如果你这样做:

SSPBUF = 0x01;
(...)
SSPBUF = 0x02;

我在主服务器上获得了两个字节。我甚至可以看到在示波器上传输的字节的波形。很有趣!

但是当我尝试使用如下变量设置SSPBUF时:

unsigned char a = 0x01;
SSPBUF = a;

我在主人身上得到零。

这让我发疯了。

我放弃了一些假设:

  1. 看门狗定时器正在搞乱协议中间的中断:事实并非如此。它被禁用,并且在SSPBUF分配中都会出现问题
  2. 我需要等到BF继续下去才能继续:我没有。 AFAIK,您设置SSPBUF,清除SSPIF,设置CKP并从中断返回以处理4Mhz的寿命,同时硬件以几Khz发送数据。完成后它会再次打断你。
  3. 对我来说没有意义。如果你不能使用变量定义任意值,那有多好?

    请那里的大师,启发这位可怜的程序员。

    提前致谢。

2 个答案:

答案 0 :(得分:0)

它与编译器如何生成代码以及SSPBUF周围的一些未记录/未知的PIC限制有关(无论如何它都是一个特殊的寄存器)。

我发现它在编译器使用movwf时有效,而在编译器使用movff时不起作用。

我将问题转移到另一个论坛,因为我意识到那里的观众更充足。

您可以在此处找到更多详细信息: https://electronics.stackexchange.com/questions/251763/writing-sspbuf-from-variable-in-i2c-slave-protocol-in-pic18/251771#251771

答案 1 :(得分:0)

  1. 尝试移动声明:“unsigned char a = 0x01;” 到函数的开头或尝试将其定义为volatile全局变量。
  2. 认识到SSPBUF是读写缓冲区。检查是否存在可能导致I2C模块重置此缓冲区的条件。