OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 27109|回复: 34

初识SPI,遇到问题,发帖请教。(已解决)

[复制链接]

20

主题

63

帖子

0

精华

初级会员

Rank: 2

积分
163
金钱
163
注册时间
2011-2-28
在线时间
0 小时
发表于 2011-3-27 15:32:34 | 显示全部楼层 |阅读模式
u8 SPIx_ReadWriteByte(u8 TxData)
{
    u8 retry=0;
    while((SPI1->SR&1<<1)==0)//等待发送区空
    {
        retry++;
        if(retry>200)return 0;
    }
    SPI1->DR=TxData; //发送一个byte
    retry=0;
    while((SPI1->SR&1<<0)==0) //等待接收完一个byte
    {
        retry++;
        if(retry>200)return 0;
    }
r    eturn SPI1->DR; //返回收到的数据
}
今天学习到SPI实验了,看到SPI读写函数有点不解,为什么读和写能写在一个函数中啊?
当我读数据的时候要先发送一个数据么?
当我写完数据还要读一个数据么?

请大家指点下。谢谢
深蓝嵌入式工作室
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2011-3-27 17:15:48 | 显示全部楼层
回复【楼主位】bluesky_kun:
-------------------------------
SPI是全双工的了.
MI是数据输入的.
M0是数据输出的.
SCK由主机产生,当SCK输出的时候,MI输入数据,同时MO输出数据.这样发送的时候就顺便收了.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

42

主题

568

帖子

0

精华

高级会员

Rank: 4

积分
784
金钱
784
注册时间
2010-12-19
在线时间
5 小时
发表于 2011-3-27 20:05:51 | 显示全部楼层
static u8 SPI_Read_Byte(void)
{  
  //等待发送信号寄存器为非空,然后发送一个字节到spi总线上
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
  SPI_I2S_SendData(SPI1, 0x00);

  //等待接收信号寄存器为非空,然后从spi总线上接收一个字节
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)  /* Wait to receive a byte */;
  return SPI_I2S_ReceiveData(SPI1)  /* Return the byte read from the SPI bus */;
}

//spi 写一个字节
static void SPI_Write_Byte(u8 byte)
{  
  //时序同发生字节一样,只是不返回读取的字节
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)  /* Loop while DR register in not emplty */;
  SPI_I2S_SendData(SPI1, byte)/* Send byte through the SPI2 peripheral */;

  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)  /* Wait to receive a byte */;
  SPI_I2S_ReceiveData(SPI1)  /* Return the byte read from the SPI bus */;
}
一个上蹿下跳的猴子~~~
回复 支持 反对

使用道具 举报

6

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
83
金钱
83
注册时间
2011-3-25
在线时间
0 小时
发表于 2011-3-28 08:08:52 | 显示全部楼层
回复【楼主位】bluesky_kun:
-------------------------------
spi的时序就是在sck的控制下,两个双向移位寄存器进行数据交换。所以它是一边发送一边接收的,必须发送一个数据才能接收一个
回复 支持 反对

使用道具 举报

20

主题

63

帖子

0

精华

初级会员

Rank: 2

积分
163
金钱
163
注册时间
2011-2-28
在线时间
0 小时
 楼主| 发表于 2011-3-28 09:08:56 | 显示全部楼层
谢谢大家的指点,明白了.
深蓝嵌入式工作室
回复 支持 反对

使用道具 举报

2

主题

4

帖子

0

精华

新手上路

积分
42
金钱
42
注册时间
2010-12-15
在线时间
2 小时
发表于 2011-11-2 09:04:03 | 显示全部楼层
受教了,谢谢了。
回复 支持 反对

使用道具 举报

13

主题

40

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
344
金钱
344
注册时间
2012-7-13
在线时间
83 小时
发表于 2012-7-13 15:00:50 | 显示全部楼层
受教了
回复 支持 反对

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2012-10-11
在线时间
0 小时
发表于 2012-10-11 19:25:57 | 显示全部楼层
回复【5楼】bluesky_kun:
---------------------------------楼主能帮我解释下、
while((SPI1->SR&1<<1)==0)//等待发送区空
     {
         retry++;
         if(retry>200)return 0;
     }
我不知道while这样写是什么意思呀? 谢谢了
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2012-10-11 21:49:58 | 显示全部楼层
等待发送区空
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

8

主题

103

帖子

0

精华

初级会员

Rank: 2

积分
187
金钱
187
注册时间
2012-11-12
在线时间
22 小时
发表于 2013-1-15 10:30:57 | 显示全部楼层
回复【3楼】wolfdong7:
---------------------------------
受教了
没人看你努力的过程,只看最后的结果。
回复 支持 反对

使用道具 举报

20

主题

