野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14961|回复: 19

STM32的硬件SPI

[复制链接]
发表于 2016-9-1 10:36:28 | 显示全部楼层 |阅读模式
昨天调试了一天的硬件SPI和RC522通信,结果一直通信不了。今天,无奈之下,将SPI写改成和别人一样的写法,结果能正常通信了。然后问题来了,
最开始的SPI 读,写操作我的程序是这样写的SPI采用双线全双工模式)
/*******************************************************************************
  * @函数名称        SPI_Write
  * @函数说明   SPI写操作
  * @输入参数   无
  * @输出参数   无
  * @返回参数   无
  *****************************************************************************/
void SPI_Write(uint16_t Data)
{
while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE))==RESET);
SPI_I2S_SendData(SPI1,Data);
}


/*******************************************************************************
  * @函数名称        SPI_Read
  * @函数说明   SPI读操作,读取外部数据
  * @输入参数   无
  * @输出参数   无
  * @返回参数   无
  *****************************************************************************/
uint16_t SPI_Read(unint16_t Data)
{
  uint16_t Value = 0;
  while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE))==RESET);
  SPI_I2S_SendData(SPI1,Data);
  while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE))==RESET);
  Value = SPI_I2S_ReceiveData(SPI1);
  return Value;

}

这种情况下,我的主机不能够和从机正常的通信,然后我把程序改成下面这种情况,通信正常了:
*******************************************************************************
  * @函数名称        SPI_Write
  * @函数说明   SPI写操作
  * @输入参数   无
  * @输出参数   无
  * @返回参数   无
  *****************************************************************************/
uint16_t SPI_Write(uint16_t Data)
{
uint16_t Value = 0;
while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE))==RESET);
SPI_I2S_SendData(SPI1,Data);
while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE))==RESET);
Value = SPI_I2S_ReceiveData(SPI1);
return Value;
}

/*******************************************************************************
  * @函数名称        SPI_Read
  * @函数说明   SPI读操作,读取外部数据
  * @输入参数   无
  * @输出参数   无
  * @返回参数   无
  *****************************************************************************/
uint16_t SPI_Read()
{
return (SPI_Write(0x11));//这里的值时任意写的
}


这两种操作,根本的区别在那呢?欢迎大家前来指教。































回复

使用道具 举报

发表于 2016-9-1 10:38:59 | 显示全部楼层
你的写跟人家的的读不是反过来了嘛?代码完全不一样。
回复 支持 反对

使用道具 举报

发表于 2016-9-1 10:42:25 | 显示全部楼层
不看2楼的回答,我还真以为两个是一模一样,你也够逗逼的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-1 10:44:42 | 显示全部楼层
万卿月 发表于 2016-9-1 10:38
你的写跟人家的的读不是反过来了嘛?代码完全不一样。

嗯,是反过来了,但是我的思想里感觉第一种的写法应该也能实现,正常的读和写呀。第二种里面也就只是在写的后面加了读数据这一步,这个有影响吗?不加这句话是不能正常写入数据吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-1 10:48:24 | 显示全部楼层
万卿月 发表于 2016-9-1 10:38
你的写跟人家的的读不是反过来了嘛?代码完全不一样。

两者的读操作没有任何区别,就是在写这个过程中,前者写没有在发送完的同时对缓冲寄存器的值进行读操作,而后者就是在下操作完毕后进行了读操作
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-1 10:52:33 | 显示全部楼层
fire 发表于 2016-9-1 10:42
不看2楼的回答,我还真以为两个是一模一样,你也够逗逼的

请火哥指教。这两种的读操作没有任何区别,区别在写操作这一步,前者的写操作,在数据发送完了,没有进行读缓冲寄存器的值,而后者的写操作就在发送完毕后读了缓冲寄存器的值。这个?
回复 支持 反对

使用道具 举报

发表于 2016-9-1 11:08:26 | 显示全部楼层
没有伞的孩子 发表于 2016-9-1 10:52
请火哥指教。这两种的读操作没有任何区别,区别在写操作这一步,前者的写操作,在数据发送完了,没有进行 ...

必须先调用发送的send库函数,让spi产生时序,spi在发送的时候会同时接收,而receive的库函数只是读数据寄存器而已,所以不能调换
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-1 11:14:28 | 显示全部楼层
flyleaf 发表于 2016-9-1 11:08
必须先调用发送的send库函数,让spi产生时序,spi在发送的时候会同时接收,而receive的库函数只是读数据 ...

能具体点吗?不太理解你所说的,感谢感谢。(我上面没有调换呀,两个的读操作都是一样的(下面的读函数只是是调用了上面的写函数),区别就在于写操作这个函数)
回复 支持 反对

