<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > SST25VF080B SPI接口FLASH STM32驅(qū)動

          SST25VF080B SPI接口FLASH STM32驅(qū)動

          作者: 時間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
          所有的FLASHA 都一樣只能從1變0,要想從0變1 只有擦除一個頁扇,SST25VF080B 最小可以擦除4KB的頁速度也不錯 50MHz 容量1MB 挺夠用的 10萬次的擦寫壽命。最低2.7V 就可正常工作。
          Flexible Erase Capability
          – Uniform 4 KByte sectors
          – Uniform 32 KByte overlay blocks
          – Uniform 64 KByte overlay blocks
          先記下 這些個7788的命令

          SST25VF080B 的各種命令比較繁瑣

          本文引用地址:http://www.ex-cimer.com/article/201612/325218.htm

          Status Register這個設(shè)置寫保護多點 我這里只用它的判忙BUSY

          一樣先配置SPI與GPIO口上圖~~

          在這也就是CE有用片選嘛~~

          #defineSST_SELECT()GPIO_ResetBits(GPIOC, GPIO_Pin_13)/* SST CS = L */
          #defineSST_DESELECT()GPIO_SetBits(GPIOC, GPIO_Pin_13)/* SST CS = H */

          /***********************************************
          **函數(shù)名:FLASH_SPI_Config
          **功能:初始化串行FLASH的SPI接口
          **注意事項:串行FLASH使用了SPI1接口
          ***********************************************/
          void FLASH_SPI_Config(void)
          {
          SPI_InitTypeDef SPI_InitStructure;
          GPIO_InitTypeDef GPIO_InitStructure;

          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |
          RCC_APB2Periph_AFIO |
          RCC_APB2Periph_SPI1,
          ENABLE);

          /* SCK, MISO and MOSI A5=CLK,A6=MISO,A7=MOSI*/
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
          GPIO_Init(GPIOA, &GPIO_InitStructure);

          /* PC.13 作片選*/
          GPIO_SetBits(GPIOC, GPIO_Pin_13);//預(yù)置為高
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
          GPIO_Init(GPIOC, &GPIO_InitStructure);

          /* SPI1 configuration */
          SPI_Cmd(SPI1, DISABLE); //必須先禁能,才能改變MODE
          SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//兩線全雙工
          SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//主
          SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//8位
          SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//CPOL=0 時鐘懸空低
          SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//CPHA=0 數(shù)據(jù)捕獲第1個
          SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//軟件NSS
          SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//2分頻=36M SST25VF說是50M沒事
          SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前
          SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC7 我不解的是如果出錯要如何處理

          SPI_Init(SPI1, &SPI_InitStructure);
          //SPI_SSOutputCmd(SPI1, ENABLE); //使能NSS腳可用 我這就一個SPI 器件
          SPI_Cmd(SPI1, ENABLE);

          }

          /***************************************
          **函數(shù)名:SPIByte
          **功能:讀寫SPI總線
          **注意事項:對于SPI來說,主機的讀也需要先寫,
          **使用此函數(shù),讀的時候建議參數(shù)設(shè)置為0xff,寫的時候則寫參數(shù).這里使用直接操作寄存器的辦法實現(xiàn)SPI硬件層讀寫,是為了加快速寫速度 在說LCD 的時候我用的就是庫函數(shù) 比如

          SPI_I2S_SendDataSPI_I2S_ReceiveData SPI_I2S_GetFlagStatus
          ***************************************/
          static u8 SPIByte(u8 byte)
          {
          /*等待發(fā)送寄存器空*/
          while((SPI1->SR & SPI_I2S_FLAG_TXE)==RESET);
          /*發(fā)送一個字節(jié)*/
          SPI1->DR = byte;
          /* 等待接收寄存器有效*/
          while((SPI1->SR & SPI_I2S_FLAG_RXNE)==RESET);
          return(SPI1->DR);
          }

          //咱用模式0

          /*****************************************
          **函數(shù)名:SSTCmd1/2/4
          **功能:寫一個SST命令/寫一個命令后接一個數(shù)據(jù)/寫一個命令后再寫3個數(shù)據(jù)
          **注意事項:這是一個完整的單命令操作,不返回
          *****************************************/
          void SSTCmd1(u8 cmd)
          {
          SST_SELECT();
          SPIByte(cmd);
          SST_DESELECT();
          }

          void SSTCmd2(u8 cmd,u8 data)
          {
          SST_SELECT();
          SPIByte(cmd);
          SPIByte(data);
          SST_DESELECT();
          }

          void SSTCmd4(u8 cmd,u8 *addr)
          {
          SST_SELECT();
          SPIByte(cmd);//首命令
          SPIByte(*addr++);
          SPIByte(*addr++);
          SPIByte(*addr);
          SST_DESELECT();
          }

          /****************************************
          **函數(shù)名:SSTCmdb1b/SSTCmd4bs
          **功能:寫一個SST命令,返回1字節(jié)數(shù)據(jù)/寫1個命令字,3個地址字,返回多個字節(jié)
          **更多使用在讀出上的
          ****************************************/
          u8 SSTCmdb1b(u8 cmd)
          {
          u8 tmp;
          SST_SELECT();
          SPIByte(cmd);
          tmp=SPIByte(0xff);
          SST_DESELECT();
          return(tmp);
          }
          void SSTCmd4bs(u8 cmd,u8* addr,u8* data,u32 no)
          {
          SST_SELECT();
          SPIByte(cmd);//首命令
          SPIByte(*addr++);
          SPIByte(*addr++);
          SPIByte(*addr);
          for(;no>0;no--)
          {
          *data++=SPIByte(0xff);
          }
          SST_DESELECT();
          }

          //命令時序復(fù)雜啊~~當然了我這為了求全都寫出來了

          常用的芯片功能

          /***************************************
          SST25WREN 允許寫功能
          ***************************************/
          void SST25WREN(void)
          {
          SSTCmd1(0x06);
          }

          /***********************************
          SST25WRDI 屏蔽寫功能
          ***********************************/
          void SST25WRDI(void)
          {
          SSTCmd1(0x04);
          }

          /**********************************
          SST25BY 檢測忙
          **********************************/
          u8 SST25BY(void)
          {
          u8 sta;
          sta=SSTCmdb1b(0x05);
          return(sta&0x01);
          }

          /***********************************
          SST25WPEN 允許軟件寫保護
          注意事項:25的寫入比較繁瑣,建議在每次操作前都取消掉寫保護,操作完成后則重新允許寫保護

          ***********************************/
          void SST25WPEN(void)
          {
          u8 sta;
          sta=SSTCmdb1b(0x05)|0x1c;//讀出寄存器并加入保護位
          SSTCmd1(0x50);//允許寫Status Register
          SSTCmd2(0x01,sta);
          }

          //先消除保護位,再允許寫位
          void SST25WriteEn(void)
          {
          u8 sta;
          sta=SSTCmdb1b(0x05)&(~0x1c);//讀出寄存器并消除保護位
          SSTCmd1(0x50);//允許寫寄存器Status Register
          SSTCmd2(0x01,sta);//寫寄存器
          SSTCmd1(0x06);//允許寫
          }

          /********************************寄存器Status Register**********************************/

          就是這樣實現(xiàn)寫保護。

          /**********************************
          SST25ReadID 讀取SST的ID 這個功能 呵呵不用多說~當然單純的讀寫操作肯定用不上
          **********************************/
          u16 SST25ReadID(void)
          {
          u8 id[3];
          u8 addr[3]={0,0,0};

          SSTCmd4bs(0x90,addr,id,3);
          return((id[0]<<8)+id[1]);
          }

          /**********************************
          SST25ChipErase 刷除CHIP
          **********************************/
          void SST25ChipErase(void)
          {
          SST25WriteEn();
          SSTCmd1(0x60);
          while(SST25BY());
          SST25WPEN();
          }

          /***********************************
          SST25SectorErase 刷扇區(qū) 用的是4kb大小 假如地址在0~4095 之間那么這之間的地址都會刷除

          當然我給 4096 的話4096到4096+4095 之間都會刷掉
          ***********************************/
          void SST25SectorErase(u32 addr)
          {
          u8 ad[3];
          ad[0]=(addr>>16)&0xff;
          ad[1]=(addr>>8)&0xff;
          ad[2]=addr&0xff;


          SST25WriteEn();

          SST_SELECT();
          SPIByte(0x20);
          SPIByte(ad[0]);
          SPIByte(ad[1]);
          SPIByte(ad[2]);
          SST_DESELECT();

          while(SST25BY());
          //SST25WPEN();
          }

          /**********************************
          SST25ByteProgram 寫一個字節(jié)*注意在此前要調(diào)用取消寫保護,實際寫應(yīng)使用AAI,此函數(shù)在AAI中調(diào)用,用于寫奇數(shù)個字節(jié)
          **********************************/
          void SST25ByteProgram(u32 addr,u8 byte)
          {
          u8 ad[3];
          ad[0]=(addr>>16)&0xff;
          ad[1]=(addr>>8)&0xff;
          ad[2]=addr&0xff;

          SST_SELECT();
          SPIByte(0x02);
          SPIByte(ad[0]);
          SPIByte(ad[1]);
          SPIByte(ad[2]);
          SPIByte(byte);
          SST_DESELECT();
          while(SST25BY());
          }

          /***********************************
          SST25Write 寫多個字節(jié)
          ***********************************/
          void SST25Write(u32 addr,u8* p_data,u32 no)
          {
          u8 ad[3];
          u32 cnt;
          if(no==0)
          return;

          SST25WriteEn();

          if(no==1)//no<2則應(yīng)使用普通單字節(jié)方式
          {
          SST25ByteProgram(addr,*p_data);
          //SST25WPEN();
          }
          else
          {
          cnt=no;

          ad[2]=(addr>>16)&0xff;
          ad[1]=(addr>>8)&0xff;
          ad[0]=addr&0xff;

          SST_SELECT();
          SPIByte(0xad);
          SPIByte(ad[2]);
          SPIByte(ad[1]);
          SPIByte(ad[0]);
          SPIByte(*p_data++);
          SPIByte(*p_data++);
          SST_DESELECT();
          cnt-=2;
          while(SST25BY());//判忙

          //中間的雙字節(jié)寫
          for(;cnt>1;cnt-=2)
          {
          SST_SELECT();
          SPIByte(0xad);
          SPIByte(*p_data++);
          SPIByte(*p_data++);
          SST_DESELECT();
          while(SST25BY());//判忙
          }
          SST25WRDI();//WRDI用于退出AAI寫模式 所謂AAI 就是地址自動加

          //如果有最后一個字節(jié)(no為奇數(shù))
          if(cnt==1)
          {
          SST25WriteEn();
          SST25ByteProgram(addr+no-1,*p_data);
          }
          }
          SST25WPEN();//WP保護
          }

          //我們用的是下邊這種


          /*************************************
          SST25Read 高速讀 對于后續(xù)帶5的芯片,可調(diào)用此函數(shù)讀
          *************************************/
          void SST25Read(u32 addr,u8* p_data,u32 no)
          {
          SST_SELECT();

          SPIByte(0x0b);
          SPIByte(addr>>16);
          SPIByte(addr>>8);
          SPIByte(addr);
          SPIByte(0xff);

          for(;no>0;no--)
          *p_data++=SPIByte(0xff);
          SST_DESELECT();
          }

          /****************************************
          SST25ReadL 低速讀
          ****************************************/
          void SST25ReadL(u32 addr,u8* p_data,u32 no)
          {
          u8 ad[3];
          ad[2]=(addr>>16)&0xff;
          ad[1]=(addr>>8)&0xff;
          ad[0]=addr&0xff;

          SSTCmd4bs(0x03,ad,p_data,no);
          }


          好了 所有的底層讀寫都做好了~!
          后面~~
          SST25SectorErase(0);//擦除 0~4095 地址之間的數(shù)據(jù)
          SST25Write(addr,db_sst1,64);//往addr 寫入db_sst164個字節(jié)
          SST25Read(addr,db_sst1,64);//從addr讀64個字節(jié)到db_sst1
          就這些接口常用了~~~



          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();