发新帖我要提问
12
返回列表
打印

请教香主、各位同道一个SPI通信的问题(急切)

[复制链接]
楼主: angryBird
手机看帖
扫描二维码
随时随地手机跟帖
21
easy_tm| | 2013-10-8 10:13 | 只看该作者 回帖奖励 |倒序浏览
注意哦,你Slave端接收后并不是发送数据,而是准备数据,等Master去读,也就是说在主机发起一次Byte传输前,slave的数据必须已经放入发送buffer了,你把master和slave的中断贴上来看看

使用特权

评论回复
22
easy_tm| | 2013-10-8 10:15 | 只看该作者
有示波器的话量下波形,应该就能定位问题在哪了

使用特权

评论回复
23
huzi2099| | 2013-10-8 10:23 | 只看该作者
MOSI和MISO一个是输出,一个是输入,初始化io那段感觉不对啊.

使用特权

评论回复
24
angryBird|  楼主 | 2013-10-8 20:23 | 只看该作者
easy_tm 发表于 2013-10-8 10:13
注意哦,你Slave端接收后并不是发送数据,而是准备数据,等Master去读,也就是说在主机发起一次Byte传输前 ...

slave端的中断处理函数,本意是在中断中接收master数据,主程序解析收到的数据,根据不同的解析,来回复给master不同的应答。所以,我在这里只做了接收数据,放到buffer里面。主循环中,调用的发送函数。

void SPIx_IRQHANDLER(void)
{
  uint8_t n;
  
  /* SPI in Slave Receiver mode--------------------------------------- */
  if (SPI_I2S_GetITStatus(SPIx, SPI_I2S_IT_RXNE) == SET)
  {
    RxBuffer[Rx_Idx++] = SPI_I2S_ReceiveData(SPIx);
    if(Rx_Idx==BUFFERSIZE)Rx_Idx=0;
  }
}

master端,是个简单的配合测试程序,在主循环中,连续发送50个0xff。同时打开中断,在中断中接收数据。

使用特权

评论回复
25
angryBird|  楼主 | 2013-10-8 20:24 | 只看该作者
easy_tm 发表于 2013-10-8 10:13
注意哦,你Slave端接收后并不是发送数据,而是准备数据,等Master去读,也就是说在主机发起一次Byte传输前 ...

你说的准备数据,放到buffer里面,这个buffer是什么?
我理解的,是把一个字节的数据,放到 spi->DR寄存器里面,也就是发送函数做的事情。

使用特权

评论回复
26
angryBird|  楼主 | 2013-10-8 20:26 | 只看该作者
huzi2099 发表于 2013-10-8 10:23
MOSI和MISO一个是输出,一个是输入,初始化io那段感觉不对啊.

GPIO_InitStructure.GPIO_Pin = SPIx_SCK_PIN | SPIx_MISO_PIN | SPIx_MOSI_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;  //GPIO_PuPd_UP
  GPIO_Init(SPIx_GPIO_PORT, &GPIO_InitStructure);

具体是哪一句?谢谢

使用特权

评论回复
27
angryBird|  楼主 | 2013-10-8 20:52 | 只看该作者
按照SPI通信特点,主机要是想得到从机的数据,先给从机循环发送无效数据,从而发送时钟给从机,比如0xff,在SD卡的SPI协议中,也是这样说的。在发送时钟的同时,接收回从机的数据。
那从机就应该是循环发送数据,在没有时钟信号的时候,会等待,当有时钟信号的时候,数据就出去了。
我用F207开发板,连接SPI2和SPI3,在主循环中,主从分别发送,用中断接收,都是可以的。
所以,是不是还是接收发送的时序搞得不对?

使用特权

评论回复
28
angryBird|  楼主 | 2013-10-8 22:25 | 只看该作者
主机试验了不用中断,而用查询方式发送接收,结果一样

static uint8_t SpiMasterSendByte1(uint8_t byte)
{
  while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
  SPI_I2S_SendData(SPIx, byte);

  while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);  
  RxBuffer[Rx_Idx++] = SPI_I2S_ReceiveData(SPIx);

  return 1;

}

从机改成在接收中断里面每收到一个字节,就发送一个字节。也一样,只要从机发送,都乱套。

使用特权

评论回复
29
angryBird|  楼主 | 2013-10-8 22:26 | 只看该作者
本帖最后由 angryBird 于 2013-10-8 22:27 编辑

左边是从机收到的,只有第一个字节是0xff,因为收到这个字节后,从机才发送,所以这个字节总是对的。后面就都错了。 右侧是主机收到的,预期收到的0xa0,一个也没有

使用特权

评论回复
30
puchuang| | 2013-10-9 10:11 | 只看该作者
需要单步调试看看先   静下心来  慢慢看看  楼主

使用特权

评论回复
31
huzi2099| | 2013-10-9 13:09 | 只看该作者
angryBird 发表于 2013-10-8 20:52
按照SPI通信特点,主机要是想得到从机的数据,先给从机循环发送无效数据,从而发送时钟给从机,比如0xff, ...

SD卡是有一套指令字的呀

使用特权

评论回复
32
angryBird|  楼主 | 2013-10-13 22:51 | 只看该作者
又过了一周。
前几天还是纠结在SPI通信的正确、稳定上,直到昨天,连接板子调试的J-LINK被烧坏,没办法在板子上调试了。于是又找了一块F207的开发板,两个开发板连在一起调试。结果,通过试验不同的CPOL与CHPA组合,终于找到了一组稳定传输的组合。如下:
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
除了这种,其它三种组合,在双向传输时,总会发生数据错位的问题。具体原因先不追究了,现在终于能够往下走,调试模拟SD卡的协议。计划使用一台开发板,发送读写SD卡的命令,一台slave模拟SD卡做出回应,以及读写U盘,并转发u盘数据给master。

上个图:

使用特权

评论回复
33
angryBird|  楼主 | 2013-10-13 22:53 | 只看该作者
谢谢大家的指导、鼓励!

使用特权

评论回复
34
GERALDWONG| | 2014-1-14 16:19 | 只看该作者
楼主你弄好了么

使用特权

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

本版积分规则