0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

STM32入門學(xué)習(xí)筆記之外置FLASH讀寫實驗(下)

jf_78858299 ? 來源:滑小稽筆記 ? 作者:電子技術(shù)園地 ? 2023-02-16 14:13 ? 次閱讀

(2)創(chuàng)建w25q128.c并輸入以下代碼。

/*********************************************************************************************************
                FLASH    驅(qū)    動    程    序
*********************************************************************************************************/
#include "w25q128.h" 
#include "delay.h"
/***************************************************
Name    :SPI2_SetSpeed
Function  :SPI2速度設(shè)置函數(shù)
Paramater  :
      SpeedSet:0~7
Return    :None
***************************************************/
void SPI2_SetSpeed( u8 SpeedSet )
{
  SpeedSet &= 0x07 ;                                          //限制范圍
  SPI2->CR1 &= 0xFFC7 ;
  SPI2->CR1 |= SpeedSet<<3 ;                                      //設(shè)置SPI2速度
  SPI2->CR1 |= 1<<6 ;                                          //SPI設(shè)備使能
}
/***************************************************
Name    :SPI2_ReadWriteByte
Function  :SPI2讀寫一個字節(jié)
Paramater  :
      TxData:要寫入的字節(jié)
Return    :讀取到的字節(jié)
***************************************************/
u8 SPI2_ReadWriteByte( u8 TxData )
{
  u16 retry=0;
  //等待發(fā)送區(qū)空
  while( ( SPI2->SR&0x02 )==0 )
  {
    retry ++ ;
    //超時退出
    if( retry>=0xFFFE )
      return 0 ;
  }
  SPI2->DR = TxData ;                                          //發(fā)送一個byte
  //等待接收完一個byte
  retry = 0 ;
  while( ( SPI2->SR&0x01 )==0 )
  {
    retry ++ ;
    //超時退出
    if( retry>=0xFFFE )
      return 0 ;
  }
  return SPI2->DR ;                                          //返回收到的數(shù)據(jù)
}
/***************************************************
Name    :W25QXX_Init
Function  :初始化W25Q128芯片
Paramater  :None
Return    :None
***************************************************/
void W25QXX_Init()
{ 
  RCC->APB2ENR |= 1<<3 ;                                        //PORTB時鐘使能     
  GPIOB->CRH &= 0x0000FFFF ;
  GPIOB->CRH |= 0xBBB30000 ;                                      //PB12推挽輸出+PB13/14/15復(fù)用
  GPIOB->ODR |= 0x7<<13 ;                                        //PB13/14/15上拉
  W25QXX_CS = 1 ;                                            //SPI FLASH不選中
  //初始化SPI
  RCC->APB1ENR |= 1<<14 ;                                        //SPI2時鐘使能
  SPI2->CR1 |= 0<<10 ;                                        //全雙工模式
  SPI2->CR1 |= 1<<9 ;                                          //軟件nss管理
  SPI2->CR1 |= 1<<8 ;
  SPI2->CR1 |= 1<<2 ;                                          //SPI主機
  SPI2->CR1 |= 0<<11 ;                                        //8bit數(shù)據(jù)格式
  SPI2->CR1 |= 1<<1 ;                                          //空閑模式下SCK為1 CPOL=1
  SPI2->CR1 |= 1<<0 ;                                          //數(shù)據(jù)采樣從第二個時間邊沿開始,CPHA=1
  //對SPI2屬于APB1的外設(shè).時鐘頻率最大為36M
  SPI2->CR1 |= 3<<3 ;                                          //Fsck=Fpclk1/256
  SPI2->CR1 |= 0<<7 ;                                          //MSBfirst
  SPI2->CR1 |= 1<<6 ;                                          //SPI設(shè)備使能
  SPI2_ReadWriteByte( 0xFF ) ;                                    //啟動傳輸
  SPI2_SetSpeed( SPI_SPEED_2 ) ;                                    //設(shè)置為18M時鐘,高速模式
}
/***************************************************
Name    :W25QXX_Wait_Busy
Function  :等待空閑
Paramater  :None
Return    :None
***************************************************/
void W25QXX_Wait_Busy()   
{
  u8 byte=0 ;
  // 等待BUSY位清空
  do
  {
    W25QXX_CS = 0 ;                                          //使能器件
    SPI2_ReadWriteByte( W25X_ReadStatusReg ) ;                            //發(fā)送讀取狀態(tài)寄存器命令
    byte = SPI2_ReadWriteByte( 0xFF ) ;                                //讀取一個字節(jié)
    W25QXX_CS = 1 ;                                          //取消片選
  }while( ( byte&0x01 )==0x01 ) ;
}
/***************************************************
Name    :W25QXX_Erase_Chip
Function  :擦除整個芯片
Paramater  :None
Return    :None
***************************************************/
void W25QXX_Erase_Chip()
{
    W25QXX_CS = 0 ;                                            //使能器件
    SPI2_ReadWriteByte( W25X_WriteEnable ) ;                              //發(fā)送寫使能
  W25QXX_CS = 1 ;                                            //取消片選
    W25QXX_Wait_Busy() ;   
    W25QXX_CS=0 ;                                            //使能器件   
    SPI2_ReadWriteByte( W25X_ChipErase ) ;                                //發(fā)送片擦除命令  
  W25QXX_CS = 1 ;                                            //取消片選             
  W25QXX_Wait_Busy() ;                                        //等待芯片擦除結(jié)束
}
/***************************************************
Name    :W25QXX_Erase_Sector
Function  :擦除一個扇區(qū)
Paramater  :
      Address:扇區(qū)地址
Return    :None
***************************************************/
void W25QXX_Erase_Sector( u32 Address )
{
   Address *= 4096 ;
    W25QXX_CS = 0 ;                                            //使能器件
    SPI2_ReadWriteByte( W25X_WriteEnable ) ;                              //發(fā)送寫使能
  W25QXX_CS = 1 ;                                            //取消片選
    W25QXX_Wait_Busy();   
    W25QXX_CS = 0 ;                                            //使能器件
    SPI2_ReadWriteByte( W25X_SectorErase ) ;                              //發(fā)送扇區(qū)擦除指令
    SPI2_ReadWriteByte( ( u8 )( Address>>16 ) ) ;                            //發(fā)送24bit地址
    SPI2_ReadWriteByte( ( u8 )( Address>>8 ) ) ;
    SPI2_ReadWriteByte( ( u8 )Address ) ;
  W25QXX_CS = 1 ;                                            //取消片選
    W25QXX_Wait_Busy() ;                                        //等待擦除完成
}
/***************************************************
Name    :W25QXX_Read
Function  :在指定地址開始讀取指定長度的數(shù)據(jù)
Paramater  :
      pBuffer:數(shù)據(jù)存儲區(qū)
      Address:開始讀取的地址
      Len:要讀取的字節(jié)數(shù)
Return    :None
***************************************************/
void W25QXX_Read( u8 *pBuffer, u32 Address, u16 Len )
{ 
   u16 i ;                           
  W25QXX_CS = 0 ;                                            //使能器件
    SPI2_ReadWriteByte( W25X_ReadData ) ;                                //發(fā)送讀取命令
    SPI2_ReadWriteByte( ( u8 )( Address>>16 ) ) ;                            //發(fā)送24bit地址
    SPI2_ReadWriteByte( ( u8 )( Address>>8 ) ) ;
    SPI2_ReadWriteByte( ( u8 )Address );
    for( i=0; i>16 ) ) ;                            //發(fā)送24bit地址
    SPI2_ReadWriteByte( ( u8 )( Address>>8 ) ) ;
    SPI2_ReadWriteByte( ( u8 )Address ) ;
    for( i=0; ipageremain
     else
    {
      pBuffer += pageremain ;
      Address += pageremain ;
      Len -= pageremain ;                                      //減去已經(jīng)寫入了的字節(jié)數(shù)
      //一次可以寫入256個字節(jié)
      if( Len>256 )
        pageremain = 256 ;
      //不夠256個字節(jié)了
      else
        pageremain = Len ;
    }
  }
}
/***************************************************
Name    :W25QXX_Write_NoCheck
Function  :在指定地址開始寫入指定長度的數(shù)據(jù)
Paramater  :
      pBuffer:數(shù)據(jù)存儲區(qū)
      Address:開始寫入的地址
      Len:要寫入的字節(jié)數(shù)
Return    :None
***************************************************/
u8 W25QXX_BUFFER[ 4096 ] ;
void W25QXX_Write( u8 *pBuffer, u32 Address, u16 Len )
{
  u32 secpos ;
  u16 secoff ;
  u16 secremain ;
   u16 i ;
  u8 *W25QXX_BUF ;
     W25QXX_BUF = W25QXX_BUFFER ;
   secpos = Address/4096 ;                                        //扇區(qū)地址
  secoff = Address%4096 ;                                        //在扇區(qū)內(nèi)的偏移
  secremain = 4096-secoff ;                                      //扇區(qū)剩余空間大小
  //不大于4096個字節(jié)
   if( Len<=secremain )
    secremain = Len ;
  while( 1 )
  {
    W25QXX_Read( W25QXX_BUF, secpos*4096, 4096 ) ;                          //讀出整個扇區(qū)的內(nèi)容
    //校驗數(shù)據(jù)
    for( i=0; i<secremain )
    {
      W25QXX_Erase_Sector( secpos ) ;                                //擦除這個扇區(qū)
      //復(fù)制
      for( i=0; i<secremain; i++ )
        W25QXX_BUF[ i+secoff ] = pBuffer[ i ] ;
      W25QXX_Write_NoCheck( W25QXX_BUF, secpos*4096, 4096 ) ;                    //寫入整個扇區(qū)


    }
    else
      W25QXX_Write_NoCheck( pBuffer, Address, secremain ) ;                    //寫已經(jīng)擦除了的,直接寫入扇區(qū)剩余區(qū)間
    //寫入結(jié)束了
    if( Len==secremain )
      break ;
    //寫入未結(jié)束
    else
    {
      secpos ++ ;                                          //扇區(qū)地址增1
      secoff = 0 ;                                        //偏移位置為0
         pBuffer += secremain ;                                    //指針偏移
      Address += secremain ;                                    //寫地址偏移
         Len -= secremain ;                                      //字節(jié)數(shù)遞減
      //下一個扇區(qū)還是寫不完
      if( Len>4096 )
        secremain = 4096 ;
      //下一個扇區(qū)可以寫完了
      else
        secremain = Len ;
    }
  }
}

