【CC2640R2F】香瓜CC2640R2F之SPI讀寫W25Q80

本文最后修改時間:2022年01月08日 10:45

一、本節簡介

本節以simple_peripheral工程為例,介紹如何使用SPI讀寫W25Q80(外部flash)。

二、實驗平臺

1)CC2640R2F平臺

①協議棧版本:CC2640R2 SDK v1.40.00.45

②編譯軟件:CCS7.3.0.00019

③硬件平臺:香瓜CC2640R2F開發板

④仿真器:香瓜XDS100V3下載器

2)外設

①板載在香瓜CC2640R2F開發板底板上的芯片:W25Q80

三、版權聲明

1)作者:甜甜的大香瓜

2)聲明:喝水不忘挖井人,轉載請注明出處。

3)糾錯/業務合作:897503845@qq.com

4)香瓜BLE之CC2640R2F群:557278427

5)本文出處:原創連載資料《簡單粗暴學藍牙5》

6)完整開源資料下載地址(電腦端打開):

opengua.taobao.com

7)香瓜CC2640R2F開發板購買鏈接:

https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4023-16963296339.8.21bfc58419sWKt&id=558653143169

四、實驗前提

1、在進行本文步驟前,請先閱讀以下章節:

1)《簡單粗暴學藍牙5》的“第一章至第四章”章節?。

2、在進行本文步驟前,請先實現以下章節:

1)《簡單粗暴學藍牙5》的“第三章 軟件的安裝及使用”章節。

五、基礎知識

1、W25Q80是什么?

答: W25Q80是winbond(華邦)公司出的8M bit(也就是1MB)的flash芯片。同系列常用的型號還有W25Q16(16Mb=2MB)、W25Q32(32Mb=4MB)等。

2、W25Q80的基本信息?

答:

如上圖,W25Q80一次可寫256字節、可4K字節扇區擦除、32K或者64K塊擦除、整片擦除。

使用的是SPI接口、2.7V~3.6V電壓范圍,香瓜購買的是8-pin SOIC 208-mil封裝。

如上圖,W25Q80的廠商ID是0xEF,設備ID是0x13。這個用于初始化時識別flash芯片用。

六、硬件原理

1、W25Q80芯片引腳圖

如上圖,W25Q80一共8個腳,其中GND和VCC供電3.3V(范圍在2.7V~3.6V)即可,其他4個SPI引腳DO(輸出)、DI(輸入)、CLK(時鐘)、CS(片選)。

WP(寫保護)、HOLD(保持輸入)這兩個引腳本文并沒有用到,且“/WP”中的“/”是低電平有效的意思,所以我們本文將WP和HOLD兩引腳拉高到VCC即可。

2、W25Q80與香瓜CC2640R2F開發板的對應關系

W25Q80引腳

香瓜CC2640R2F開發板引腳

引腳1(/CS)

DIO_30

引腳2(DO)

DIO_8

引腳3(/WP)

置高到VCC

引腳4(GND)

GND

引腳5(DI)

DIO_9

引腳6(CLK)

DIO_10

引腳7(/HOLD)

置高到VCC

引腳6(VCC)

3.3V

3、硬件原理圖

七、實驗步驟

1、編寫并添加自定義的W25Q80驅動

1)寫一個驅動GUA_ExtFlash.c(存放在“……

\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\ble5stack\simple_peripheral\src\app\GUA“路徑下)

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

//name:???????? GUA_ExtFlash.c

//introduce:??? 外部flash驅動

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

#include “string.h”

#include <ti/devices/cc26x0r2/driverlib/Ssi.h>

#include <ti/drivers/spi/SPICC26XXDMA.h>

#include <ti/drivers/dma/UDMACC26XX.h>

#include <ti/drivers/SPI.h>

#include “GUA_ExtFlash.h”

/*********************宏定義************************/

//SPI引腳

#define GUA_CC2640R2_SPI0_MISO????????????? IOID_8

#define GUA_CC2640R2_SPI0_MOSI????????????? IOID_9

#define GUA_CC2640R2_SPI0_CLK?????????????? IOID_10

#define GUA_CC2640R2_SPI0_CSN?????????????? PIN_UNASSIGNED

#define GUA_Spi_flash_CS??????????????????? IOID_30

//SPI片選開關宏

#define GUA_FLASH_CS_ON???????????????????? 0

#define GUA_FLASH_CS_OFF??????????????????? 1

/* Instruction codes */

#define GUA_BLS_CODE_PROGRAM??????????????? 0x02 /**< Page Program */

#define GUA_BLS_CODE_READ?????????????????? 0x03 /**< Read Data */

#define GUA_BLS_CODE_READ_STATUS??????????? 0x05 /**< Read Status Register */

#define GUA_BLS_CODE_WRITE_ENABLE?????????? 0x06 /**< Write Enable */

#define GUA_BLS_CODE_SECTOR_ERASE?????????? 0x20 /**< Sector Erase */

#define GUA_BLS_CODE_MDID?????????????????? 0x90 /**< Manufacturer Device ID */

#define GUA_BLS_CODE_DP???????????????????? 0xB9 /**< Power down */

#define GUA_BLS_CODE_RDP??????????????????? 0xAB /**< Power standby */