使用道具 举报

发表于 2016-9-1 11:18:46 | 显示全部楼层
没有伞的孩子 发表于 2016-9-1 11:14
能具体点吗?不太理解你所说的,感谢感谢。(我上面没有调换呀,两个的读操作都是一样的(下面的读函数只 ...

把你原来的写函数加多个等待条件试试:
void SPI_Write(uint16_t Data)
{
while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE))==RESET);
SPI_I2S_SendData(SPI1,Data);
while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE))==RESET);
}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-1 11:24:44 | 显示全部楼层
flyleaf 发表于 2016-9-1 11:18
把你原来的写函数加多个等待条件试试:
void SPI_Write(uint16_t Data)
{

你的意思是我前面的写函数,没写进去
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-1 11:37:44 | 显示全部楼层
没有伞的孩子 发表于 2016-9-1 11:24
你的意思是我前面的写函数,没写进去

刚刚去掉写操作后面的读那就话,然后加延时,结果不行。这说明在发送数据同时还必须对DR进行读操作,将其清0
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-1 11:38:38 | 显示全部楼层
flyleaf 发表于 2016-9-1 11:18
把你原来的写函数加多个等待条件试试:
void SPI_Write(uint16_t Data)
{


刚刚去掉写操作后面的读那就话,然后加延时,结果还是不行。这说明在发送数据同时还必须对DR进行读操作,将其清0,我这样的解释对吗?
回复 支持 反对

使用道具 举报

发表于 2016-9-1 11:39:23 | 显示全部楼层
没有伞的孩子 发表于 2016-9-1 11:37
刚刚去掉写操作后面的读那就话,然后加延时,结果不行。这说明在发送数据同时还必须对DR进行读操作,将其 ...

那就说明写函数的那些操作不能省了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-1 13:33:04 | 显示全部楼层
flyleaf 发表于 2016-9-1 11:39
那就说明写函数的那些操作不能省了

嗯,但是为什么呢?
回复 支持 反对

使用道具 举报

发表于 2016-9-1 14:01:17 | 显示全部楼层

需要等待,清标志
回复 支持 反对

使用道具 举报

发表于 2016-9-1 14:04:13 | 显示全部楼层
SPI 设备间的数据传输之所以又被称为数据交换, 是因为 SPI 协议规定一个 SPI 设备不能在数据通信过程中仅仅只充当一个 "发送者(Transmitter)" 或者 "接收者(Receiver)". 在每个 Clock 周期内, SPI 设备都会发送并接收一个 bit 大小的数据, 相当于该设备有一个 bit 大小的数据被交换了。

不能只发送,还要接收一个同样大小的数。就想例程中那样。要了解更多,百度上有很多。

而且你读函数的形参里类型是unint16_t,这是个什么类型?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-1 17:35:02 | 显示全部楼层
望蓝天 发表于 2016-9-1 14:04
SPI 设备间的数据传输之所以又被称为数据交换, 是因为 SPI 协议规定一个 SPI 设备不能在数据通信过程中仅 ...

uint16_t是我自己定义的 unsigned int ,嗯嗯,知道了。
回复 支持 反对

使用道具 举报

发表于 2016-9-1 17:56:06 | 显示全部楼层
不懂,帮顶!!!
回复

使用道具 举报

发表于 2016-9-2 12:20:58 | 显示全部楼层
读写必须在一个函数内,别想着我先读或者先写,然后在需要的时候在别处操作,这是错误概念,时序不产生的话你无法干任何事每一次产生时序时读写会在这个时间段内全部完成,如果你只写一半,那么要么只是单纯的调不通,严重的直接卡死在等待标志上

u8 SPI_RW(u8 data)
{         
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);                  // 当 SPI发送缓冲器非空时等待
  SPI_I2S_SendData(SPI2, data);                                                                                                                                                                 //        发送数据
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);                 // 当SPI接收缓冲器为空时等待
  return SPI_I2S_ReceiveData(SPI2);                                                                                                                                                 //        返回数据
}

我一直用上面这种形式,没毛病
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-2 17:46:40 | 显示全部楼层
ㄗs-.蝸牛· 发表于 2016-9-2 12:20
读写必须在一个函数内,别想着我先读或者先写,然后在需要的时候在别处操作,这是错误概念,时序不产生的话 ...

嗯,这下才算明白SPI的原理呀,不知道原理,调程序好苦逼,开始我只是单纯的写操作,没有进行读操作,以至于不能够正常的进行通信
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-23 19:09 , Processed in 0.033662 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表