(3)在1.c文件中輸入以下代碼。

#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "lcd.h"
#include "w25q128.h"


const u8 TEXT_Buffer[] = { "WarShip STM32F1 SPI TEST" } ;
#define SIZE sizeof( TEXT_Buffer )


int main()
{
  u8 datatemp[ SIZE ] ;
  u32 FLASH_SIZE ;
  STM32_Clock_Init( 9 ) ;                                        //STM32時鐘初始化
  SysTick_Init( 72 ) ;                                        //SysTick初始化
  USART1_Init( 72, 115200 ) ;                                      //初始化串口1波特率115200
  LCD_Init() ;                                            //LCD初始化
  W25QXX_Init() ;                                            //W25QXX初始化
   POINT_COLOR = RED ;                                          //設(shè)置字體為紅色
  FLASH_SIZE = 128*1024*1024 ;                                    //FLASH 大小為16M字節(jié)
  W25QXX_Write( (u8*)TEXT_Buffer, FLASH_SIZE-100, SIZE ) ;                      //從倒數(shù)第100個地址處開始,寫入SIZE長度的數(shù)據(jù)
  W25QXX_Read( datatemp, FLASH_SIZE-100, SIZE ) ;                            //從倒數(shù)第100個地址處開始,讀出SIZE個字節(jié)
  LCD_ShowString( 0, 0, datatemp ) ;                                  //顯示讀到的字符串
  while( 1 )
  {

  }
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 閃存
    +關(guān)注

    關(guān)注

    16

    文章

    1771

    瀏覽量

    114765
  • FlaSh
    +關(guān)注

    關(guān)注

    10

    文章

    1614

    瀏覽量

    147652
  • ROM
    ROM
    +關(guān)注

    關(guān)注

    4

    文章

    562

    瀏覽量

    85623
  • STM32
    +關(guān)注

    關(guān)注

    2264

    文章

    10854

    瀏覽量

    354291
  • EEPROM
    +關(guān)注

    關(guān)注

    9

    文章

    1008

    瀏覽量

    81332
收藏 人收藏

    評論

    相關(guān)推薦

    STM32入門學(xué)習(xí)筆記之外置FLASH讀寫實驗(上)

    Flash,全名叫做Flash EEPROM Memory,即平時所說的“閃存”,它結(jié)合了ROM和RAM的長處,不僅可以反復(fù)擦除,還可以快速讀取數(shù)據(jù),STM32運行的程序其實就是存放在Flas
    的頭像 發(fā)表于 02-16 14:10 ?8788次閱讀
    <b class='flag-5'>STM32</b><b class='flag-5'>入門</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b><b class='flag-5'>之外置</b><b class='flag-5'>FLASH</b><b class='flag-5'>讀寫實驗</b>(上)

    【GD32F470紫藤派開發(fā)板使用手冊】第十二講 SDIO-SD卡讀寫實驗

    通過本實驗主要學(xué)習(xí)以下內(nèi)容: ?SDIO操作原理 ?SD卡讀寫實現(xiàn)
    的頭像 發(fā)表于 05-18 09:36 ?1264次閱讀
    【GD32F470紫藤派開發(fā)板使用手冊】第十二講 SDIO-SD卡<b class='flag-5'>讀寫實驗</b>

    如何對擴展存儲器進行讀寫實驗

    擴展存儲器讀寫實驗的目的是什么?怎樣去設(shè)計一種擴展存儲器讀寫的電路?擴展存儲器讀寫實驗的流程有哪些?
    發(fā)表于 07-14 07:04

    如何通過對flash讀寫實現(xiàn)stm32的編程操作?

    如何通過對flash讀寫實現(xiàn)stm32的編程操作?
    發(fā)表于 10-29 06:19

    接觸式IC卡讀寫實驗

    接觸式IC卡讀寫實驗 一. 實驗目的了解接觸式IC 卡的知識,
    發(fā)表于 09-22 17:20 ?4688次閱讀
    接觸式IC卡<b class='flag-5'>讀寫實驗</b>

    AVR內(nèi)部EEPROM讀寫實驗

    片內(nèi)EEPROM讀寫實險。?1、用內(nèi)部EEPROM記錄CPU啟動次數(shù),并在PB口上顯示出來。?2、內(nèi)部1 M晶振,程序采用單任務(wù)方式,軟件延時。?3、進行此實驗
    發(fā)表于 06-30 11:25 ?2531次閱讀

    STM32_ SPI讀寫Flash

    STM32_SPI讀寫Flash
    的頭像 發(fā)表于 04-08 10:26 ?5458次閱讀
    <b class='flag-5'>STM32</b>_ SPI<b class='flag-5'>讀寫</b><b class='flag-5'>Flash</b>

    單片機實驗匯編--擴展存儲器讀寫實驗

    擴展存儲器讀寫實驗一.實驗要求編制簡單程序,對實驗板上提供的外部存貯器(62256)進行讀寫操作。二.實驗目的1.
    發(fā)表于 11-23 09:51 ?19次下載
    單片機<b class='flag-5'>實驗</b>匯編--擴展存儲器<b class='flag-5'>讀寫實驗</b>

    STM32內(nèi)部Flash讀寫問題

    STM32Flash讀寫Flash調(diào)試技巧文章目錄先熟悉所用MCU的Flash存儲大小以及扇區(qū)地址Flsah寫之前為什么要先擦除Flash
    發(fā)表于 12-01 20:21 ?20次下載
    <b class='flag-5'>STM32</b>內(nèi)部<b class='flag-5'>Flash</b><b class='flag-5'>讀寫</b>問題

    STM32F103學(xué)習(xí)筆記——SPI讀寫Flash(一)

    STM32F103學(xué)習(xí)筆記——SPI讀寫Flash(一)??此系列文章是小白學(xué)習(xí)
    發(fā)表于 12-02 12:06 ?19次下載
    <b class='flag-5'>STM32</b>F103<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>——SPI<b class='flag-5'>讀寫</b><b class='flag-5'>Flash</b>(一)

    STM32F103學(xué)習(xí)筆記——SPI讀寫Flash(三)

    ??此系列文章是小白學(xué)習(xí)STM32的一些學(xué)習(xí)筆記。小白第一次寫筆記文章,有不足或是錯誤之處,請多體諒和交流!目錄1.
    發(fā)表于 12-22 19:29 ?11次下載
    <b class='flag-5'>STM32</b>F103<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>——SPI<b class='flag-5'>讀寫</b><b class='flag-5'>Flash</b>(三)

    STM32F103學(xué)習(xí)筆記——SPI讀寫Flash(二)

    ??此系列文章是小白學(xué)習(xí)STM32的一些學(xué)習(xí)筆記。小白第一次寫筆記文章,有不足或是錯誤之處,請多體諒和交流!目錄1.軟件設(shè)計流程2.SPI初
    發(fā)表于 12-22 19:30 ?10次下載
    <b class='flag-5'>STM32</b>F103<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>——SPI<b class='flag-5'>讀寫</b><b class='flag-5'>Flash</b>(二)

    STM32F103學(xué)習(xí)筆記——SPI讀寫Flash(四)

    ??此系列文章是小白學(xué)習(xí)STM32的一些學(xué)習(xí)筆記。小白第一次寫筆記文章,有不足或是錯誤之處,請多體諒和交流!目錄1.main函數(shù)編寫2.下載
    發(fā)表于 12-22 19:32 ?6次下載
    <b class='flag-5'>STM32</b>F103<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>——SPI<b class='flag-5'>讀寫</b><b class='flag-5'>Flash</b>(四)

    外置FLASH讀寫實驗

    Flash,全名叫做Flash EEPROM Memory,即平時所說的“閃存”,它結(jié)合了ROM和RAM的長處,不僅可以反復(fù)擦除,還可以快速讀取數(shù)據(jù),STM32運行的程序其實就是存放在Flas
    的頭像 發(fā)表于 03-01 14:56 ?4776次閱讀

    【GD32F303紅楓派開發(fā)板使用手冊】第二十三講 SDIO-SD卡讀寫實驗

    通過本實驗主要學(xué)習(xí)以下內(nèi)容: ?SDIO操作原理 ?SD卡讀寫實現(xiàn)
    的頭像 發(fā)表于 06-23 10:49 ?517次閱讀
    【GD32F303紅楓派開發(fā)板使用手冊】第二十三講 SDIO-SD卡<b class='flag-5'>讀寫實驗</b>