/* Erase instructions */

#define GUA_BLS_CODE_ERASE_4K?????????????? 0x20 /**< Sector Erase */

#define GUA_BLS_CODE_ERASE_32K????????????? 0x52

#define GUA_BLS_CODE_ERASE_64K????????????? 0xD8

#define GUA_BLS_CODE_ERASE_ALL????????????? 0xC7 /**< Mass Erase */

/* Bitmasks of the status register */

#define GUA_BLS_STATUS_SRWD_BM????????????? 0x80

#define GUA_BLS_STATUS_BP_BM??????????????? 0x0C

#define GUA_BLS_STATUS_WEL_BM?????????????? 0x02

#define GUA_BLS_STATUS_WIP_BM?????????????? 0x01

#define GUA_BLS_STATUS_BIT_BUSY???????????? 0x01 /**< Busy bit of the status register */

/* Part specific constants */

#define GUA_BLS_PROGRAM_PAGE_SIZE?????????? 256

#define GUA_BLS_ERASE_SECTOR_SIZE?????????? 4096

/* Manufacturer IDs */

#define GUA_MF_MACRONIX???????????????????? 0xC2

#define GUA_MF_WINBOND????????????????????? 0xEF

typedef enum GUA_CC2640R2_SPIName {

GUA_CC2640R2_SPI0 = 0,

GUA_CC2640R2_SPICOUNT

} GUA_CC2640R2_SPIName;

SPICC26XXDMA_Object GUA_spiCC26XXDMAObjects[GUA_CC2640R2_SPICOUNT];

//SPI速度4M

#define GUA_SPI_BIT_RATE??????????????????? 4000000

//flash每頁大小4K

#define GUA_EXT_FLASH_PAGE_SIZE???????????? 4096

/*********************內部變量************************/

const SPICC26XXDMA_HWAttrsV1 GUA_spiCC26XXDMAHWAttrs[GUA_CC2640R2_SPICOUNT] = {

{

??????? .baseAddr?????????? = SSI0_BASE,

??????? .intNum???????????? = INT_SSI0_COMB,

??????? .intPriority??????? = ~0,

??????? .swiPriority??????? = 0,

??????? .powerMngrId?????? ?= PowerCC26XX_PERIPH_SSI0,

??????? .defaultTxBufValue? = 0,

??????? .rxChannelBitMask?? = 1<<UDMA_CHAN_SSI0_RX,

??????? .txChannelBitMask?? = 1<<UDMA_CHAN_SSI0_TX,

??????? .mosiPin??????????? = GUA_CC2640R2_SPI0_MOSI,

??????? .misoPin??????????? = GUA_CC2640R2_SPI0_MISO,

??????? .clkPin???????????? = GUA_CC2640R2_SPI0_CLK,

??????? .csnPin???????????? = GUA_CC2640R2_SPI0_CSN

}

};

const SPI_Config GUA_SPI_config[GUA_CC2640R2_SPICOUNT] = {

{

???????? .fxnTablePtr = &SPICC26XXDMA_fxnTable,

???????? .object????? = &GUA_spiCC26XXDMAObjects[GUA_CC2640R2_SPI0],

???????? .hwAttrs???? = &GUA_spiCC26XXDMAHWAttrs[GUA_CC2640R2_SPI0]

},

};

const uint_least8_t GUA_SPI_count = GUA_CC2640R2_SPICOUNT;

static PIN_Config GUA_BoardFlashPinTable[] =

{

GUA_Spi_flash_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MIN, /* Ext. flash chip select */

PIN_TERMINATE

};

static PIN_Handle GUA_hFlashPin = NULL;

static PIN_State GUA_pinState;

// Supported flash devices

static GUA_ExtFlashInfo_t GUA_flashInfo[] =

{

{

??????? .manfId = GUA_MF_MACRONIX,? // Macronics

??????? .devId = 0x15,????????????? // MX25R1635F

??????? .deviceSize = 0x200000????? // 2 Mbyte (16 Mbit)

},

{

??????? .manfId = GUA_MF_MACRONIX,? // Macronics

??????? .devId = 0x14,????????????? // MX25R8035F

??????? .deviceSize = 0x100000????? // 1 Mbyte (8 Mbit)

},

{

??????? .manfId = GUA_MF_WINBOND,?? // WinBond

??????? .devId = 0x13,????????????? // W25Q80DV

??????? .deviceSize = 0x100000????? // 1 Mbyte (8 Mbit)

},

{

??????? .manfId = GUA_MF_WINBOND,?? // WinBond

??????? .devId = 0x12,????????????? // W25X40CL

??????? .deviceSize = 0x080000????? // 512 Kbyte (4 Mbit)

},

{

??????? .manfId = GUA_MF_WINBOND,?? // WinBond

??????? .devId = 0x11,????????????? // W25X20CL

??????? .deviceSize = 0x040000????? // 256 Kbyte (2 Mbit)

},

{

??????? .manfId = 0x0,

??????? .devId = 0x0,

??????? .deviceSize = 0x0

}

};

// Flash information

static GUA_ExtFlashInfo_t *pGUA_flashInfo = NULL;

static GUA_U8 GUA_infoBuf[2];

// SPI interface

