单片机与 8 脚 Flash 的通信通常基于 SPI(Serial Peripheral Interface)协议,下面为你详细介绍通信过程及实现方法。
单片机与 8 脚 Flash 的典型硬件连接方式如下:
| 单片机引脚 | Flash 引脚 |
|---|---|
| SCK(时钟输出) | CLK(时钟输入) |
| MOSI(主出从入) | DI(数据输入) |
| MISO(主入从出) | DO(数据输出) |
| 片选输出 | CS#(低电平有效) |
| 通用输出 | HOLD#(低电平有效) |
| VCC | VCC(接电源) |
| GND | VSS(接地) |
SPI 通信的关键要点如下:
与 Flash 通信的基本流程为:
Flash 芯片支持多种指令,下面列举一些常用指令及其功能:
| 指令代码(十六进制) | 指令名称 | 功能描述 |
|---|---|---|
| 03H | 读数据 | 从指定地址连续读取数据。 |
| 0BH | 快速读 | 比普通读数据指令速度更快,在地址后需发送一个空字节。 |
| 06H | 写使能 | 使能芯片的写操作,在执行写数据或擦除操作前必须先执行此指令。 |
| 04H | 写禁止 | 禁止芯片的写操作。 |
| 05H | 读状态寄存器 | 读取状态寄存器内容,可获取芯片是否忙碌、写保护状态等信息。 |
| 0AH | 写状态寄存器 | 向状态寄存器写入数据,可设置写保护、块锁定等功能。 |
| 20H | 扇区擦除 | 擦除指定地址所在的扇区(通常为 4KB),擦除后扇区数据全部变为 FFH。 |
| D8H | 块擦除 | 擦除指定地址所在的块(通常为 64KB),擦除后块内数据全部变为 FFH。 |
| C7H | 芯片擦除 | 擦除整个 Flash 芯片的数据,所有存储单元数据变为 FFH。 |
| 02H | 页编程 | 向指定地址写入数据,每次最多可写入 256 字节(一页)。 |
下面以 Arduino 为例,展示 SPI 通信的代码实现:
#define CS_PIN 10 // 片选引脚#define HOLD_PIN 9 // HOLD引脚void setup() {
// 初始化SPI接口
SPI.begin();
// 设置引脚模式
pinMode(CS_PIN, OUTPUT);
pinMode(HOLD_PIN, OUTPUT);
// 初始状态:CS和HOLD为高电平
digitalWrite(CS_PIN, HIGH);
digitalWrite(HOLD_PIN, HIGH);
Serial.begin(115200);
Serial.println("Flash初始化完成");}// 读取Flash状态寄存器byte readStatusRegister() {
digitalWrite(CS_PIN, LOW); // 选中Flash
SPI.transfer(0x05); // 发送读状态寄存器指令
byte status = SPI.transfer(0x00); // 读取状态寄存器值
digitalWrite(CS_PIN, HIGH); // 取消选中Flash
return status;}// 等待Flash空闲void waitForFlashReady() {
while ((readStatusRegister() & 0x01) == 0x01); // 等待忙碌位(BUSY)清零}// 使能写操作void writeEnable() {
digitalWrite(CS_PIN, LOW); // 选中Flash
SPI.transfer(0x06); // 发送写使能指令
digitalWrite(CS_PIN, HIGH); // 取消选中Flash}// 读取Flash数据void readData(uint32_t address, byte* buffer, uint16_t length) {
waitForFlashReady();
digitalWrite(CS_PIN, LOW); // 选中Flash
SPI.transfer(0x03); // 发送读数据指令
SPI.transfer((address >> 16) & 0xFF); // 发送地址高字节
SPI.transfer((address >> 8) & 0xFF); // 发送地址中字节
SPI.transfer(address & 0xFF); // 发送地址低字节
// 读取数据
for (uint16_t i = 0; i < length; i++) {
buffer[i] = SPI.transfer(0x00);
}
digitalWrite(CS_PIN, HIGH); // 取消选中Flash}// 页编程(写入数据)void pageProgram(uint32_t address, byte* data, uint16_t length) {
if (length > 256) length = 256; // 一页最多256字节
waitForFlashReady();
writeEnable(); // 使能写操作
digitalWrite(CS_PIN, LOW); // 选中Flash
SPI.transfer(0x02); // 发送页编程指令
SPI.transfer((address >> 16) & 0xFF); // 发送地址高字节
SPI.transfer((address >> 8) & 0xFF); // 发送地址中字节
SPI.transfer(address & 0xFF); // 发送地址低字节
// 写入数据
for (uint16_t i = 0; i < length; i++) {
SPI.transfer(data[i]);
}
digitalWrite(CS_PIN, HIGH); // 取消选中Flash
waitForFlashReady(); // 等待写入完成}// 扇区擦除void sectorErase(uint32_t address) {
waitForFlashReady();
writeEnable(); // 使能写操作
digitalWrite(CS_PIN, LOW); // 选中Flash
SPI.transfer(0x20); // 发送扇区擦除指令
SPI.transfer((address >> 16) & 0xFF); // 发送地址高字节
SPI.transfer((address >> 8) & 0xFF); // 发送地址中字节
SPI.transfer(address & 0xFF); // 发送地址低字节
digitalWrite(CS_PIN, HIGH); // 取消选中Flash
waitForFlashReady(); // 等待擦除完成(耗时较长)}void loop() {
// 示例:读取Flash ID
byte id[3];
digitalWrite(CS_PIN, LOW);
SPI.transfer(0x9F); // 发送读取设备ID指令
id[0] = SPI.transfer(0x00); // 制造商ID
id[1] = SPI.transfer(0x00); // 设备ID1
id[2] = SPI.transfer(0x00); // 设备ID2
digitalWrite(CS_PIN, HIGH);
Serial.print("Flash ID: 0x");
for (int i = 0; i < 3; i++) {
if (id[i] < 0x10) Serial.print("0");
Serial.print(id[i], HEX);
}
Serial.println();
// 示例:写入数据
byte writeData[] = "Hello, Flash!";
pageProgram(0x0000, writeData, sizeof(writeData));
// 示例:读取数据
byte readBuffer[32];
readData(0x0000, readBuffer, sizeof(writeData));
Serial.print("读取的数据: ");
Serial.println((char*)readBuffer);
delay(5000); // 每5秒执行一次}上一篇:8脚flash引脚定义
电话:176-6539-0767
Q Q:135-0379-986
邮箱:1350379986@qq.com
地址:深圳市南山区后海大道1021号C座