SPI等待问题

[复制链接]
3319|17
 楼主| aaa2742 发表于 2010-10-22 08:59 | 显示全部楼层 |阅读模式
static void WR_CMD (unsigned char cmd)  
{
  /* Wait for SPI1 Tx buffer empty */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
  //int i;
  //while(SPI1->SR & 0x0002 == 0);
  //for(i = 0;i<5;i++);
  /* Send SPI1 data */
  SPI_I2S_SendData(SPI1,cmd);
  /* Wait for SPI1 data reception */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
  //while(SPI1->SR & 0x0001 == 0);
  //for(i = 0;i<5;i++);
  /* Read SPI1 received data */
  SPI_I2S_ReceiveData(SPI1);
}为什么不用库函数直接用寄存器等待就运行不了?
jgphu 发表于 2010-10-22 12:58 | 显示全部楼层
SPI等待就读BUSY位就好了啊。
jgphu 发表于 2010-10-22 12:58 | 显示全部楼层
SPI等待就读寄存器中的BUSY位就好了啊。
 楼主| aaa2742 发表于 2010-10-22 14:03 | 显示全部楼层
为什么会这样:)
香水城 发表于 2010-10-22 14:05 | 显示全部楼层
什么现象?
 楼主| aaa2742 发表于 2010-10-25 13:21 | 显示全部楼层
调用系统的查询标志函数,在那等待运行结果就正确。但是直接操作寄存器查询运行就不正常?
jgphu 发表于 2010-10-25 18:09 | 显示全部楼层
既然你调用系统的查询标志函数是可行的,直接读寄存器就也是可行的,如果不可行,请贴出这个地方的程序。
 楼主| aaa2742 发表于 2010-10-26 08:53 | 显示全部楼层
就是一开始贴的地方,画横线的是库函数,方框是直接读寄存器,改为直接读寄存器运行结果不正确,读BUSY也不行。
spi.jpg
jgphu 发表于 2010-10-26 09:49 | 显示全部楼层
看不懂你的程序。
帮你理清一下逻辑
1、while(BUSY == 0); //表示SPI总线空闲.
2、SPI_I2S_SendData(SPI,cmd);
3、while(TXE == 0);
4、SPI_I2S_ReceiveData(SPI1);
5、while(RXNE == 0);

想问一下你的SPI是和什么器件通信。
jgphu 发表于 2010-10-26 09:50 | 显示全部楼层
看不懂你的程序。
帮你理清一下逻辑
1、while(BUSY == 1); //表示SPI总线空闲.
2、SPI_I2S_SendData(SPI,cmd);
3、while(TXE == 0);
4、SPI_I2S_ReceiveData(SPI1);
5、while(RXNE == 0);

想问一下你的SPI是和什么器件通信。
 楼主| aaa2742 发表于 2010-10-26 11:46 | 显示全部楼层
和ADS7843
jgphu 发表于 2010-10-26 11:51 | 显示全部楼层
你和ADS7843这样通信肯定会出问题的。

1、while(BUSY == 1); //表示SPI总线空闲.
2、SPI_I2S_SendData(SPI,cmd);
3、while(BUSY == 1); //表示SPI总线空闲.
4、while(7843BUSY == 1); //等待7843的BUSY引脚。也可以去掉这步
5、SPI_I2S_SendData(SPI,0x00);
6、while(BUSY == 1); //表示SPI总线空闲.
7、SPI_I2S_ReceiveData(SPI1);
8、SPI_I2S_SendData(SPI,0x00);
9、while(BUSY == 1); //表示SPI总线空闲.
10、SPI_I2S_ReceiveData(SPI1);
这样才会正确接收坐标,压力等触摸屏信息
jgphu 发表于 2010-10-26 11:52 | 显示全部楼层
你要好好看看7843那个协议,用示波器测SPI,严格按照那个协议来写程序。
 楼主| aaa2742 发表于 2010-10-26 13:49 | 显示全部楼层
static void WR_CMD (unsigned char cmd)  
{
  /* Wait for SPI1 Tx buffer empty */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
  /* Send SPI1 data */
  SPI_I2S_SendData(SPI1,cmd);
  /* Wait for SPI1 data reception */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
  /* Read SPI1 received data */
  SPI_I2S_ReceiveData(SPI1);
}
我这样写就可以的。
我说的判忙标志都是指的是stm32的。
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
这一句如果改为直接操作寄存器,还有下面的判忙改为直接读寄存器,那么运行结果就不对。
而直接用库函数就正确.
?????
jgphu 发表于 2010-10-26 14:04 | 显示全部楼层
你用库函数这样写能正常接收到触摸屏的坐标信息???
 楼主| aaa2742 发表于 2010-10-26 15:56 | 显示全部楼层
是的,直接用寄存器就不行了
香水城 发表于 2010-10-26 17:28 | 显示全部楼层
由于AHB与APB之间桥的延迟,还有CM3核心的流水线效应,设置寄存器到器件中真正做动作之间很可能会有延迟。估计这就是你看到的现象,库函数调用引入了等待延迟,导致结果正确,但直接寄存器操作没有等待延迟,导致结果错误。

所以可以尝试在等待循环之前和之后,增加一些小的延迟(最多4个CPU周期),这样应能解决问题。
 楼主| aaa2742 发表于 2010-10-27 08:39 | 显示全部楼层
17# 香水城
你说的这种解释我是理解的,我也考虑过延时的问题,所以在第一次贴图的时候,我在后面加了一个for,我想问一下是不是延时加的太短或者比你说的长点,也是不可以的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

217

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部