static SPI_Handle GUA_spiHandle = NULL;

static SPI_Params GUA_spiParams;

/*********************內部函數************************/

static int GUA_Spi_write(const GUA_U8 *pGUA_buf, size_t GUA_length);

static int GUA_Spi_read(GUA_U8 *pGUA_buf, size_t GUA_length);

static bool GUA_Spi_open(GUA_U32 GUA_bitRate);

static void GUA_Spi_close(void);

static void GUA_Spi_flash(void);

static void GUA_extFlashSelect(void);

static void GUA_extFlashDeselect(void);

static bool GUA_extFlashPowerDown(void);

static bool GUA_extFlashPowerStandby(void);

static bool GUA_ExtFlash_readInfo(void);

static bool GUA_extFlashVerifyPart(void);

static int GUA_ExtFlash_waitReady(void);

static int GUA_ExtFlash_powerDown(void);

static int GUA_ExtFlash_writeEnable(void);

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

//name:???????? GUA_Spi_write

//introduce:??? SPI設備

//parameter:??? pGUA_buf:寫緩存

//????????????? GUA_len:數據長度

//return:?????? 如果操作正常,返回0;反之返回1

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static int GUA_Spi_write(const GUA_U8 *pGUA_buf, size_t GUA_len)

{

SPI_Transaction masterTransaction;

masterTransaction.count? = GUA_len;

masterTransaction.txBuf? = (void*)pGUA_buf;

masterTransaction.arg??? = NULL;

masterTransaction.rxBuf? = NULL;

return SPI_transfer(GUA_spiHandle, &masterTransaction) ? 0 : -1;

}

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

//name:???????? GUA_Spi_read

//introduce:??? SPI設備

//parameter:??? pGUA_buf:讀緩存

//????????????? GUA_len:數據長度

//return:?????? 如果操作正常,返回0;反之返回1

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static int GUA_Spi_read(GUA_U8 *pGUA_buf, size_t GUA_len)

{

SPI_Transaction masterTransaction;

masterTransaction.count = GUA_len;

masterTransaction.txBuf = NULL;

masterTransaction.arg = NULL;

masterTransaction.rxBuf = pGUA_buf;

return SPI_transfer(GUA_spiHandle, &masterTransaction) ? 0 : -1;

}

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

//name:???????? GUA_Spi_open

//introduce:??? 打開SPI

//parameter:??? GUA_bitRate:要設置的SPI速度

//return:?????? 如果操作正常,返回true;反之返回false

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static bool GUA_Spi_open(GUA_U32 GUA_bitRate)

{

/*? Configure SPI as master */

SPI_Params_init(&GUA_spiParams);

GUA_spiParams.bitRate = GUA_bitRate;

GUA_spiParams.mode = SPI_MASTER;

GUA_spiParams.transferMode = SPI_MODE_BLOCKING;

/* Attempt to open SPI. */

GUA_spiHandle = SPI_open(GUA_CC2640R2_SPI0, &GUA_spiParams);

return GUA_spiHandle != NULL;

}

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

//name:???????? GUA_Spi_close

//introduce:??? 關閉SPI

//parameter:??? none

//return:?????? none

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static void GUA_Spi_close(void)

{

if (GUA_spiHandle != NULL)

{

??????? // Close the RTOS driver

??????? SPI_close(GUA_spiHandle);

??????? GUA_spiHandle = NULL;

}

}

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

//name:???????? GUA_Spi_flash

//introduce:??? 把沒用的垃圾數據處理掉

//parameter:??? none

//return: ??????none

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static void GUA_Spi_flash(void)

{

/* make sure SPI hardware module is done? */

while(SSIBusy(((SPICC26XXDMA_HWAttrsV1*)GUA_spiHandle->hwAttrs)->baseAddr))

{ };

}

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

//name:???????? GUA_extFlashSelect

//introduce:??? 片選引腳選擇外部flash

//parameter:??? none

//return:?????? none

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static void GUA_extFlashSelect(void)

{

PIN_setOutputValue(GUA_hFlashPin, GUA_Spi_flash_CS, GUA_FLASH_CS_ON);

}

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

//name:???????? GUA_extFlashDeselect

//introduce:??? 取消片選引腳選擇外部flash

//parameter:??? none

//return:?????? none

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static void GUA_extFlashDeselect(void)

{

PIN_setOutputValue(GUA_hFlashPin, GUA_Spi_flash_CS, GUA_FLASH_CS_OFF);

}

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

//name:???????? GUA_extFlashPowerDown

//introduce:??? 讓設備進入低功耗模式,不能訪問數據,只能讀取寄存器狀態

//parameter:??? none

//return:?????? 如果操作正常,返回true;反之返回false

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static bool GUA_extFlashPowerDown(void)

{

GUA_U8 GUA_cmd;

bool GUA_success;

GUA_cmd = GUA_BLS_CODE_DP;

GUA_extFlashSelect();

GUA_success = GUA_Spi_write(&GUA_cmd, sizeof(GUA_cmd)) == 0;

GUA_extFlashDeselect();

return GUA_success;

}

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

//name:???????? GUA_extFlashPowerStandby

//introduce:??? 退出低功耗模式

//parameter:??? none