122

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
222
金钱
222
注册时间
2013-9-21
在线时间
0 小时
发表于 2013-11-22 12:29:59 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
原子哥,我把例程的spi读写函数拆成了2个
u8 SPI2_Write(u8 data)
{
 u8 retry=0;
 while((SPI2->SR&0X02)==0) //等待数据发送完
 {
  retry++;
  if(retry>=0XFE)return 0;
 }
 SPI2->DR=data;   //data是要发送的数据
 return 0;
}
u8 SPI2_Read(void)
{
 u8 retry=0;
 while((SPI2->SR&0X01)==0) //等待数据接收完
 {
  retry++;
  if(retry>=0XFE)return 0;
 }
 return SPI2->DR;    //data是接收到的数据
}
这样就不行了,是不是和3楼的朋友说的那样:spi的时序就是在sck的控制下,两个双向移位寄存器进行数据交换。所以它是一边发送一边接收的,必须发送一个数据才能接收一个
所以spi的读写不能分开,必须在一个函数里?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2013-11-22 23:04:47 | 显示全部楼层
回复【11楼】jikaishihuaidan:
---------------------------------
SPI,必须要由主机产生时钟,才行.
所以,你的接收函数,主机都没有数据发送,也就是不会产生时钟,自然就收不到数据了.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

20

主题

122

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
222
金钱
222
注册时间
2013-9-21
在线时间
0 小时
发表于 2013-11-24 08:53:46 | 显示全部楼层
回复【12楼】正点原子:
---------------------------------
抱歉原子哥,忘了回复。
恩,主设备的读数据实际上是从设备的发送数据,对吗?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2013-11-24 11:21:25 | 显示全部楼层
回复【13楼】jikaishihuaidan:
---------------------------------
要从设备发送数据,必须给他提供时钟.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

20

主题

122

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
222
金钱
222
注册时间
2013-9-21
在线时间
0 小时
发表于 2013-11-24 21:37:55 | 显示全部楼层
回复【14楼】正点原子:
---------------------------------
恩恩。
回复 支持 反对

使用道具 举报

23

主题

292

帖子

0

精华

高级会员

Rank: 4

积分
501
金钱
501
注册时间
2013-9-17
在线时间
17 小时
发表于 2013-11-30 02:26:14 | 显示全部楼层
回复【3楼】wolfdong7:
---------------------------------可以贴你的代码 给我 学习一下么  我在学习SPI1 debug的时候就卡在这个while 一直不置位  
  读不出ID 等等 配置暂时不会修改 看看能不能接兄台之力 上一上台阶
闷鱼闷闷不乐吃焖鱼
回复 支持 反对

使用道具 举报

10

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
134
金钱
134
注册时间
2013-11-27
在线时间
11 小时
发表于 2013-12-4 23:05:42 | 显示全部楼层
T0:原子&各位高手

我是新手,刚刚看到SPI,看到手册里面说了,在写的时候要先发送,发送不一定要传送内容,只是为了给从机一个时钟,因为SCLK是主机来发出的,所以想单独写一个SPI写函数的话,那么这个写函数里面要有一个空发送指令,目的是提供从机的写时钟,请问一下原子大哥,这个理解是不是对的呀,因为我觉得SPI读写函数应该是可以分开的!!!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2013-12-4 23:17:06 | 显示全部楼层
回复【17楼】hjhand:
---------------------------------
不需要空指令,直接发,那边就收了。
关键你要提供时钟。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

10

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
134
金钱
134
注册时间
2013-11-27
在线时间
11 小时
发表于 2013-12-5 23:42:54 | 显示全部楼层
谢谢你的回答!
pBuffer=SPI2_ReadWriteByte(0XFF);   //循环读数 

看到这句很不理解?  SPI全双工的时候,在发送的时候,同时也在接受, 那不停的写0xff就是为了擦除flash吗?如果都写进去0xff的话,那读出来的不也是0xff,难道是读回来看一下是不是擦除成功?期待原子哥的解答,TKS!!!
回复 支持 反对

使用道具 举报

头像被屏蔽

38

主题

382

帖子

0

精华

高级会员

Rank: 4

积分
596
金钱
596
注册时间
2012-12-5
在线时间
19 小时
发表于 2013-12-6 00:22:03 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

56

主题

289

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2012-11-16
在线时间
65 小时
发表于 2014-3-29 11:54:05 | 显示全部楼层
学习了
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2014-8-31
在线时间
0 小时
发表于 2014-8-31 17:36:14 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
retry++;
 if(retry>200)return 0;
在这个变量的作用是什么,等待 还是发送区的数据呢
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2014-8-31 18:06:45 | 显示全部楼层
回复【22楼】无极电工:
---------------------------------
防止死机
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2014-8-31
在线时间
0 小时
发表于 2014-8-31 19:42:05 | 显示全部楼层
回复【23楼】正点原子:
---------------------------------
原子的论坛回复就是快,
小弟查了老多资料大部分都是使用retry变量,小弟愚笨还是没太弄清怎么防死机
它有延时作用吗,为什么是要200呢,retry++的变量在整个程序没什么大出现啊
希望原子大哥指点下
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2014-9-1 00:33:02 | 显示全部楼层
回复【24楼】无极电工:
---------------------------------
就是多次尝试。200是随意定的,你可以自己设置其它值。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

19

主题

90

帖子

1

精华

高级会员

Rank: 4

