1)實(shí)驗(yàn)平臺(tái):正點(diǎn)原子APM32E103最小系統(tǒng)板
2)平臺(tái)購買地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套實(shí)驗(yàn)源碼+手冊(cè)+視頻下載地址: http://www.openedv.com/docs/boards/xiaoxitongban
第四十一章 SPI實(shí)驗(yàn)
本章將介紹使用APM32E103驅(qū)動(dòng)板載的NOR Flash進(jìn)行讀寫操作。通過本章的學(xué)習(xí),讀者將學(xué)習(xí)到使用SPI驅(qū)動(dòng)NOR Flash的使用。
本章分為如下幾個(gè)小節(jié):
41.1 硬件設(shè)計(jì)
41.2 程序設(shè)計(jì)
41.3 下載驗(yàn)證
41.1 硬件設(shè)計(jì)
41.1.1 例程功能
- 按下KEY_UP和KEY0按鍵,分別對(duì)25Q128進(jìn)行數(shù)據(jù)的寫入和讀取操作,讀取到的數(shù)據(jù)會(huì)顯示至LCD
- 可通過USMART對(duì)25Q128進(jìn)行讀ID和芯片/扇區(qū)擦除的操作
- LED0閃爍,指示程序正在運(yùn)行
41.1.2 硬件資源 - LED
LED0 - PB5 - 按鍵
KEY0 - PE4
KEY_UP - PA0 - USART1(PA9、PA10連接至板載USB轉(zhuǎn)串口芯片上)
- 正點(diǎn)原子 2.8/3.5/4.3/7/10寸TFTLCD模塊(僅限MCU屏,16位8080并口驅(qū)動(dòng))
- SPI2
SPI2_SCK - PB13
SPI2_MISO - PB14
SPI2_MOSI - PB15 - 25Q128
F_CS - PB12
41.1.3 原理圖
本章實(shí)驗(yàn)使用了板載的25Q128芯片,該芯片是一個(gè)NOR Flash,MCU是通過SPI與該NOR Flash進(jìn)行連接與通信的,該NOR Flash與MCU的連接原理圖,如下如圖所示:
圖41.1.3.1 NOR Flash與MCU的連接原理圖
41.2 程序設(shè)計(jì)
41.2.1 Geehy標(biāo)準(zhǔn)庫的SPI驅(qū)動(dòng)
本章實(shí)驗(yàn)通過SPI2驅(qū)動(dòng)NOR Flash,因此需要對(duì)SPI2進(jìn)行相應(yīng)的配置,并使用SPI2與NOR Flash進(jìn)行通信,其具體的步驟如下所示:
①:配置SPI2
②:使能SPI2
③:使用SPI2發(fā)送數(shù)據(jù)(接收數(shù)據(jù))前,等待SPI2發(fā)送緩沖區(qū)為空(接收緩沖區(qū)非空)
④:使用SPI2發(fā)送一字節(jié)數(shù)據(jù)
⑤:使用SPI2接收一字節(jié)數(shù)據(jù)
在Geehy標(biāo)準(zhǔn)庫中對(duì)應(yīng)的驅(qū)動(dòng)函數(shù)如下:
①:配置SPI
該函數(shù)用于配置SPI,其函數(shù)原型如下所示:
void SPI_Config(SPI_T* spi, SPI_Config_T* spiConfig);
該函數(shù)的形參描述,如下表所示:
形參 描述
spi 指向SPI外設(shè)結(jié)構(gòu)體的指針
例如:SPI1、SPI2等(在apm32e10x.h文件中有定義)
spiConfig 指向SPI配置結(jié)構(gòu)體的指針
需自行定義,并根據(jù)SPI的配置參數(shù)填充結(jié)構(gòu)體中的成員變量
表41.2.1.1 函數(shù)SPI_Config()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無 無
表41.2.1.2 函數(shù)SPI_Config()返回值描述
該函數(shù)使用SPI_Config_T類型的結(jié)構(gòu)體變量傳入SPI的配置參數(shù),該結(jié)構(gòu)體的定義如下所示:
typedef enum
{
SPI_MODE_MASTER = 0x0104, /* 主機(jī)模式 */
SPI_MODE_SLAVE = 0x0000 /* 從機(jī)模式 */
}SPI_MODE_T;
typedef enum
{
SPI_DATA_LENGTH_16B = 0x0800, /* 8位數(shù)據(jù)格式 */
SPI_DATA_LENGTH_8B = 0x0000 /* 8位數(shù)據(jù)格式 */
}SPI_DATA_LENGTH_T;
typedef enum
{
SPI_CLKPHA_1EDGE = 0x0000, /* 在第一個(gè)時(shí)鐘邊沿進(jìn)行采樣 */
SPI_CLKPHA_2EDGE = 0x0001 /* 在第二個(gè)時(shí)鐘邊沿進(jìn)行采樣 */
}SPI_CLKPHA_T;
typedef enum
{
SPI_CLKPOL_LOW = 0x0000, /* 時(shí)鐘信號(hào)空閑時(shí)為低電平 */
SPI_CLKPOL_HIGH = 0x0002 /* 時(shí)鐘信號(hào)空閑時(shí)為高電平 */
}SPI_CLKPOL_T;
typedef enum
{
SPI_NSS_SOFT = 0x0200, /* 軟件片選 */
SPI_NSS_HARD = 0x0000 /* 硬件片選 */
}SPI_NSS_T;
typedef enum
{
SPI_FIRSTBIT_MSB = 0x0000, /* MSB */
SPI_FIRSTBIT_LSB = 0x0080 /* LSB */
}SPI_FIRSTBIT_T;
typedef enum
{
SPI_DIRECTION_2LINES_FULLDUPLEX = 0x0000, /* 雙線全雙工 */
SPI_DIRECTION_2LINES_RXONLY = 0x0400, /* 雙線僅接收 */
SPI_DIRECTION_1LINE_RX = 0x8000, /* 單線僅接受 */
SPI_DIRECTION_1LINE_TX = 0xC000 /* 單線僅發(fā)送 */
}SPI_DIRECTION_T;
typedef enum
{
SPI_BAUDRATE_DIV_2 = 0x0000, /*波特率2分頻 */
SPI_BAUDRATE_DIV_4 = 0x0008, /*波特率4分頻 */
SPI_BAUDRATE_DIV_8 = 0x0010, /*波特率8分頻 */
SPI_BAUDRATE_DIV_16 = 0x0018, /*波特率16分頻 */
SPI_BAUDRATE_DIV_32 = 0x0020, /*波特率32分頻 */
SPI_BAUDRATE_DIV_64 = 0x0028, /*波特率64分頻 */
SPI_BAUDRATE_DIV_128 = 0x0030, /*波特率128分頻 */
SPI_BAUDRATE_DIV_256 = 0x0038, /*波特率256分頻 */
}SPI_BAUDRATE_DIV_T;
typedef struct
{
SPI_MODE_T mode; /* 模式 */
SPI_DATA_LENGTH_T length; /* 數(shù)據(jù)位長(zhǎng)度 */
SPI_CLKPHA_T phase; /* 采樣階段 */
SPI_CLKPOL_T polarity; /* 時(shí)鐘線空閑極性 */
SPI_NSS_T nss; /* 片選信號(hào) */
SPI_FIRSTBIT_T firstBit; /* 數(shù)據(jù)第一比特 */
SPI_DIRECTION_T direction; /* 方向 */
SPI_BAUDRATE_DIV_T baudrateDiv; /* 波特率分頻 */
uint16_t crcPolynomial; /* CRC校驗(yàn)值 */
} SPI_Config_T;
該函數(shù)的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_spi.h"
void example_fun(void)
{
SPI_Config_T spi_init_struct;
/* 配置SPI1 */
spi_init_struct.mode = SPI_MODE_MASTER;
spi_init_struct.length = SPI_DATA_LENGTH_8B;
spi_init_struct.phase = SPI_CLKPHA_2EDGE;
spi_init_struct.polarity = SPI_CLKPOL_HIGH;
spi_init_struct.nss = SPI_NSS_SOFT;
spi_init_struct.firstBit = SPI_FIRSTBIT_MSB;
spi_init_struct.direction = SPI_DIRECTION_2LINES_FULLDUPLEX;
spi_init_struct.baudrateDiv = SPI_BAUDRATE_DIV_256;
spi_init_struct.crcPolynomial = 7;
SPI_Config(SPI1_SPI, &spi_init_struct);
}
②:使能SPI
該函數(shù)用于使能SPI,其函數(shù)原型如下所示:
void SPI_Enable(SPI_T* spi);
該函數(shù)的形參描述,如下表所示:
形參 描述
spi 指向SPI外設(shè)結(jié)構(gòu)體的指針
例如:SPI1、SPI2等(在apm32e10x.h文件中有定義)
表41.2.1.3 函數(shù)SPI_Enable()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無 無
表41.2.1.4 函數(shù)SPI_Enable()返回值描述
該函數(shù)的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_spi.h"
void example_fun(void)
{
/* 使能SPI2 */
SPI_Enable(SPI2);
}
③:讀取SPI的狀態(tài)標(biāo)志
該函數(shù)用于讀取SPI的狀態(tài)標(biāo)志,其函數(shù)原型如下所示:
uint8_t SPI_I2S_ReadStatusFlag(SPI_T* spi, SPI_FLAG_T flag);
該函數(shù)的形參描述,如下表所示:
形參 描述
spi 指向SPI外設(shè)結(jié)構(gòu)體的指針
例如:SPI1、SPI2等(在apm32e10x.h文件中有定義)
flag 指定的SPI狀態(tài)標(biāo)志
例如:SPI_FLAG_RXBNE、SPI_FLAG_TXBE等(在apm32e10x_spi.h文件中有定義)
表41.2.1.5 函數(shù)SPI_I2S_ReadStatusFlag()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
SET 事件標(biāo)志發(fā)生
RESET 事件標(biāo)志未發(fā)生
表41.2.1.6 函數(shù)SPI_I2S_ReadStatusFlag()返回值描述
該函數(shù)的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_spi.h"
void example_fun(void)
{
uint8_t flag;
/* 讀取SPI2的接收緩沖區(qū)非空標(biāo)志 */
flag = SPI_I2S_ReadStatusFlag(SPI2, SPI_FLAG_RXBNE);
if (flag == SET)
{
/* Do something. */
}
else
{
/* Do something. */
}
}
④:SPI發(fā)送數(shù)據(jù)
該函數(shù)用于使用SPI發(fā)送數(shù)據(jù),其函數(shù)原型如下所示:
void SPI_I2S_TxData(SPI_T* spi, uint16_t data);
該函數(shù)的形參描述,如下表所示:
形參 描述
spi 指向SPI外設(shè)結(jié)構(gòu)體的指針
例如:SPI1、SPI2等(在apm32e10x.h文件中有定義)
data 待發(fā)送的數(shù)據(jù)
表41.2.1.7 函數(shù)SPI_I2S_TxData()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無 無
表41.2.1.8 函數(shù)SPI_I2S_TxData()返回值描述
該函數(shù)的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_spi.h"
void example_fun(void)
{
uint8_t data;
data = 0x55;
/* 使用SPI2發(fā)送1字節(jié)數(shù)據(jù) */
SPI_I2S_TxData(SPI2, (uint16_t)data);
}
⑤:SPI接收數(shù)據(jù)
該函數(shù)用于接收SPI接收的數(shù)據(jù),其函數(shù)原型如下所示:
uint16_t SPI_I2S_RxData(SPI_T* spi);
該函數(shù)的形參描述,如下表所示:
形參 描述
spi 指向SPI外設(shè)結(jié)構(gòu)體的指針
例如:SPI1、SPI2等(在apm32e10x.h文件中有定義)
表41.2.1.9 函數(shù)SPI_I2S_RxData()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
uint16_t類型數(shù)據(jù) SPI接收的數(shù)據(jù)
表41.2.1.10 函數(shù)SPI_I2S_TxData()返回值描述
該函數(shù)的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_spi.h"
void example_fun(void)
{
uint8_t data;
/* 接收SPI2接收到的1字節(jié)數(shù)據(jù) */
data = (uint8_t)SPI_I2S_RxData(SPI2);
/* Do something. */
}
41.2.2 SPI驅(qū)動(dòng)
本章實(shí)驗(yàn)的SPI驅(qū)動(dòng)主要負(fù)責(zé)向NOR Flash驅(qū)動(dòng)提供SPI的各種操作函數(shù),例如:SPI初始化、SPI讀寫等。本章實(shí)驗(yàn)中,SPI的驅(qū)動(dòng)代碼包括spi.c和spi.h兩個(gè)文件。
SPI驅(qū)動(dòng)中,對(duì)SPI、GPIO相關(guān)的宏定義,如下所示:
/* SPI2相關(guān)定義 */
#define SPI2_SPI SPI2
#define SPI2_SPI_CLK_ENABLE() do{ RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI2); }while(0)
/* SPI2引腳定義 */
#define SPI2_SCK_GPIO_PORT GPIOB
#define SPI2_SCK_GPIO_PIN GPIO_PIN_13
#define SPI2_SCK_GPIO_CLK_ENABLE() do{ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB); }while(0)
#define SPI2_MISO_GPIO_PORT GPIOB
#define SPI2_MISO_GPIO_PIN GPIO_PIN_14
#define SPI2_MISO_GPIO_CLK_ENABLE() do{ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB); }while(0)
#define SPI2_MOSI_GPIO_PORT GPIOB
#define SPI2_MOSI_GPIO_PIN GPIO_PIN_15
#define SPI2_MOSI_GPIO_CLK_ENABLE() do{ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB); }while(0)
SPI驅(qū)動(dòng)中,SPI的初始化函數(shù),如下所示:
/**
* @brief 初始化SPI2
* @param 無
* @retval 無
*/
void spi2_init(void)
{
GPIO_Config_T gpio_init_struct;
SPI_Config_T spi_init_struct;
/* 使能時(shí)鐘 */
SPI2_SPI_CLK_ENABLE(); /* 使能SPI2時(shí)鐘 */
SPI2_SCK_GPIO_CLK_ENABLE(); /* 使能SPI2 SCK引腳端口時(shí)鐘 */
SPI2_MISO_GPIO_CLK_ENABLE(); /* 使能SPI2 MISO引腳端口時(shí)鐘 */
SPI2_MOSI_GPIO_CLK_ENABLE(); /* 使能SPI2 MOSI引腳端口時(shí)鐘 */
/* 配置SPI2 SCK引腳 */
gpio_init_struct.pin = SPI2_SCK_GPIO_PIN; /* SPI2 SCK引腳 */
gpio_init_struct.speed = GPIO_SPEED_50MHz; /* 高速 */
gpio_init_struct.mode = GPIO_MODE_AF_PP; /* 復(fù)用功能推挽輸出模式 */
GPIO_Config(SPI2_SCK_GPIO_PORT, &gpio_init_struct);
/* 配置SPI2 MISO引腳 */
gpio_init_struct.pin = SPI2_MISO_GPIO_PIN; /* SPI2 MISO引腳 */
gpio_init_struct.speed = GPIO_SPEED_50MHz; /* 高速 */
gpio_init_struct.mode = GPIO_MODE_AF_PP; /* 復(fù)用功能推挽輸出模式 */
GPIO_Config(SPI2_MISO_GPIO_PORT, &gpio_init_struct);
/* 配置SPI2 MOSI引腳 */
gpio_init_struct.pin = SPI2_MOSI_GPIO_PIN; /* SPI2 MOSI引腳 */
gpio_init_struct.speed = GPIO_SPEED_50MHz; /* 高速 */
gpio_init_struct.mode = GPIO_MODE_AF_PP; /* 復(fù)用功能推挽輸出模式 */
GPIO_Config(SPI2_MOSI_GPIO_PORT, &gpio_init_struct);
/* 配置SPI2 */
spi_init_struct.mode = SPI_MODE_MASTER; /* 主模式 */
spi_init_struct.length = SPI_DATA_LENGTH_8B; /* 8位數(shù)據(jù)幀格式 */
spi_init_struct.phase = SPI_CLKPHA_2EDGE; /* 在第2個(gè)時(shí)鐘邊沿采樣 */
/* SPI處于空閑狀態(tài)時(shí),SCK保持高電平狀態(tài) */
spi_init_struct.polarity = SPI_CLKPOL_HIGH;
spi_init_struct.nss = SPI_NSS_SOFT; /* 啟用軟件NSS模式 */
spi_init_struct.firstBit = SPI_FIRSTBIT_MSB; /* 先發(fā)送最高有效位(MSB) */
/* 雙線單向、同時(shí)發(fā)送和接收 */
spi_init_struct.direction = SPI_DIRECTION_2LINES_FULLDUPLEX;
/* 波特率分頻系數(shù) */
spi_init_struct.baudrateDiv = SPI_BAUDRATE_DIV_256;
spi_init_struct.crcPolynomial = 7; /* CRC多項(xiàng)式數(shù)值 */
SPI_Config(SPI2_SPI, &spi_init_struct); /* 配置SPI2 */
SPI_DisableCRC(SPI2_SPI); /* 禁止CRC */
SPI_Enable(SPI2_SPI); /* 使能SPI2 */
}
可以看到,該函數(shù)會(huì)配置并使能SPI1,同時(shí)也配置SPI使用的GPIO引腳的復(fù)用功能。
SPI驅(qū)動(dòng)中,使用SPI傳輸1字節(jié)數(shù)據(jù)的函數(shù),如下所示:
/**
* @brief SPI2讀寫一個(gè)字節(jié)數(shù)據(jù)
* @param txdata: 待發(fā)送的一字節(jié)數(shù)據(jù)
* @retval 接收到的一字節(jié)數(shù)據(jù)
*/
uint8_t spi2_read_write_byte(uint8_t txdata)
{
uint8_t rxdata;
/* 等待發(fā)送緩沖器為空 */
while (SPI_I2S_ReadStatusFlag(SPI2_SPI, SPI_FLAG_TXBE) != SET);
/* 發(fā)送一字節(jié)數(shù)據(jù) */
SPI_I2S_TxData(SPI2_SPI, txdata);
/* 等待接收緩沖非空 */
while (SPI_I2S_ReadStatusFlag(SPI2_SPI, SPI_FLAG_RXBNE) != SET);
/* 接收一字節(jié)數(shù)據(jù) */
rxdata = SPI_I2S_RxData(SPI2_SPI);
return rxdata;
}
使用SPI傳輸1字節(jié)數(shù)據(jù)就是先后發(fā)送并接收1字節(jié)數(shù)據(jù)。
41.2.3 NOR Flash驅(qū)動(dòng)
本章實(shí)驗(yàn)的NOR Flash驅(qū)動(dòng)主要負(fù)責(zé)向應(yīng)用層提供NOR Flash的初始化和讀寫操作等函數(shù)。本章實(shí)驗(yàn)中,NOR Flash的驅(qū)動(dòng)代碼包括norflash.c和norflash.h兩個(gè)文件。
NOR Flash驅(qū)動(dòng)中,對(duì)GPIO的相關(guān)宏定義,如下所示:
/* NOR Flash片選引腳定義 */
#define NORFLASH_CS_GPIO_PORT GPIOB
#define NORFLASH_CS_GPIO_PIN GPIO_PIN_12
#define NORFLASH_CS_GPIO_CLK_ENABLE() do{ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB); }while(0)
/* NOR Flash片選引腳IO操作 */
#define NORFLASH_CS(x) do{ x ? \
GPIO_SetBit(NORFLASH_CS_GPIO_PORT, NORFLASH_CS_GPIO_PIN) : \
GPIO_ResetBit(NORFLASH_CS_GPIO_PORT, NORFLASH_CS_GPIO_PIN); \
}while(0)
NOR Flash驅(qū)動(dòng)中,初始化NOR Flash的函數(shù),如下所示:
/**
* @brief 初始化NOR Flash
* @param 無
* @retval 無
*/
void norflash_init(void)
{
GPIO_Config_T gpio_init_struct;
uint8_t temp;
/* 使能NOR Flash片選引腳端口時(shí)鐘 */
NORFLASH_CS_GPIO_CLK_ENABLE();
/* NOR Flash片選引腳 */
gpio_init_struct.pin = NORFLASH_CS_GPIO_PIN;
gpio_init_struct.speed = GPIO_SPEED_50MHz; /* 高速 */
gpio_init_struct.mode = GPIO_MODE_OUT_PP; /* 推挽輸出模式 */
GPIO_Config(NORFLASH_CS_GPIO_PORT, &gpio_init_struct);
NORFLASH_CS(1); /* 失能NOR Flash片選 */
/* 配置SPI2接口 */
spi2_init(); /* 初始化SPI2 */
/* 設(shè)置SPI2速度,60MHz/2=30MHz */
spi2_set_speed(SPI_SPEED_2);
/* 讀取NOR Flash芯片ID */
g_norflash_type = norflash_read_id();
/* W25Q256需使能4字節(jié)地址模式 */
if (g_norflash_type == W25Q256)
{
/* 讀狀態(tài)寄存器3,判斷地址模式 */
temp = norflash_read_sr(3);
/* 如果不是4字節(jié)地址模式,則需進(jìn)行相應(yīng)配置 */
if ((temp & 0x01) == 0)
{
norflash_write_enable(); /* NOR Flash寫使能 */
/* ADP=1,配置上電4字節(jié)地址模式 */
temp |= (1 << 1);
norflash_write_sr(3, temp); /* 寫狀態(tài)寄存器3 */
NORFLASH_CS(0); /* 使能NOR Flash片選 */
/* 使能4字節(jié)地址模式 */
spi2_read_write_byte(NORFLASH_Enable4ByteAddr);
NORFLASH_CS(1); /* 失能NOR Flash片選 */
}
}
}
可以看到,在NOR Flash的初始化函數(shù)中,先初始化了控制NOR Flash片選的GPIO引腳,然后再是初始化與NOR Flash通訊的SPI并配置其通訊波特率,最后還會(huì)根據(jù)不同容量的NOR Flash做相應(yīng)的配置操作。
NOR Flash驅(qū)動(dòng)中其他對(duì)NOR Flash的操作函數(shù),例如,NOR Flash的讀寫函數(shù)、擦除函數(shù)等,請(qǐng)讀者結(jié)合25Q128 NOR Flash芯片的數(shù)據(jù)手冊(cè)查看本實(shí)驗(yàn)的配套實(shí)驗(yàn)源碼。
41.2.4 實(shí)驗(yàn)應(yīng)用代碼
本章實(shí)驗(yàn)的應(yīng)用代碼,如下所示:文章來源:http://www.zghlxwxcb.cn/news/detail-806254.html
/* 待寫入NOR Flash的數(shù)據(jù) */
static const uint8_t g_text_buf[] = {"APM32 SPI TEST"};
/* 待寫入NOR Flash數(shù)據(jù)的長(zhǎng)度 */
#define TEXT_SIZE sizeof(g_text_buf)
int main(void)
{
uint16_t id;
uint8_t t = 0;
uint8_t key;
uint8_t data[TEXT_SIZE];
uint32_t flashsize;
NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_4); /* 設(shè)置中斷優(yōu)先級(jí)分組為組4 */
sys_apm32_clock_init(15); /* 配置系統(tǒng)時(shí)鐘 */
delay_init(120); /* 初始化延時(shí)功能 */
usart_init(115200); /* 初始化串口 */
usmart_dev.init(120); /* 初始化USMART */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
norflash_init(); /* 初始化NOR Flash */
lcd_show_string(30, 50, 200, 16, 16, "APM32", RED);
lcd_show_string(30, 70, 200, 16, 16, "SPI TEST", RED);
lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(30, 110, 200, 16, 16, "KEY_UP:Write KEY0:Read", RED);
id = norflash_read_id(); /* 讀NOR Flash芯片ID */
while ((id == 0) || (id == 0xFFFF)) /* 檢測(cè)不到NOR Flash芯片 */
{
lcd_show_string(30, 130, 200, 16, 16, "NOR Flash Check Failed!", RED);
delay_ms(500);
lcd_show_string(30, 130, 200, 16, 16, "Please Check! ", RED);
delay_ms(500);
LED0_TOGGLE();
}
/* NOR Flash檢測(cè)正常 */
lcd_show_string(30, 130, 200, 16, 16, "NOR FLASH Ready!", BLUE);
/* NOR Flash容量為16MB */
flashsize = 16 * 1024 * 1204;
while (1)
{
t++;
key = key_scan(0);
if (key == WKUP_PRES) /* 寫入數(shù)據(jù) */
{
lcd_fill(0, 150, 239, 319, WHITE);
lcd_show_string(30, 150, 200, 16, 16,
"Start Write Flash....", BLUE);
sprintf((char *)data, "%s%d", (char *)g_text_buf, t);
/* 從倒數(shù)第100個(gè)地址處開始寫入TEXT_SIZE個(gè)字節(jié)的數(shù)據(jù) */
norflash_write((uint8_t *)data, flashsize - 100, TEXT_SIZE);
lcd_show_string(30, 150, 200, 16, 16,
"Flash Write Finished!", BLUE);
}
else if (key == KEY0_PRES) /* 讀取數(shù)據(jù) */
{
lcd_show_string(30, 150, 200, 16, 16,
"Start Read FLASH... . ", BLUE);
/* 從倒數(shù)第100個(gè)地址處開始讀出TEXT_SIZE個(gè)字節(jié)的數(shù)據(jù) */
norflash_read(data, flashsize - 100, TEXT_SIZE);
lcd_show_string(30, 150, 200, 16, 16,
"The Data Readed Is: ", BLUE);
lcd_show_string(30, 170, 200, 16, 16, (char *)data, BLUE);
}
if (t == 20)
{
LED0_TOGGLE();
t = 0;
}
delay_ms(10);
}
}
從本章實(shí)驗(yàn)的應(yīng)用代碼中可以看到,在初始化完NOR Flash后,會(huì)檢測(cè)與NOR Flash的連接是否正常,若與NOR Flash的連接正常,則會(huì)不斷地等待按鍵輸入,若檢測(cè)到KEY_UP按鍵被按下,則會(huì)往NOR Flash的指定地址中寫入指定的數(shù)據(jù),若檢測(cè)KEY0按鍵被按下,則會(huì)從NOR Flash的指定地址中讀取數(shù)據(jù),并在LCD上進(jìn)行顯示。
41.3 下載驗(yàn)證
在完成編譯和燒錄操作后,若MCU與NOR Flash的連接無誤,則可以在LCD上看到“NOR Flash Ready!”的提示信息,此時(shí)可以按下KEY_UP按鍵往NOR Flash的指定地址寫入指定的數(shù)據(jù),然后再按下KEY_0按鍵從NOR Flash的指定地址將寫入的數(shù)據(jù)讀回來在LCD上進(jìn)行顯示,此時(shí)便可以看到LCD上顯示“APM32 SPI TESTn”的提示信息,該提示信息就是從NOR Flash中讀回的數(shù)據(jù)。文章來源地址http://www.zghlxwxcb.cn/news/detail-806254.html
到了這里,關(guān)于【正點(diǎn)原子STM32連載】 第四十一章 SPI實(shí)驗(yàn) 摘自【正點(diǎn)原子】APM32E103最小系統(tǒng)板使用指南的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!