//return:?????? 如果操作正常,返回true;反之返回false

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static bool GUA_extFlashPowerStandby(void)

{

GUA_U8 GUA_cmd;

bool GUA_success;

GUA_cmd = GUA_BLS_CODE_RDP;

GUA_extFlashSelect();

GUA_success = GUA_Spi_write(&GUA_cmd, sizeof(GUA_cmd)) == 0;

GUA_extFlashDeselect();

if(GUA_success)

{

??????? if(GUA_ExtFlash_waitReady() != 0)

??????? {

??????????? GUA_success = false;

??????? }

}

return GUA_success;

}

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

//name:???????? GUA_ExtFlash_readInfo

//introduce:??? flash信息(廠商ID和設備ID

//parameter:??? none

//return:?????? 如果操作正常,返回true;反之返回false

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static bool GUA_ExtFlash_readInfo(void)

{

const GUA_U8 GUA_wbuf[] = {GUA_BLS_CODE_MDID, 0xFF, 0xFF, 0x00};

GUA_extFlashSelect();

int GUA_ret = GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf));

if(GUA_ret)

{

??????? GUA_extFlashDeselect();

??????? return false;

}

GUA_ret = GUA_Spi_read(GUA_infoBuf, sizeof(GUA_infoBuf));

GUA_extFlashDeselect();

return GUA_ret == 0;

}

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

//name:???????? GUA_extFlashVerifyPart

//introduce:??? 校驗flash芯片是否是驅動支持的flash

//parameter:??? none

//return:?????? 如果操作正常,返回true;反之返回false

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static bool GUA_extFlashVerifyPart(void)

{

if(!GUA_ExtFlash_readInfo())

{

??????? return false;

}

pGUA_flashInfo = GUA_flashInfo;

while(pGUA_flashInfo->deviceSize > 0)

{

??????? if(GUA_infoBuf[0] == pGUA_flashInfo->manfId && GUA_infoBuf[1] == pGUA_flashInfo->devId)

??????? {

??????????? break;

??????? }

??????? pGUA_flashInfo++;

}

return pGUA_flashInfo->deviceSize > 0;

}

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

//name:???????? GUA_ExtFlash_waitReady

//introduce:??? 等待當前擦除、編程的操作結束

//parameter:??? none

//return:?????? 如果操作正常,返回0;反之返回非0

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static int GUA_ExtFlash_waitReady(void)

{

const GUA_U8 GUA_wbuf[1] = {GUA_BLS_CODE_READ_STATUS};

int GUA_ret;

/* Throw away all garbage */

GUA_extFlashSelect();

GUA_Spi_flash();

GUA_extFlashDeselect();

for(;;)

{

??????? GUA_U8 GUA_buf;

??????? GUA_extFlashSelect();

??????? GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf));

??????? GUA_ret = GUA_Spi_read(&GUA_buf, sizeof(GUA_buf));

??????? GUA_extFlashDeselect();

??????? if(GUA_ret)

??????? {

??????????? /* Error */

??????????? return -2;

??????? }

??????? if(!(GUA_buf & GUA_BLS_STATUS_BIT_BUSY))

??????? {

??????????? /* Now ready */

??????????? break;

??????? }

}

return 0;

}

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

//name:???????? GUA_ExtFlash_powerDown

//introduce:??? 等待進入低功耗模式

//parameter:??? none

//return:?????? 如果操作正常,返回0;反之返回非0

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static int GUA_ExtFlash_powerDown(void)

{

GUA_U8 GUA_i;

GUA_i = 0;

while(GUA_i < 10)

{

??????? if(!GUA_ExtFlash_readInfo())

??????? {

??????????? return 0;

??????? }

??????? GUA_i++;

}

return -1;

}

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

//name:???????? GUA_ExtFlash_writeEnable

//introduce:??? 啟動寫操作

//parameter:??? none

//return:?????? 如果操作正常,返回0;反之返回非0

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

static int GUA_ExtFlash_writeEnable(void)

{

const GUA_U8 GUA_wbuf[] = {GUA_BLS_CODE_WRITE_ENABLE};

GUA_extFlashSelect();

int GUA_ret = GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf));

GUA_extFlashDeselect();

if(GUA_ret)

{

??????? return -3;

}

return 0;

}

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

//name:???????? GUA_ExtFlash_open

//introduce:??? 初始化flash

//parameter:??? none

//return:?????? 如果操作正常,返回true;反之返回false

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

bool GUA_ExtFlash_open(void)

{

bool GUA_f;

GUA_hFlashPin = PIN_open(&GUA_pinState, GUA_BoardFlashPinTable);

if(GUA_hFlashPin == NULL)

{

??????? return false;

}

/* Initialise SPI. Subsequent calls will do nothing. */

SPI_init();

/* Make sure SPI is available */

GUA_f = GUA_Spi_open(GUA_SPI_BIT_RATE);

if (GUA_f)

{

??????? /* Put the part is standby mode */

??????? GUA_f = GUA_extFlashPowerStandby();

??????? if(GUA_f)

??????? {

??????????? /* Verify manufacturer and device ID */

??????????? GUA_f = GUA_extFlashVerifyPart();

??????? }

??????? if(!GUA_f)

??????? {

??????????? GUA_ExtFlash_close();

??????? }

}

return GUA_f;

}

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

