OpenEdv-开源电子网

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

SPI 实验读取ID错误的讨论,有点长

[复制链接]

7

主题

63

帖子

0

精华

初级会员

Rank: 2

积分
142
金钱
142
注册时间
2013-1-23
在线时间
4 小时
发表于 2015-11-25 16:50:35 | 显示全部楼层 |阅读模式
5金钱
我的SPI读写函数是分开的,如下
[mw_shl_code=c,true]void SPIWriteByte(u8 dat) { SPI_I2S_SendData(SPI1,dat); while(!SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)); } u8 SPIReadByte(void) { u8 readDat; readDat = SPI_I2S_ReceiveData(SPI1); return readDat; }[/mw_shl_code]
读取ID函数
[mw_shl_code=c,true]//读取芯片ID W25X16的ID:0XEF14 u16 SPI_Flash_ReadID(void) { u16 Temp = 0; FLASH_CS_ENABLE(); SPIWriteByte(0x90);//发送读取ID命令 SPIWriteByte(0x00); SPIWriteByte(0x00); SPIWriteByte(0x00); SPIWriteByte(0xff); Temp |= SPIReadByte()<<8; SPIWriteByte(0xff); Temp |= SPIReadByte(); return Temp; }[/mw_shl_code]
返回ID错误



后面我加多条打印观察情况
[mw_shl_code=c,true]//读取芯片ID W25X16的ID:0XEF14 u16 SPI_Flash_ReadID(void) { u16 Temp = 0; FLASH_CS_ENABLE(); SPIWriteByte(0x90);//发送读取ID命令 SPIWriteByte(0x00); SPIWriteByte(0x00); SPIWriteByte(0x00); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp1:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp2:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp3:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp4:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp5:%x\r\n",Temp); return Temp; }[/mw_shl_code]
结果如下,


也就是第一个字节读取错误,我怀疑是不是有一条0xff没有发出去,导致第一个字节错误,遂把程序更为
[mw_shl_code=c,true]//读取芯片ID W25X16的ID:0XEF14 u16 SPI_Flash_ReadID(void) { u16 Temp = 0; FLASH_CS_ENABLE(); SPIWriteByte(0x90);//发送读取ID命令 SPIWriteByte(0x00); SPIWriteByte(0x00); SPIWriteByte(0x00); SPIWriteByte(0xff); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp1:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp2:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp3:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp4:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp5:%x\r\n",Temp); return Temp; }[/mw_shl_code]
结果如下,



对比上面可以发现,其实,0xff发送是成功的,接收寄存器里面上面一次本应该是0xef,这次本应该是0x16,不知道问题出在哪里?


后面把程序更为下面
[mw_shl_code=c,true]//读取芯片ID W25X16的ID:0XEF14 u16 SPI_Flash_ReadID(void) { u16 Temp = 0; FLASH_CS_ENABLE(); SPIWriteByte(0x90);//发送读取ID命令 SPIWriteByte(0x00); SPIWriteByte(0x00); SPIWriteByte(0x00); SPIReadByte(); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp1:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp2:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp3:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp4:%x\r\n",Temp); SPIWriteByte(0xff); Temp = SPIReadByte(); printf("temp5:%x\r\n",Temp); return Temp; }[/mw_shl_code]

读取成功!

这让人有点无法理解,我们都知道主从SPI设备的寄存器其实是构成了一个环形,最后一个0x00发送完毕后,接收寄存器里面的应该是0xff,这个没错,但当我们再次发送一个0xff时,即使上次接收寄存器里面的数据不读出,新的数据(0xef)也应该把它挤掉啊,为什么命令发送结束后只要不读取,无论发送多少次0xff,接收寄存器里面的值都是0xff呢?
之前做8051设备的时候就不是这样的啊

最佳答案

查看完整内容[请看2#楼]

不建议读写函数分开。 SPI本就是全双工的,读的时候主机要写0XFF,以发送脉冲。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-11-25 16:50:36 | 显示全部楼层
不建议读写函数分开。
SPI本就是全双工的,读的时候主机要写0XFF,以发送脉冲。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

7

主题

63

帖子

0

精华

初级会员

Rank: 2

积分
142
金钱
142
注册时间
2013-1-23
在线时间
4 小时
 楼主| 发表于 2015-11-26 09:07:42 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
 主要是之前做8051的时候,读写是分开的,然后没有出现问题,
有点先入为主的思维定式,看来以后还是读写一体的比较好!
回复

使用道具 举报

1

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
195
金钱
195
注册时间
2015-11-26
在线时间
25 小时
发表于 2015-11-26 17:03:51 | 显示全部楼层
回复【3楼】浮生长恨:
---------------------------------
这个发送完命令 就要读取id了  时序上  就很紧凑的   你的读和写  是不会互相影响的  时序上
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-20 15:02

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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