在103项目中,原来SPI中断部分接收数据的程序如下(代码以简化):
void interrupt ISR(void)
{
GIE=1;
SSPIF=0;
Byte0=SSPBUF;
while(SSPIF==0);
SSPIF=0;
Byte1=SSPBUF;
while(SSPIF==0);
SSPIF=0;
Byte2=SSPBUF;
while(SSPIF==0); //这行代码多余,应该去掉
SSPIF=0; //这行代码多余,去掉
command=0; //收发标志位
GIE=1;
}
以上程序有两行是多余的程序,导致收发数据不正确;根据从模式时序,当主芯片时钟启动时,从SPI启动接收和发送,一个字节的八个时钟结束后SSPIF置1,产生中断,此时SPI收到一个字节,且发送出一个字节;当第三个字节的时钟跑完时,第三个字节接收完毕。此时接收命令的三个字节就完成了,而原程序在第三个字节接收完毕后执行了while(SSPIF==0);此时SSPIF在读取SSPBUF之前就已经置0了,又执行while(SSPIF==0);那么程序就会死在这个地方,等以后时钟再启动时程序才可以继续运行,这就会导致收发错误。
原SPI发送数据程序如下(部分):
void interrupt ISR(void)
{
GIE=1;
SSPBUF=0x11;
while(BF==0);
。。。。。。。。。
。。。。。。。。。
while(BF==0);
SSPBUF=0xbb; //发送最后一个字节数据
command=0;
GIE=1;
}
当程序将最后一个要发送的字节0xbb给出后,SSPBUF=0xbb;最后一个数据主SPI要想成功接收,主SPI必须接着运行一个字节的时钟,也就是说要发送的数据是在时钟之前给出的,那么如果将0xbb给出后就马上退出中断就会有问题了,因为在0xbb给了SSPBUF后时钟启动,这是才启动最后这个字节的发送与接收,当八个CLK结束后0xbb被成功发送置主SPI,那同时SSPIF被置1,BF被置1,此时程序已经退出中断了,而SSPIF=1则在实际上没有接收到新数据的情况下就会产生中断,程序在没有收到新数据的情况下又一次进入中断,一起收发数据错误。
更改后程序为:
void interrupt ISR(void) //接收主芯片下发的三个字节的命令
{
GIE=0;
SSPIF=0;
Byte0=SSPBUF;
while(SSPIF==0);
SSPIF=0;
Byte1=SSPBUF;
while(SSPIF==0);
SSPIF=0;
Byte2=SSPBUF; //去掉两行多余代码
GIE=1;
}
void interrupt ISR(void) //向主芯片返回数据
{
GIE=0;
SSPBUF=0x11;
while(BF==0);
......
......
SSPBUF=0xbb;
while(BF==0); //等待,等主时钟八个CLK后将最后一个字节接收完毕后将SSPIF清零
SSPIF=0; //此时再退出中断
command=0;
GIE=1;
}
阅读(1164) | 评论(0) | 转发(0) |