你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F429与AT45DB321通讯问题求助

[复制链接]
hhhhhhhaa 提问时间:2019-9-24 13:10 /
我用STM32F429与AT45DB321通讯,配置好SPI后,读取321的ID,读出来的数据都是FF是怎么回事呢  spi代码如下
  1. #include "spi.h"

  2. void SPIx_Init(void);
  3. uint8_t SPIx_ReadByte(void);
  4. uint8_t SPIx_SendByte(uint8_t byte);


  5. void SPIx_Init(void)
  6. {
  7.   GPIO_InitTypeDef  GPIO_InitStructure;
  8.   SPI_InitTypeDef  SPI_InitStructure;
  9.        
  10.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//ʹÄÜGPIOBʱÖÓ
  11.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//ʹÄÜSPI1ʱÖÓ

  12.   //GPIOB13,14,15³õʼ»¯ÉèÖÃ
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;//PB3~5¸´Óù¦ÄÜÊä³ö       
  14.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//¸´Óù¦ÄÜ
  15.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//ÍÆÍìÊä³ö
  16.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  17.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ÉÏÀ­
  18.   GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯
  19.        
  20.         GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2); //PB13¸´ÓÃΪ SPI2
  21.         GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2); //PB14¸´ÓÃΪ SPI2
  22.         GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2); //PB51¸´ÓÃΪ SPI2




  23.         SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;       //ÉèÖÃSPIµ¥Ïò»òÕßË«ÏòµÄÊý¾Ýģʽ:SPIÉèÖÃΪ˫ÏßË«ÏòÈ«Ë«¹¤
  24.         SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                                         //ÉèÖÃSPI¹¤×÷ģʽ:ÉèÖÃΪÖ÷SPI
  25.         SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                                     //ÉèÖÃSPIµÄÊý¾Ý´óС:SPI·¢ËͽÓÊÕ8λ֡½á¹¹
  26.         SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                                           //´®ÐÐͬ²½Ê±ÖӵĿÕÏÐ״̬Ϊ¸ßµçƽ
  27.         SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                                   //´®ÐÐͬ²½Ê±Öӵĵڶþ¸öÌø±äÑØ£¨ÉÏÉý»òϽµ£©Êý¾Ý±»²ÉÑù
  28.         SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                             //NSSÐźÅÓÉÓ²¼þ£¨NSS¹Ü½Å£©»¹ÊÇÈí¼þ£¨Ê¹ÓÃSSI룩¹ÜÀí:ÄÚ²¿NSSÐźÅÓÐSSIλ¿ØÖÆ
  29.         SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;           //¶¨Ò岨ÌØÂÊÔ¤·ÖƵµÄÖµ:²¨ÌØÂÊÔ¤·ÖƵֵΪ256
  30.         SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                             //Ö¸¶¨Êý¾Ý´«Êä´ÓMSBλ»¹ÊÇLSBλ¿ªÊ¼:Êý¾Ý´«Êä´ÓMSBλ¿ªÊ¼
  31.         SPI_InitStructure.SPI_CRCPolynomial = 7;                                       //CRCÖµ¼ÆËãµÄ¶àÏîʽ
  32.         SPI_Init(SPI2, &SPI_InitStructure);                                      //¸ù¾ÝSPI_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèSPIx¼Ä´æÆ÷

  33.         SPI_Cmd(SPI2, ENABLE); //ʹÄÜSPIÍâÉè

  34. }   


  35. /*******************************************************************************
  36. * Function Name  : SPIx_ReadByte
  37. * Description    : Reads a byte from the SPI Flash.
  38. *                  This function must be used only if the Start_Read_Sequence
  39. *                  function has been previously called.
  40. * Input          : None
  41. * Output         : None
  42. * Return         : Byte Read from the SPI Flash.
  43. *******************************************************************************/
  44. uint8_t SPIx_ReadByte(void)
  45. {
  46.         return (SPIx_SendByte(Dummy_Byte));
  47. }


  48. /*******************************************************************************
  49. * Function Name  : SPIx_SendByte
  50. * Description    : Sends a byte through the SPI interface and return the byte
  51. *                  received from the SPI bus.
  52. * Input          : byte : byte to send.
  53. * Output         : None
  54. * Return         : The value of the received byte.
  55. *******************************************************************************/
  56. uint8_t SPIx_SendByte(uint8_t byte)
  57. {
  58.         /* Loop while DR register in not emplty */
  59.         while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
  60.        
  61.         /* Send byte through the SPI1 peripheral */
  62.         SPI_I2S_SendData(SPI2, byte);
  63.        
  64.         /* Wait to receive a byte */
  65.         while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
  66.        
  67.         /* Return the byte read from the SPI bus */
  68.         return SPI_I2S_ReceiveData(SPI2);
  69. }