积分
543
金钱
543
注册时间
2012-5-13
在线时间
40 小时
发表于 2014-9-23 12:12:00 | 显示全部楼层
回复【20楼】toddchen:
---------------------------------
 我的也是这样死在 while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);  这里了。现在还在郁闷中...
回复 支持 反对

使用道具 举报

2

主题

37

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
484
金钱
484
注册时间
2014-9-5
在线时间
179 小时
发表于 2014-10-2 22:05:40 | 显示全部楼层
刚在学spi这章,查了网现在对0xff有点眉目了,因为前面发送读命令,所以0xff不会被写进去,而读出来的数据放在读的DR里面,这时写的DR里面放的是0xff。
  SPI2_ReadWriteByte(W25X_ReadData);  //发送读取命令
回复 支持 反对

使用道具 举报

60

主题

204

帖子

0

精华

高级会员

Rank: 4

积分
503
金钱
503
注册时间
2014-2-28
在线时间
7 小时
发表于 2014-10-28 14:02:53 | 显示全部楼层
回复【12楼】正点原子:
---------------------------------
原子哥,这个CLK是在发送数据的时候自动产生方波的吧?我现在碰到的问题是,主机根本发不出去数据;
    while (SPI_I2S_GetFlagStatus(SPIX, SPI_I2S_FLAG_TXE) == RESET);   程序卡死在了这,那么CLK还能产生码???

我在网上搜了好多网有的问题,但是卡在这个地方,没有人给出合理的解答。。。。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2014-10-28 23:33:55 | 显示全部楼层
回复【28楼】交流zzk:
---------------------------------
我们例程不就有SPI发送嘛
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

60

主题

204

帖子

0

精华

高级会员

Rank: 4

积分
503
金钱
503
注册时间
2014-2-28
在线时间
7 小时
发表于 2014-10-29 08:05:50 | 显示全部楼层
回复【29楼】正点原子:
--------------------------------原子哥,是这样的,我现在的程序只要一进入 SPI_SentData()函数, 
 就会卡在while (SPI_I2S_GetFlagStatus(SPIX, SPI_I2S_FLAG_TXE) == RESET);这个地方,我想这个硬件关系不大的,
随后我就检查了一下SPI的配置,也没发现什么问题,参考官方的例程, 甚至换了片芯片,都不管用。。。。
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2014-12-11
在线时间
0 小时
发表于 2014-12-11 19:00:10 | 显示全部楼层
回复【30楼】交流zzk:
---------------------------------
不知层主解决没有,我也同样有这个疑问,在读取Device ID时,应该在第四个发送指令之后才应该有一个回复啊,所以应该陷入死循环啊、、、
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2015-11-22
在线时间
3 小时
发表于 2015-11-24 17:50:10 | 显示全部楼层
如果我只用到SCK、以及MISO两根线,配置为双线双工,MOSI悬空不接。那样的话,我还是用
u8 SPI2_ReadWriteByte(u8 TxData) 
{
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); 
  SPI_SendData8(SPI2,TxData);  
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);   
  return SPI_ReceiveData8(SPI2);        

这个函数,我可以理解为,在MISO上给从机发送了一个指令,从机接收了这个指令后,反馈回来数据???恳请原子哥解答。回复【29楼】正点原子:
---------------------------------
回复 支持 反对

使用道具 举报

66

主题

364

帖子

0

精华

初级会员

Rank: 2

积分
132
金钱
132
注册时间
2015-6-18
在线时间
129 小时
发表于 2016-5-26 13:00:53 | 显示全部楼层
hjhand 发表于 2013-12-5 23:42
谢谢你的回答!
pBuffer=SPI2_ReadWriteByte(0XFF);&nbsp;&nbsp;&nbsp;//循环读数&nbsp;

看到这句很不理解 ...

我也想问:
谢谢你的回答!
pBuffer=SPI2_ReadWriteByte(0XFF);   //循环读数  

看到这句很不理解?  SPI全双工的时候,在发送的时候,同时也在接受, 那不停的写0xff就是为了擦除flash吗?如果都写进去0xff的话,那读出来的不也是0xff,难道是读回来看一下是不是擦除成功?期待原子哥的解答,TKS!!!
写进去的0XFF不会把从机上的数据给擦除吗?
回复 支持 反对

使用道具 举报

12

主题

70

帖子

0

精华

高级会员

Rank: 4

积分
888
金钱
888
注册时间
2016-3-29
在线时间
178 小时
发表于 2016-8-1 17:59:46 | 显示全部楼层
受教啦
回复 支持 反对

使用道具 举报

20

主题

143

帖子

0

精华

初级会员

Rank: 2

积分
64
金钱
64
注册时间
2015-8-28
在线时间
108 小时
发表于 2016-12-13 14:32:10 | 显示全部楼层
蓝色天使211 发表于 2014-9-23 12:12
回复【20楼】toddchen:
---------------------------------
&nbsp;我的也是这样死在&nbsp;while(SPI_I2S_Ge ...

运行一会,不确定多久,就会死在这个while里,改为直接操作寄存器也不行,搞死人了
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-28 05:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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