//name:???????? GUA_ExtFlash_close

//introduce:??? 關閉flash

//parameter:??? none

//return:?????? 如果操作正常,返回true;反之返回false

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

void GUA_ExtFlash_close(void)

{

if(GUA_hFlashPin != NULL)

{

??????? // Put the part in low power mode

??????? GUA_extFlashPowerDown();

??????? if(pGUA_flashInfo->manfId == GUA_MF_WINBOND)

??????? {

??????????? GUA_ExtFlash_powerDown();

??????? }

??????? /* Make sure SPI lines have a defined state */

??????? GUA_Spi_close();

??????? PIN_close(GUA_hFlashPin);

??????? GUA_hFlashPin = NULL;

}

}

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

//name:???????? GUA_ExtFlash_read

//introduce:??? flash

//parameter:??? GUA_offset:偏移地址

//????????????? GUA_length:數據長度

//????????????? pGUA_buf:接收緩存區

//return:?????? 如果操作正常,返回true;反之返回false

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

bool GUA_ExtFlash_read(size_t GUA_offset, size_t GUA_length, GUA_U8 *pGUA_buf)

{

GUA_U8 GUA_wbuf[4];

/* Wait till previous erase/program operation completes */

int GUA_ret = GUA_ExtFlash_waitReady();

if(GUA_ret)

{

??????? return false;

}

/* SPI is driven with very low frequency (1MHz < 33MHz fR spec)

* in this temporary implementation.

* and hence it is not necessary to use fast read. */

GUA_wbuf[0] = GUA_BLS_CODE_READ;

GUA_wbuf[1] = (GUA_offset >> 16) & 0xff;

GUA_wbuf[2] = (GUA_offset >> 8) & 0xff;

GUA_wbuf[3] = GUA_offset & 0xff;

GUA_extFlashSelect();

if(GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf)))

{

??????? /* failure */

??????? GUA_extFlashDeselect();

??????? return false;

}

GUA_ret = GUA_Spi_read(pGUA_buf, GUA_length);

GUA_extFlashDeselect();

return GUA_ret == 0;

}

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

//name:???????? GUA_ExtFlash_write

//introduce:??? flash

//parameter:? ??GUA_offset:偏移地址

//????????????? GUA_length:數據長度

//????????????? pGUA_buf:發送緩存區

//return:?????? 如果操作正常,返回true;反之返回false

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

bool GUA_ExtFlash_write(size_t GUA_offset, size_t GUA_length, const GUA_U8 *pGUA_buf)

{

GUA_U8 GUA_wbuf[4];

while(GUA_length > 0)

{

??????? /* Wait till previous erase/program operation completes */

??????? int GUA_ret = GUA_ExtFlash_waitReady();

??????? if(GUA_ret)

??????? {

??????????? return false;

??????? }

??????? GUA_ret = GUA_ExtFlash_writeEnable();

??????? if (GUA_ret)

??????? {

??????????? return false;

??????? }

??????? size_t GUA_ilen; /* interim GUA_length per instruction */

??????? GUA_ilen = GUA_BLS_PROGRAM_PAGE_SIZE – (GUA_offset % GUA_BLS_PROGRAM_PAGE_SIZE);

??????? if (GUA_length < GUA_ilen)

??????? {

??????????? GUA_ilen = GUA_length;

??????? }

??????? GUA_wbuf[0] = GUA_BLS_CODE_PROGRAM;

??????? GUA_wbuf[1] = (GUA_offset >> 16) & 0xff;

??????? GUA_wbuf[2] = (GUA_offset >> 8) & 0xff;

??????? GUA_wbuf[3] = GUA_offset & 0xff;

??????? GUA_offset += GUA_ilen;

??????? GUA_length -= GUA_ilen;

??????? /* Up to 100ns CS hold time (which is not clear

??????? * whether it’s application only in between reads)

??????? * is not imposed here since above instructions

??????? * should be enough to delay

??????? * as much. */

??????? GUA_extFlashSelect();

??????? if (GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf)))

??????? {

??????????? /* failure */

??????????? GUA_extFlashDeselect();

??????????? return false;

??????? }

?? ?????if (GUA_Spi_write(pGUA_buf, GUA_ilen))

??????? {

??????????? /* failure */

??????????? GUA_extFlashDeselect();

??????????? return false;

??????? }

??????? pGUA_buf += GUA_ilen;

??????? GUA_extFlashDeselect();

}

return true;

}

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

//name:???????? GUA_ExtFlash_erase

//introduce:??? 擦除flash

//parameter:??? GUA_offset:偏移地址

//????????????? GUA_length:數據長度

//????????????? pGUA_buf:發送緩存區

//return:?????? 如果操作正常,返回true;反之返回false

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

bool GUA_ExtFlash_erase(size_t GUA_offset, size_t GUA_length)

