pic中断变化不会在第一时间触发

时间:2016-02-15 09:51:30

标签: interrupt pic

我试图用一个arduino 101通信pic18f24k50。我使用两行来建立同步通信。在第一行从低到高的每次变化中,我从第二行读取值。 我对arduino代码没有任何问题,我的问题是在pic中,Interrupt on change触发第二次从低变为高而不是触发第一次变化。这仅在我第一次发送数据时发生,之后,它完美地工作(它在第一次更改时触发,我正确地接收到该字节)。对不起我的英语,我会尝试用这张图片更好地解释自己:

enter image description here

通道1是时钟信号,通道2是数据(Im暂时发送一个字节,位值为10101010)。通道4是每次处理一位时改变的输出I。 (正如你所看到的,它开始于时钟信号的第二次上升而不是第一次上升)。这是在第一个发送的字节上捕获的,下一个可以正常工作。

我在图片中发布相关代码:

这是我初始化的地方:

TRISCbits.TRISC6 = 0;
TRISCbits.TRISC1 = 1;
TRISCbits.TRISC2 = 1;
IOCC1 = 1;
ANSELCbits.ANSC2=0;
IOCC2 = 0;
INTCONbits.IOCIE = 1;
INTCONbits.IOCIF = 0;

这是关于中断代码的:

void interrupt SYS_InterruptHigh(void)
{
    if (INTCONbits.IOCIE==1 && INTCONbits.IOCIF==1)
    {
          readByte();
    }
}

void readByte(void)
{
while(contaBits<8)
{
    INTCONbits.IOCIE = 0;
    INTCONbits.IOCIF = 0;

    while (PORTCbits.RC1 != HIGH)
    {
    }    

    if (PORTCbits.RC1 == HIGH)
    {

            LATCbits.LATC6 = !LATCbits.LATC6;


        //LATCbits.LATC6 = ~LATCbits.LATC6;
        switch (contaBits)
        {
            case 0:
                if (PORTCbits.RC2 == HIGH)
                    varByte.b0 = 1;
                else
                    varByte.b0 = 0;
                break;
            case 1:
                if (PORTCbits.RC2 == HIGH)
                    varByte.b1 = 1;
                else
                    varByte.b1 = 0;
                break;    
            case 2:
                if (PORTCbits.RC2 == HIGH)
                    varByte.b2 = 1;
                else
                    varByte.b2 = 0;
                break;
            case 3:
                if (PORTCbits.RC2 == HIGH)
                    varByte.b3 = 1;
                else
                    varByte.b3 = 0;
                break;
            case 4:
                if (PORTCbits.RC2 == HIGH)
                    varByte.b4 = 1;
                else
                    varByte.b4 = 0;
                break;
            case 5:
                if (PORTCbits.RC2 == HIGH)
                    varByte.b5 = 1;
                else
                    varByte.b5 = 0;
                break;
            case 6:
                if (PORTCbits.RC2 == HIGH)
                    varByte.b6 = 1;
                else
                    varByte.b6 = 0;
                break;
            case 7:
                if (PORTCbits.RC2 == HIGH)
                    varByte.b7 = 1;
                else
                    varByte.b7 = 0;
                break;
        }

        contaBits++;
    }

}//while(contaBits<8)
INTCONbits.IOCIE = 1;
contaBits=0;
}

LATCbits.LATC6 =!LATCbits.LATC6; &lt; - 这是与通道4对应的行。

RC1是第1频道 和RC2是通道2

我的问题是我做错了什么,为什么在第一次发送的字节中,中断在第1行的第一次更改时没有触发?

谢谢。

2 个答案:

答案 0 :(得分:0)

您想要实现的目标是什么?

您所描述的通信协议通常称为SPI (Serial Peripheral Interface)。如果可能,应使用PIC / Microchip提供的硬件实现,以获得最佳性能。

保持代码记录/格式化/逻辑

我注意到你的代码有点奇怪。 奇怪的代码会产生奇怪的错误。

第一: 你正在使用中断,你的中断中有这个阻塞代码。这根本不好。

第二: 你的“contabits”和“varByte”变量无处不在,可能它们是全球性的。这可能不是最好的做法。 但是,如果您正在使用中断,并且通过使用全局将变量传输到主程序可能是有意义的。全局应为volatile

第三: 那个案例开关只是相同代码的8倍,但有点不同。

另外,在代码中添加一些注释。

说实话

我没有发现你的实际错误,自从我使用PIC以来已经很久了。 但是,你应该尝试硬件SPI。

下面是我对你所描述的软件SPI的尝试,它可能更合乎逻辑,并且可以解除对中断的任何烦恼。

我建议将while(CLOCK_PIN_MACRO != 1){};替换为for(unsigned int timeout = 64000; timeout > 0; timeout--){};。 因此,您可以确保您的程序在等待不会发出的SPI信号时不会挂起。 (使超时适合您的需要)

#define CLOCK_PIN_MACRO PORTCbits.RC1 
#define DATA_PIN_MACRO PORTCbits.RC2

/*
Test, without interrupts.
I would strongly advise to use Hardware SPI or non-blocking code.
*/

unsigned char readByte(void){
    unsigned char returnByte = 0;
    for(int i = 0; i < 8; i++){             //Do this for bit 0 to 7, to get a complete byte.
        while(CLOCK_PIN_MACRO != 1){};      //Wait until the Clock pin goes high.
        if(DATA_PIN_MACRO == 1)             //Check the data pin.
        returnByte = returnByte & (1 << i); //Shift the bit in our byte. (https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/bitshift.html)
        while(CLOCK_PIN_MACRO == 1){};      //Wait untill the Clock pin goes low again.
    }
    return returnByte;
}

void setup(){
    TRISCbits.TRISC6 = 0;
    TRISCbits.TRISC1 = 1;
    TRISCbits.TRISC2 = 1;
    //IOCC1 = 1;
    ANSELCbits.ANSC2=0;
    //IOCC2 = 0;
    INTCONbits.IOCIE = 1;
    INTCONbits.IOCIF = 0;
}

void run(){
    unsigned char theByte = readByte();
}

main(){
    setup();
    while(1){
     run();
    }
}

答案 1 :(得分:0)

您可以从数据表中找到以下内容。

  

将引脚与上次读取时锁存的旧值进行比较   PORTB。 &#34;不匹配&#34; RB7:RB4的输出进行“或”运算以生成   RB端口改变中断,带标志位RBIF(INTCON&lt; 0&gt;)。

这意味着当您读取PORTB RB7:RB4引脚时,每个引脚的值将存储在内部锁存器中。只有当引脚输入与先前锁存的值发生任何变化时,才会产生中断。

然后,锁存器中的默认初始值是什么?即在我们从PORTB阅读任何内容之前。

它是什么。在您的情况下,默认锁存器值与输入信号的逻辑状态不同。在信号的下一次转换期间,锁存值和信号电平变得相同。所以第一次没有产生中断。

您可以做的是将锁存值设置为信号的初始状态。这可以通过读取PORTB来完成(应该在启用中断之前完成)。

以下代码足以简单地读取寄存器。

unsigned char ch;
ch = PORTB;

希望这会有所帮助。