打印
[STM32F1]

SPI的中断发送奇怪问题

[复制链接]
2951|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sfesdm|  楼主 | 2014-4-30 23:45 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 sfesdm 于 2014-5-3 00:37 编辑

在调试STM32F103与W25X64通信的时候,如果不开中断,用查询的方式通信,比如读取器件ID,通信是没问题的。但是使用中断的方式通信,接收到的数据就全都是0XFF,通过逻辑分析仪观察数据,发现中断发送出去的数据(命令)有问题,具体情况如下:

  读取器件ID发送的命令


中断发送的程序如下:

读取器件ID调试程序
void ReadDeviceID(void)
{
        SPI.start    = SPI.sendbuf;
        SPI.end     = SPI.sendbuf+6;
        SPI.sendbuf[0] = 0x90;
        SPI.sendbuf[1] = 0x00;
        SPI.sendbuf[2] = 0x00;
        SPI.sendbuf[3] = 0x00;
        SPI.sendbuf[4] = 0xff;
        SPI.sendbuf[5] = 0xff;
        SPI.recv    = 0;//保存接收到的数据
        GPIO_ResetBits(GPIOB,GPIO_Pin_12);//拉低FCS
        Delay(10);
        SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_TXE,ENABLE); //打开发送中断
        Delay(1000);  //等待通信完成
        GPIO_SetBits(GPIOB,GPIO_Pin_12);//拉高FCS
}


void SPI2_IRQHandler(void)
{
        if(SPI_I2S_GetITStatus(SPI2,SPI_I2S_IT_TXE) != RESET)
        {
                if(SPI.start < SPI.end)
                {
                        SPI_I2S_SendData(SPI2,SPI.sendbuf[*SPI.start]);
                        SPI.start++;
                       SendLen++;  //计算发送次数
                }
                else
                {
                        SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_TXE,DISABLE); //发送完成,关闭发送中断
                }
        }
        
        if(SPI_I2S_GetITStatus(SPI2,SPI_I2S_IT_RXNE) != RESET)
        {
                SPI.readbuf[SPI.recv] = SPI_I2S_ReceiveData(SPI2);
                SPI.recv++;
                RecvLen++;  //计算接收次数
        }
}


逻辑仪观察到的结果



通过观察,发现用于统计发送次数和接收次数的变量,都是相等的。也就是说,有发送,就有接收,而且都是发送6个数据,就接收到6个数据。
但是纳闷的是,通过逻辑仪观察到的结果,发送的第1个数据是0,第2、3、4个数据都是0x90,第5、6个数据本应是0xff的,却又变为0了。
程序的其它地方并没有对SPI.sendbuf进行任何改变,在SPI通信完成后,通过串口把SPI.sendbuf打印出来看到也确实如此。如果是配置有问题,查询方式的通信也应该有问题吧!

请教香主,这样的问题应该从何分析呢?谢谢了!



对不起,我犯了个弱智的错误: SPI.start    = SPI.sendbuf;
然后SPI_I2S_SendData(SPI2,SPI.sendbuf[*SPI.start]);
应该是SPI_I2S_SendData(SPI2,*SPI.start);


此帖不删前面的内容,引以为戒!结帖了。



沙发
gufeng1| | 2014-5-1 12:09 | 只看该作者

还有逻辑分析仪

使用特权

评论回复
板凳
香水城| | 2014-5-1 22:12 | 只看该作者
你在“SPI_I2S_SendData(SPI2,SPI.sendbuf[*SPI.start]);”的地方用某个空闲GPIO toggle一下,然后和MOSI、MISO一起拉出来在示波器上看,我估计调用SendData()的时刻不是你想的那样。

使用特权

评论回复
地板
mmuuss586| | 2014-5-1 22:40 | 只看该作者
语法使用不严谨,该加括号的地方就加吧。

使用特权

评论回复
5
mmuuss586| | 2014-5-1 22:51 | 只看该作者
发送的*去掉看看。

使用特权

评论回复
6
sfesdm|  楼主 | 2014-5-2 00:46 | 只看该作者
我在中断程序里的发送、接收那里分别取反一个脚位,然后观察结果,程序改动的地方如下:
SPI_I2S_SendData(SPI2,SPI.sendbuf[*SPI.start]);
GPIOB->ODR ^= (1<<6);  //取反


SPI.readbuf[SPI.size] = SPI_I2S_ReceiveData(SPI2);
GPIOB->ODR ^= (1<<7);  //取反
然后看到波形如图下:

对此图的分析是:
1、第一条红线那里,是刚打开发送中断。因为SPI->DR为空,所以马上进入中断,把数据移到DR里面,而且又马上给移到移位寄存器里面开始发送。所以此时DR又为空了,因此再次进入中断,把第二个数据移到DR里面。所以看到第一、二条红线的时间间隔比较短。
2、第三条红线,是因为接收到了一个数据,并且把数据移到接收DR里面了,所以进入中断,它的波形宽度都一样。
3、第一、二条红线的时间宽度,跟第二、四条红线的时间宽度相差那么大,是因为第一、二条的时间宽度如步骤1所描述的那样。而第二、四条红线的时间宽度,是因为第一个数据在发送时,DR不为空。等到第一个数据发送完成后,DR把数据传送到移位寄存器了,DR变空,才再次进入中断,如此循环。

所以,根据以上的时序分析,发送程序应该是没问题的。我也怀疑SPI.start这个指针在操作的时候,会不会发生无法预料的变化,所以就改了一下程序,把每次发送中断里的这个变量保存起来
SPI_I2S_SendData(SPI2,SPI.sendbuf[*SPI.start]);
GPIOB->ODR ^= (1<<6);  //取反
addr[SPI.start + 6 - SPI.end] = SPI.start; //保存地址

然后通过串口打印出来,结果发现没有问题。。。所以,搞不懂了。我在网上搜SPI的中断发送例程,但找到的都是用查询方式操作的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

346

帖子

3

粉丝