复制代码
SPI头文件代码
  1. #ifndef __SPI_H
  2. #define __SPI_H
  3. #include "sys.h"
  4. #include "delay.h"

  5. #define Dummy_Byte 0xA5





  6. extern void SPIx_Init(void);
  7. extern uint8_t SPIx_ReadByte(void);
  8. extern uint8_t SPIx_SendByte(uint8_t byte);

  9. #endif

复制代码
读状态
  1. /*******************************************************************************
  2. Ãû    ³Æ£º        uint8_t AT45_GetStatus(void)
  3. ¹¦    ÄÜ£º        ¶ÁÈ¡ flash ״̬¼Ä´æÆ÷
  4. ÊäÈë²ÎÊý£º        ÎÞ
  5. Êä³ö²ÎÊý£º        ÎÞ
  6. ·µ    »Ø£º        µ±Ç°×´Ì¬
  7. Æä    Ëü£º        ÎÞ
  8. *******************************************************************************/
  9. uint8_t AT45_GetStatus(void)
  10. {
  11.         uint8_t state;

  12.         AT45_Chip_Select_ENABLE();

  13.         SPIx_SendByte(AT45_CMD_READ_STATUS);
  14.        
  15.         state =        SPIx_SendByte(Dummy_Byte);

  16.         AT45_Chip_Select_DISABLE();

  17.         if(state & 0x80)
  18.         {
  19.                 return 1;
  20.         }
  21.         else
  22.         {
  23.                 return 0;
  24.         }
  25. }
复制代码
读ID
  1. void AT45DBXX_Read_ID(u8 *IData)
  2. {

  3.         uint8_t state;
  4.        
  5.         do{
  6.                 state = AT45_GetStatus();
  7.         }while(!state);

  8.          AT45_Chip_Select_ENABLE();
  9.    SPIx_SendByte(Read_ID);
  10.    IData[0]= SPIx_SendByte(0x00);
  11.          IData[1]= SPIx_SendByte(0x00);
  12.          IData[2]= SPIx_SendByte(0x00);
  13.          IData[3]= SPIx_SendByte(0x00);
  14.    AT45_Chip_Select_DISABLE();


  15. }

复制代码
   AT45DBXX_Read_ID(ID); 函数调用读取,调试发现ID的内容都是FF

收藏 评论9 发布时间:2019-9-24 13:10

举报

