新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > SST25VF080B SPI接口FLASH STM32驅動

        SST25VF080B SPI接口FLASH STM32驅動

        作者: 時間:2016-10-07 來源:網絡 收藏

          所有的FLASHA 都一樣只能從1變0,要想從0變1 只有擦除一個頁扇, SST25VF080B 最小可以擦除4KB的頁 速度也不錯 50MHz 容量1MB 挺夠用的 10萬次的擦寫壽命。最低2.7V 就可正常工作。

        本文引用地址:http://www.104case.com/article/201610/310909.htm

          Flexible Erase Capability

          – Uniform 4 KByte sectors

          – Uniform 32 KByte overlay blocks

          – Uniform 64 KByte overlay blocks

          先記下 這些個7788的命令

          

         

          SST25VF080B 的各種命令比較繁瑣

         

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

          

         

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

         

          

         

          

         

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

          #define SST_SELECT() GPIO_ResetBits(GPIOC, GPIO_Pin_13) /* SST CS = L */

          #define SST_DESELECT() GPIO_SetBits(GPIOC, GPIO_Pin_13) /* SST CS = H */

          /***********************************************

          **函數名:FLASH__Config

          **功能:初始化串行FLASH的接口

          **注意事項:串行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); //預置為高

          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 數據捕獲第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);

          }

          /***************************************

          **函數名:SPIByte

          **功能:讀寫SPI總線

          **注意事項:對于SPI來說,主機的讀也需要先寫,

          **使用此函數,讀的時候建議參數設置為0xff,寫的時候則寫參數.這里使用直接操作寄存器的辦法實現SPI硬件層讀寫,是為了加快速寫速度 在說LCD 的時候我用的就是庫函數 比如

          SPI_I2S_SendData SPI_I2S_ReceiveData SPI_I2S_GetFlagStatus

          ***************************************/

          static u8 SPIByte(u8 byte)

          {

          /*等待發送寄存器空*/

          while((SPI1->SR & SPI_I2S_FLAG_TXE)==RESET);

          /*發送一個字節*/

          SPI1->DR = byte;

          /* 等待接收寄存器有效*/

          while((SPI1->SR & SPI_I2S_FLAG_RXNE)==RESET);

          return(SPI1->DR);

          }

          

         

          //咱用模式0

          /*****************************************

          **函數名:SSTCmd1/2/4

          **功能:寫一個SST命令/寫一個命令后接一個數據/寫一個命令后再寫3個數據

          **注意事項:這是一個完整的單命令操作,不返回

          *****************************************/

          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();

          }

          /****************************************

          **函數名:SSTCmdb1b/SSTCmd4bs

          **功能:寫一個SST命令,返回1字節數據/寫1個命令字,3個地址字,返回多個字節

          **更多使用在讀出上的

          ****************************************/

          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();

          }

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

          常用的芯片功能

          /***************************************

          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**********************************/

          

         

          就是這樣實現寫保護。

          

         

          /**********************************

          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 刷扇區 用的是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 寫一個字節*注意在此前要調用取消寫保護,實際寫應使用AAI,此函數在AAI中調用,用于寫奇數個字節

          **********************************/

          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 寫多個字節

          ***********************************/

          void SST25Write(u32 addr,u8* p_data,u32 no)

          {

          u8 ad[3];

          u32 cnt;

          if(no==0)

          return;

          SST25WriteEn();

          if(no==1) //no<2則應使用普通單字節方式

          {

          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()); //判忙

          //中間的雙字節寫

          for(;cnt>1;cnt-=2)

          {

          SST_SELECT();

          SPIByte(0xad);

          SPIByte(*p_data++);

          SPIByte(*p_data++);

          SST_DESELECT();

          while(SST25BY()); //判忙

          }

          SST25WRDI(); //WRDI用于退出AAI寫模式 所謂AAI 就是地址自動加

          //如果有最后一個字節(no為奇數)

          if(cnt==1)

          {

          SST25WriteEn();

          SST25ByteProgram(addr+no-1,*p_data);

          }

          }

          SST25WPEN();//WP保護

          }

          

         

          //我們用的是下邊這種

          

         

          /*************************************

          SST25Read 高速讀 對于后續帶5的芯片,可調用此函數讀

          *************************************/

          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 地址之間的數據

          SST25Write(addr,db_sst1,64); //往addr 寫入db_sst164個字節

          SST25Read(addr,db_sst1,64); //從addr讀64個字節到db_sst1

          就這些接口常用了~~~



        關鍵詞: STM32 SPI

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 武定县| 石城县| 射洪县| 肥乡县| 铜川市| 怀宁县| 三都| 甘孜县| 土默特右旗| 富阳市| 凤冈县| 称多县| 兴和县| 北海市| 峨眉山市| 轮台县| 故城县| 成安县| 枞阳县| 滁州市| 陈巴尔虎旗| 南昌县| 温州市| 买车| 陆良县| 屏南县| 龙江县| 海淀区| 贵港市| 阿拉善左旗| 徐州市| 隆德县| 东明县| 循化| 尼勒克县| 威远县| 绥阳县| 迁西县| 东港市| 桐庐县| 竹山县|