{

/* Note that Block erase might be more efficient when the floor map

* is well planned for OTA but to simplify for the temporary implementation,

* sector erase is used blindly. */

GUA_U8 GUA_wbuf[4];

size_t GUA_i, GUA_numsectors;

GUA_wbuf[0] = GUA_BLS_CODE_SECTOR_ERASE;

{

??????? size_t GUA_endoffset = GUA_offset + GUA_length – 1;

??????? GUA_offset = (GUA_offset / GUA_BLS_ERASE_SECTOR_SIZE) * GUA_BLS_ERASE_SECTOR_SIZE;

??????? GUA_numsectors = (GUA_endoffset – GUA_offset + GUA_BLS_ERASE_SECTOR_SIZE – 1) /

??????????? GUA_BLS_ERASE_SECTOR_SIZE;

}

for(GUA_i = 0; GUA_i < GUA_numsectors; GUA_i++)

{

??????? /* Wait till previous erase/program operation completes */

??????? int GUA_ret = GUA_ExtFlash_waitReady();

??????? if(GUA_ret)

??????? {

??????????? return false;

??????? }

??????? GUA_ret = GUA_ExtFlash_writeEnable();

??????? if(GUA_ret)

??????? {

??????????? return false;

??????? }

??????? GUA_wbuf[1] = (GUA_offset >> 16) & 0xff;

??????? GUA_wbuf[2] = (GUA_offset >> 8) & 0xff;

??????? GUA_wbuf[3] = GUA_offset & 0xff;

??????? GUA_extFlashSelect();

??????? if(GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf)))

??????? {

??????????? /* failure */

??????????? GUA_extFlashDeselect();

??????????? return false;

??????? }

??????? GUA_extFlashDeselect();

??????? GUA_offset += GUA_BLS_ERASE_SECTOR_SIZE;

}

return true;

}

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

//name:???????? GUA_ExtFlash_info

//introduce:??? 獲取當前連接的外部flash的信息

//parameter:??? none

//return:?????? ExtFlashInfo_t(包含設備內存大小、廠商ID、設備ID)

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

GUA_ExtFlashInfo_t *GUA_ExtFlash_info(void)

{

return pGUA_flashInfo;

}

2)寫一個驅動頭文件GUA_ExtFlash.h(存放在“……

\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\ble5stack\simple_peripheral\src\app\GUA“路徑下)

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

//name:???????? GUA_ExtFlash.h

//introduce:??? 外部flash驅動的頭文件

//author:?????? 甜甜的大香瓜

//email:??????? 897503845@qq.com

//QQ group:???? 香瓜BLECC2640R2F(557278427)

//shop:???????? opengua.taobao.com

//changetime:?? 2021.08.02

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

#ifndef GUA_EXT_FLASH_H

#define GUA_EXT_FLASH_H

//頭文件

#include <stdlib.h>

#include <stdbool.h>

/*********************宏定義************************/

//類型宏

#ifndef GUA_C

typedef char GUA_C;

#endif

#ifndef GUA_U8

typedef unsigned char GUA_U8;

#endif

#ifndef GUA_8

typedef signed char GUA_8;

#endif

#ifndef GUA_U16

typedef unsigned short GUA_U16;

#endif

#ifndef GUA_16

typedef signed short GUA_16;

#endif

#ifndef GUA_U32

typedef unsigned long GUA_U32;

#endif

#ifndef GUA_32

typedef signed long GUA_32;

#endif

#ifndef GUA_U64

typedef unsigned long long GUA_U64;

#endif

#ifndef GUA_64

typedef signed long long GUA_64;

#endif

/*********************外部變量************************/

//設備信息結構體

typedef struct

{

GUA_U32 deviceSize; // bytes

GUA_U8 manfId;????? // manufacturer ID

GUA_U8 devId;?????? // device ID

} GUA_ExtFlashInfo_t;

/*********************函數聲明************************/

extern bool GUA_ExtFlash_open(void);

extern void GUA_ExtFlash_close(void);

extern bool GUA_ExtFlash_read(size_t GUA_offset, size_t GUA_length, GUA_U8 *pGUA_buf);

extern bool GUA_ExtFlash_write(size_t GUA_offset, size_t GUA_length, const GUA_U8 *pGUA_buf);

extern bool GUA_ExtFlash_erase(size_t GUA_offset, size_t GUA_length);

extern GUA_ExtFlashInfo_t *GUA_ExtFlash_info(void);

#endif

3、工程中添加驅動文件GUA_ExtFlash.c、GUA_ExtFlash.h

注:拖拽至CCS工程的Application文件夾下

添加文件過程中,選項選擇如下

4、應用層調用

1)添加頭文件(simple_peripheral.c中)

//GUA

#include “GUA_ ExtFlash.h”

//GUA

2)添加測試代碼(simple_peripheral.c的SimpleBLEPeripheral_init函數末尾中)

//GUA

GUA_U32 GUA_offset = 0x012233;

GUA_U8 GUA_write_buf[7] = {‘o’,’p’,’e’,’n’,’g’,’u’,’a’};

GUA_U8 GUA_read_buf[7] = {0};

bool GUA_flash_Ret;

//初始化flash

GUA_flash_Ret = GUA_ExtFlash_open();

if(GUA_flash_Ret == true)