9个回答
hhhhhhhaa 回答时间:2019-9-24 19:13:39
没有人知道吗?读出来的都是FF
hhhhhhhaa 回答时间:2019-9-25 08:25:46
hhhhhhhaa 回答时间:2019-9-25 11:05:14
好了问题解决了,加一个片选的配置就好了,如果不配置片选读出来的都是FF,片选配置如下void SPIx_Init_cs(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PB13~15¸´Óù¦ÄÜÊä³ö       
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//ÍÆÍìÊä³ö
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ÉÏÀ­
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
}
hhhhhhhaa 回答时间:2019-9-30 17:10:31
有大神知道怎样连续读取多页的数据吗?我的理解是首先是要知道从第几页的第几个开始读,然后读取多少,然后由一个数组进行存储,
一页的数据是528个字节,那就是528个数,比我想从第一页的第12个数开始读,连续读取100个,这种情况是最简单的,应该是直接读取就行,调用函数把第一页的数据都读到缓冲区,然后从缓冲区的第12项开始读,连续读100个数(一个for循环读取),
第二种情况 :从第一页的第12个数开始读,连续读528个字节,这种情况相对复杂,首先要判断从第12个开始+528的情况是不是大于一页,很显然大于1页的数据了,那就要读两次缓冲区,第一次读缓冲区从第12个字开始读,一直读到结尾,放在一个数组内,第二次读的时候从第二页的第0个字节开始读,读取528+12-528=12个,第二页只需要读取12个就可以了,然后把数组1和数组2合并
第三种情况:从第一页的第12个数开始读,连续读取1100个字节的数据,这种情况更加复杂,首先要判断12+1100的情况÷528的整数是几,很显然整数是2 ,余数是56,这样的话就需要读次缓冲区,第一次读从第12个开始,一直读到结尾,第二次读需要读取整页的数据,第三次的话需要读取56个数据,最后把三个数组合成一个返回。
如果有再多的数据基本上都和第三组相同了
hhhhhhhaa 回答时间:2019-10-11 15:34:54
今天看了野火和原子的两个例子,感觉野火写的比较好,和大家分享一下,读取的话野火讲的是,可以直接读取片内数据,不通过缓冲区读,可以读取任意的条数。写的话,需要先把数据读到缓冲区,在缓冲区进行修改后,从缓冲区写入到存储区
hhhhhhhaa 回答时间:2019-10-11 15:36:07
不定量数据写入
应用的时候我们常常要写入不定量的数据,直接调用“页写入”函数并不是特别方便,
所以我们在它的基础上编写了“不定量数据写入”的函数,基实现见代码清单 24-12。
代码清单 24-12 不定量数据写入
1 /**
2 * @brief 对 FLASH 写入数据,调用本函数写入数据前需要先擦除扇区
3 * @param pBuffer,要写入数据的指针
4 * @param WriteAddr,写入地址
5 * @param NumByteToWrite,写入数据长度
6 * @retval 无
7 */
8 void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
9 {
10 u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
11
12 /*mod 运算求余,若 writeAddr 是 SPI_FLASH_PageSize 整数倍,运算结果 Addr 值为
0*/
13 Addr = WriteAddr % SPI_FLASH_PageSize;
15 /*差 count 个数据值,刚好可以对齐到页地址*/
16 count = SPI_FLASH_PageSize - Addr;
17 /*计算出要写多少整数页*/
18 NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
19 /*mod 运算求余,计算出剩余不满一页的字节数*/
20 NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
21
22 /* Addr=0,则 WriteAddr 刚好按页对齐 aligned */
23 if (Addr == 0)
24 {
25 /* NumByteToWrite < SPI_FLASH_PageSize */
26 if (NumOfPage == 0)
27 {
28 SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
29 }
30 else /* NumByteToWrite > SPI_FLASH_PageSize */
31 {
32 /*先把整数页都写了*/
33 while (NumOfPage--)
34 {
35 SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
36 WriteAddr += SPI_FLASH_PageSize;
37 pBuffer += SPI_FLASH_PageSize;
38 }
39
40 /*若有多余的不满一页的数据,把它写完*/
41 SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
42 }
43 }
44 /* 若地址与 SPI_FLASH_PageSize 不对齐 */
45 else
46 {
47 /* NumByteToWrite < SPI_FLASH_PageSize */
48 if (NumOfPage == 0)
49 {
50 /*当前页剩余的 count 个位置比 NumOfSingle 小,写不完*/
51 if (NumOfSingle > count)
52 {
53 temp = NumOfSingle - count;
54
55 /*先写满当前页*/
56 SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
57 WriteAddr += count;
58 pBuffer += count;
59
60 /*再写剩余的数据*/
61 SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
62 }
63 else /*当前页剩余的 count 个位置能写完 NumOfSingle 个数据*/
64 {
65 SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
66 }
67 }
68 else /* NumByteToWrite > SPI_FLASH_PageSize */
69 {
70 /*地址不对齐多出的 count 分开处理,不加入这个运算*/
71 NumByteToWrite -= count;
72 NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
73 NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
74
75 SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
76 WriteAddr += count;
77 pBuffer += count;
78
79 /*把整数页都写了*/
80 while (NumOfPage--)
81 {
82 SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
83 WriteAddr += SPI_FLASH_PageSize;
84 pBuffer += SPI_FLASH_PageSize;
85 }
86 /*若有多余的不满一页的数据,把它写完*/
87 if (NumOfSingle != 0)
88 {
89 SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
90 }
91 }
92 }
93 }
hhhhhhhaa 回答时间:2019-10-11 15:37:33
解释一下很多读者觉得这段代码的运算很复杂,看不懂,其实它的主旨就是对输入的数据进行
分页(本型号芯片每页 8个字节),见表 23-2。通过“整除”计算要写入的数据
NumByteToWrite 能写满多少“完整的页”,计算得的值存储在 NumOfPage 中,但有时数
据不是刚好能写满完整页的,会多一点出来,通过“求余”计算得出“不满一页的数据个
数”就存储在 NumOfSingle 中。计算后通过按页传输 NumOfPage 次整页数据及最后的
NumOfSing 个数据,使用页传输,比之前的单个字节数据传输要快很多。
除了基本的分页传输,还要考虑首地址的问题,见表 23-3。若首地址不是刚好对齐到
页的首地址,会需要一个 count值,用于存储从该首地址开始写满该地址所在的页,还能
写多少个数据。实际传输时,先把这部分 count个数据先写入,填满该页,然后把剩余的
数据(NumByteToWrite-count),再重复上述求出 NumOPage及 NumOfSingle的过程,按页
传输到 EEPROM。
1.  若 writeAddress=16,计算得 Addr=16%8= 0 ,count=8-0= 8;
2.  同时,若 NumOfPage=22,计算得 NumOfPage=22/8= 2,NumOfSingle=22%8= 6。
4.  若 writeAddress=17,计算得 Addr=17%8= 1,count=8-1= 7;
5.  同时,若 NumOfPage=22,
6.  先把 count 去掉,特殊处理,计算得新的 NumOfPage=22-7= 15
7.  计算得 NumOfPage=15/8= 1,NumOfSingle=15%8= 7。
hhhhhhhaa 回答时间:2019-10-11 15:40:09
这个是参照w25q128的例子,AT45DB321

hhhhhhhaa 回答时间:2019-10-14 10:55:24
刚才看AT45DB321,重新阅读了一下,在读取命令里,有分为直接读内存中的数据,包括高速读取,低速读取,页读取,第二种情况就是通过命令进行缓冲区读取
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版