{

??????? //擦除flash

??????? GUA_flash_Ret = GUA_ExtFlash_erase(GUA_offset, sizeof(GUA_write_buf));

??????? if(GUA_flash_Ret == true)

??????? {

??????????? //flash

??????????? GUA_flash_Ret = GUA_ExtFlash_write(GUA_offset, sizeof(GUA_write_buf), GUA_write_buf);

??????????? if(GUA_flash_Ret == true)

??????????? {

??????????????? //flash

??????????????? GUA_flash_Ret = GUA_ExtFlash_read(GUA_offset, sizeof(GUA_read_buf), GUA_read_buf);

??????????????? if(GUA_flash_Ret == true)

??????????????? {

??????????????????? //讀正確后關flash

??????????????????? GUA_ExtFlash_close();

??????????????? }

??????????? }

??????? }

}

//GUA

上述代碼,先將0x012233地址擦除7個字節,再寫入7個字節“opengua”,再讀出7個字節,判斷是否讀出的是“opengua”,以此來判斷是否有正常寫入。

八、注意事項

1、W25Q80的內存大小是1M,也就是0x100000,所以讀、寫、擦除的范圍就是0~0x100000。

2、在寫入之前,需要先擦除,否則會寫入不成功。

3、本文驅動會與《香瓜CC2640R2F之LCD》沖突,因為都是使用SPI。如果只是想檢測flash是否良好,可以在oled啟動之前,測試一下flash再關閉。思路如下

//flash測試代碼

//……

//oled初始化代碼

//……

//GUA

//oled顯示flash的好壞

if(GUA_flash_Ret == true)

{

??????? GUA_LCD_WriteString(“flash OK”, GUA_LCD_LINE7);

}

else

{

??????? GUA_LCD_WriteString(“flash error”, GUA_LCD_LINE7);

}

//GUA

九、實驗結果

仿真并設置斷點,查看讀出的flash數據

可見讀出的是“opengua”,與寫入的數據一樣,表示讀寫正常。

因此,實驗成功。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/66347.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/66347.shtml
英文地址,請注明出處:http://en.pswp.cn/web/66347.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

光譜相機如何還原色彩

多光譜通道采集 光譜相機設有多個不同波段的光譜通道&#xff0c;可精確記錄每個波長的光強信息。如 8 到 16 個甚至更多的光譜通道&#xff0c;每個通道負責特定波長范圍的光信息記錄。這使得相機能分辨出不同光譜組合產生的相同顏色感知&#xff0c;而傳統相機的傳感器通常只…

C# 獲取PDF文檔中的字體信息(字體名、大小、顏色、樣式等

在設計和出版行業中&#xff0c;字體的選擇和使用對最終作品的質量有著重要影響。然而&#xff0c;有時我們可能會遇到包含未知字體的PDF文件&#xff0c;這使得我們無法準確地復制或修改文檔。獲取PDF中的字體信息可以解決這個問題&#xff0c;讓我們能夠更好地處理這些文件。…

C++ 的 CTAD 與推斷指示(Deduction Guides)

1 類模板參數推導&#xff08;CTAD&#xff09; 1.1 曲線救國 ? CTAD 的全稱是類模板參數推導&#xff08;Class Template Argument Deduction&#xff09;&#xff0c;它允許在實例化類模板時&#xff0c;根據構造函數的參數類型自動推導模板參數&#xff0c;從而避免顯式指…

Shell正則表達式與文本處理三劍客(grep、sed、awk)

一、正則表達式 Shell正則表達式分為兩種&#xff1a; 基礎正則表達式&#xff1a;BRE&#xff08;basic regular express&#xff09; 擴展正則表達式&#xff1a;ERE&#xff08;extend regular express&#xff09;&#xff0c;擴展的表達式有、?、|和() 1.1 基本正則表…

掌握 React 高階組件與高階函數:構建可復用組件的新境界

一、引言 在 React 開發中&#xff0c;代碼復用性和邏輯分離是提高開發效率和維護性的重要手段。高階組件&#xff08;Higher-Order Component, HOC&#xff09;和高階函數&#xff08;Higher-Order Function, HOF&#xff09;是實現這一目標的兩種強大工具。本文將詳細介紹這…

arcgis提取不規則柵格數據的矢量邊界

效果 1、準備數據 柵格數據:dem或者dsm 2、柵格重分類 分成兩類即可 3、新建線面圖層 在目錄下選擇預先準備好的文件夾,點擊右鍵,選擇“新建”→“Shapefile”,新建一個Shapefile文件。 在彈出的“新建Shapefile”對話框內“名稱”命名為“折線”,“要素類型”選…

阿里云通義實驗室自然語言處理方向負責人黃非:通義靈碼2.0,邁入 Agentic AI

通義靈碼是基于阿里巴巴通義大模型研發的AI 智能編碼助手&#xff0c;在通義靈碼 1.0 時代&#xff0c;我們針對代碼的生成、補全和問答&#xff0c;通過高效果、低時延&#xff0c;研發出了國內最受歡迎的編碼助手。 在通義靈碼 2.0 發布會上&#xff0c;阿里云通義實驗室自然…

Open3D 最小二乘擬合平面(直接求解法)【2025最新版】

目錄 一、算法原理二、代碼實現三、結果展示本文由CSDN點云俠原創,原文鏈接。如果你不是在點云俠的博客中看到該文章,那么此處便是不要臉的爬蟲與GPT。 博客長期更新,本文最近更新時間為:2025年1月18日。 一、算法原理 平面方程的一般表達式為:

超標量處理器設計2-cache

1. cache 介紹 影響Cache缺失的情況有3種&#xff1a; Compulsory: 第一次被訪問的指令或者數據肯定不會在cache中&#xff0c;需要通過預取來減少這種缺失Capcity: Cache容量越大&#xff0c;缺失就可以更少, 程序頻繁使用的三個數據來源于3個set&#xff0c; 但是&#xff…

linux 安裝PrometheusAlert配置釘釘告警

在 Linux 上安裝 PrometheusAlert 并配置釘釘告警的步驟如下: 1. 準備工作 釘釘機器人: 在釘釘群中創建一個機器人,獲取 Webhook URL。示例 Webhook URL:https://oapi.dingtalk.com/robot/send?access_token=your_dingtalk_token。PrometheusAlert 安裝包: 從 Prometheus…

當PHP遇上區塊鏈:一場奇妙的技術之旅

PHP 與區塊鏈的邂逅 在技術的廣袤宇宙中&#xff0c;區塊鏈技術如同一顆耀眼的新星&#xff0c;以其去中心化、不可篡改、透明等特性&#xff0c;掀起了一場席卷全球的變革浪潮。眾多開發者懷揣著對新技術的熱忱與探索精神&#xff0c;紛紛投身于區塊鏈開發的領域&#xff0c;試…

vscode的安裝與使用

下載 地址&#xff1a;https://code.visualstudio.com/ 安裝 修改安裝路徑&#xff08;不要有中文&#xff09; 點擊下一步&#xff0c;創建桌面快捷方式&#xff0c;等待安裝 安裝中文插件 可以根據自己的需要安裝python和Jupyter插件

32單片機綜合應用案例——物聯網(IoT)環境監測站(四)(內附詳細代碼講解!!!)

無論你身處何種困境&#xff0c;都要堅持下去&#xff0c;因為勇氣和毅力是成功的基石。不要害怕失敗&#xff0c;因為失敗并不代表終結&#xff0c;而是為了成長和進步。相信自己的能力&#xff0c;相信自己的潛力&#xff0c;相信自己可以克服一切困難。成功需要付出努力和堅…

淺談云計算19 | OpenStack管理模塊 (上)

OpenStack管理模塊&#xff08;上&#xff09; 一、操作界面管理架構二、認證管理2.1 定義與作用2.2 認證原理與流程2.2.1 認證機制原理2.2.2 用戶認證流程 三、鏡像管理3.1 定義與功能3.2 鏡像服務架構3.3 工作原理與流程3.3.1 鏡像存儲原理3.3.2 鏡像檢索流程 四、計算管理4.…

RK3568 Android11 鎖屏界面屏蔽下拉狀態欄

參考文章&#xff1a; Android R鎖屏界面屏蔽下拉狀態欄_pulseexpansionhandler-CSDN博客 前提增加狀態欄控制顯隱屬性&#xff0c;以下面文章為前提補充功能 RK3568 Android11 狀態欄和導航欄增加顯示控制功能-CSDN博客 修改文件位置&#xff1a; frameworks/base/package…

彩色圖像面積計算一般方法及MATLAB實現

一、引言 在數字圖像處理中&#xff0c;經常需要獲取感興趣區域的面積屬性&#xff0c;下面給出圖像處理的一般步驟。 1.讀入的彩色圖像 2.將彩色圖像轉化為灰度圖像 3.灰度圖像轉化為二值圖像 4.區域標記 5.對每個區域的面積進行計算和顯示 二、程序代碼 %面積計算 cle…

分布式理解

分布式 如何理解分布式 狹義的分布是指&#xff0c;指多臺PC在地理位置上分布在不同的地方。 分布式系統 分布式系**統&#xff1a;**多個能獨立運行的計算機&#xff08;稱為結點&#xff09;組成。各個結點利用計算機網絡進行信息傳遞&#xff0c;從而實現共同的“目標或者任…

深入了解卷積神經網絡(CNN):圖像處理與深度學習的革命性技術

深入了解卷積神經網絡&#xff08;CNN&#xff09;&#xff1a;圖像處理與深度學習的革命性技術 導語 卷積神經網絡&#xff08;CNN&#xff09;是現代深度學習領域中最重要的模型之一&#xff0c;特別在計算機視覺&#xff08;CV&#xff09;領域具有革命性的影響。無論是圖…

QT:IconButton的動畫效果

要實現IconButton&#xff0c;需要處理背景。參考&#xff1a; QT之IconWidget-CSDN博客 隨后就是Button的按下動畫效果。實現也簡單。思路就是記錄按下狀態&#xff0c;然后在繪制時偏移一個像素&#xff08;也可以繪制另外一個圖&#xff09;。 增加一個字段&#xff0c;記…

Android渲染Latex公式的開源框架比較

對比主流框架&#xff0c;介紹如下幾款 1、AndroidMath 官網&#xff1a;https://github.com/gregcockroft/AndroidMath/tree/master 基于android原生view方式渲染 優點&#xff1a;速度快&#xff0c;開源協議 MIT license 缺點&#xff1a;不支持文字公式混合渲染 2、Ma…