八、SPI读写XT25数据
SPI(Serial Peripheral Interface,串行外设接口)是一种同步串行通信协议,广泛用于嵌入式系统中连接微控制器与外围设备,如传感器、存储器、显示屏等。主要特点1. 全双工通信:支持同时发送和接收数据。2. 同步通信:依靠时钟信号(SCLK)同步数据传输。3. 主从架构:一个主设备控制一个或多个从设备。4. 高速传输:速度通常高于I2C和UART。优点:高速传输,全双工通信,
8.1 SPI 简介
SPI(Serial Peripheral Interface,串行外设接口)是一种同步串行通信协议,广泛用于嵌入式系统中连接微控制器与外围设备,如传感器、存储器、显示屏等。
主要特点
1. 全双工通信:支持同时发送和接收数据。
2. 同步通信:依靠时钟信号(SCLK)同步数据传输。
3. 主从架构:一个主设备控制一个或多个从设备。
4. 高速传输:速度通常高于I2C和UART。
优点:高速传输,全双工通信,硬件简单。
缺点:需要更多引脚,无内置错误检测,协议复杂度较高。
全双工,这里就跟I2C区别开了,I2C只有一根数据线,发送数据时不能接收,接收数据时不能发送,所以SPI相较于I2C通信十分迅速,但是,主从身份是无法改变的,硬件(接的线)固定了,一个主机多个从机,主机是这些从机永远的主机。就是接的线相对多一点,I2C就用个SCL,SDA,SPI至少用四根。
信号线
1. SCLK(Serial Clock):主设备提供的时钟信号。
2. MOSI(Master Out Slave In):主设备发送数据,从设备接收。
3. MISO(Master In Slave Out):从设备发送数据,主设备接收。
4. SS/CS(Slave Select/Chip Select):主设备选择从设备。

应用场景
存储器:如Flash、EEPROM。
传感器:如温度、加速度传感器。
显示屏:如OLED、LCD。
通信模块:如Wi-Fi、蓝牙模块。
8.2 SPI 工作原理
1. 初始化:主设备配置时钟频率、数据格式等参数。
2. 选择从设备:主设备拉低(或者拉高,取决于从机)对应从设备的SS线。
3. 数据传输:主设备通过MOSI发送数据,同时通过MISO接收数据。
4. 结束通信:主设备拉高(或拉低)SS线,结束传输。
SPI(Serial Peripheral Interface)、SSI(Synchronous Serial Interface)和Microwire是三种常见的同步串行通信协议,它们在帧格式、通信方式和应用场景上有所不同。

8.3 XT25 简介
XT25F02E 含有2Mb串行FLASH,支持标准串行外围接口(SPI),并支持Dual SPI:串行时钟、芯片选择、串行数据I/O0(SI)、I/O1(SO)。Dual I/O数据以160Mbits/s的速度传输。下图为XT25内部方框图。

XT25F02ESOIGU_XTX(芯天下)_XT25F02ESOIGU中文资料_PDF手册_价格-立创商城
存储大小及地址
命令

相关注意事项如图
(图片来自江协科技)
更多详情请看数据手册
XT25F02ESOIGU_XTX(芯天下)_XT25F02ESOIGU中文资料_PDF手册_价格-立创商城
8.4 寄存器
8.4.1 控制寄存器0 SSP0CR0, SSP1CR0
这里CPOL和CPHA可改变空闲状态和接收时刻,而I2C就是固定的
| 位 | ||
| 3:0 | DSS |
数据长度选择,控制每帧中传输的位的数目,0000~0010无效 0011 ~ 1111分别对应4-16位,相当于DSS的二进制值加一 |
| 5:4 | FRF |
帧格式 00 SPI 01 TI SPI 10 Microwire 11 不适用 |
| 6 | CPOL |
时钟输出极性 只用于SPI模式 0 使帧之间的总线时钟保持低电平 1 使帧之间的总线时钟保持高电平 |
| 7 | CPHA |
时钟输出相位 0 SSP控制器在帧传输第一次跳变(01 or 10)时捕获串行数据, 即跳变远离时钟线的帧间状态 1 SSP控制器在帧传输第二次跳变时捕获串行数据,即跳变靠近时钟线的帧间状态 |
| 15:8 | SCR |
串行时钟速率 位频率为 PCLK / (CPSDVSR * [SCR + 1]), CPSDVSR为预分频器分频值 PCLK为APB时钟PCLK计时预分频器 |
8.4.2 控制寄存器1 SSP0CR1 SSP1CR1
| 位 | ||
| 0 | LBM |
0 正常操作 1 串行输入脚可做串行输出脚 启用后,发送的数据会直接回环到接收端,用于测试或调试,无需外部连接。在LBM模式下,原本用于接收数据的串行输入脚(如MISO)可以临时用作串行输出脚(类似MOSI),直接输出发送的数据。 |
| 1 | SSE |
SSP使能 0 禁能 1 与总线上的其他设备相互通信,置位前先向其他SSP寄存器和中断控制寄存器写入合适的控制信息 |
| 2 | MS |
主master/从slave模式 SSE为0时才能写入(I/O是输入in/输出out) 0 SSP控制器作为总线主机,驱动SCLK,MOSI和SSEL接收MISO 1 SSP控制器作为总线从机,驱动MISO,接收SLCK、MOSI和SSEL |
| 3 | SOD |
从模式下有用,从机输出禁能, 1 将禁止MISO,从机就发不出去了 |
| 7:4 | 保留 |
8.4.3 数据寄存器 SSP0DR、SSP1DR
16位,可往寄存器写入,可从寄存器读出
写入:
状态寄存器 TNF 置1,即Tx FIFO未满时,软件就可以将帧数据写入,满了不能写;
Tx FIFO 原来为空并且总线上SSP控制器空闲,写了立马发,不然排队等
小于16位,写入寄存器的数据右对齐
读出:
状态寄存器 RNE 置一,即Rx FIFO未空,就能读出数据
读的时候返回Rx FIFO最早接收到的帧数据
读出的数据小于16位,高位补零
8.4.4 状态寄存器 SSP0SR、SSP1SR
只读
| 位 |
E为empty F为full |
描述 |
| 0 | TFE | 1 发送FIFO为空 |
| 1 | TNF | 1 发送FIFO未满 |
| 2 | RNF | 1 接收FIFO未空 |
| 3 | RFE | 1 接收FIFO为空 |
| 4 | BSY忙 |
0 空闲 1 发送/接收一个帧或TxFIFO非空 |
| 7:5 | 保留 |
8.4.5 时钟预分频寄存器 SSP0CPSR SSP1CPSR
该寄存器对SSP外设时钟SSP_PCLK分频来获得预分频时钟,再被SSPnCR0(8.4.1)中的SCR因数分频得到位时钟
[7:0] CPSDVSR 为2~256之中的一个偶数,第0位就保持0不变了

实际硬件限制使得SCLK速率不能超过SSP外设时钟的1/12。
8.4.6 中断屏蔽置位/清零寄存器 SSP0IMSC SSP1IMSC
4个中断条件的使能
| 位 | ||
| 0 | ROIM |
当SPI接收缓冲区已满(即已接收到数据但未被读取),而新的数据又到达时,会发生接收溢出。 使能ROIM中断后,当发生接收溢出时,SPI模块会触发中断,通知程序处理溢出情况。 |
| 1 | RTIM | 接收超时(Rx FIFO非空且在超时周期内没有读出任何数据)后,置位该位会触发接收超时中断 |
| 2 | RXIM | Rx FIFO至少有一半满,产生中断 |
| 3 | TXIM | Tx FIFO至少有一半空,产生中断 |
| 7:4 | 保留 |
8.4.7 原始中断状态寄存器 SSP0RIS SSP1RIS
不管SSPnIMSC中的中断是否使能,只要出现有效的中断条件,SSP原始中断状态寄存器就将相应的位置一。
| 位 | ||
| 0 | RORRIS | 当SPI接收缓冲区已满(即已接收到数据但未被读取),而新的数据又到达时,会发生接收溢出。该位置一 |
| 1 | RTRIS | 接收超时 |
| 2 | RXRIS | Rx FIFO至少有一半满 |
| 3 | TXRIS | Tx FIFO至少有一半空 |
| 7:4 | 保留 |
8.4.8 屏蔽中断状态寄存器 SSP0MIS SSP1MIS
中断条件触发且中断使能时,相应位置一
| 位 | ||
| 0 | RORRIS | 当SPI接收缓冲区已满(即已接收到数据但未被读取),而新的数据又到达时,会发生接收溢出。该位置一 |
| 1 | RTRIS | 接收超时 |
| 2 | RXRIS | Rx FIFO至少有一半满 |
| 3 | TXRIS | Tx FIFO至少有一半空 |
| 7:4 | 保留 |
8.4.9 SSP中断清零寄存器 SSP0ICR SSP1ICR
用于清零接收溢出Receive Overrun 和接收超时 Receive Timeout 的中断
另外两个RXIM、TXIM通过读/写 Rx/ Tx FIFO会自动清零
| 位 | 写1清除 | |
| 0 | RORIC | 清除ROIM |
| 1 | RTRC | 清除RTIM |
| 7:2 | 保留 |
8.5 SPI实现读取XT25
复制UART工程,然后新建 XT25.c、XT25.h、SPI.c、SPI.h
main.c
#include <LPC11xx.h>
#include "LED.h"
#include "Button.h"
#include "TIMER.h"
#include "UART.h"
#include "string.h"
#include "SPI.h"
#include "XT25.h"
int main(void)
{
LED_Init();
LED_ON();
UART_Init();
SSPI1_Init(); // SPI初始化
char message[] = "Hello, SPI!";// 定义要发送的数据
int length = strlen(message);// 计算数据长度,不包括结束符 '\0'
UART_Send(message, length); // 调用UART_Send函数发送数据
UART_Send_Bit(0x0d); //发送换行
UART_Send_Bit(0x0a);
// 读取唯一ID
uint8_t ID[16];
XT25_RUID(ID);
UART_Send((char *)ID, 16);
UART_Send_Bit(0x0d); //发送换行
UART_Send_Bit(0x0a);
uint8_t data[8] = "01234567"; // 要发的数据
uint8_t receive[20]; // 接收数据放这里
// 擦除所有数据
XT25_EraseAll();// 观察手册,擦整个芯片时间为1.7 - 5s, 耐心等一下
long int ADDR = 0x000000; // 要操作的地址
SPI1_Read_FLASH(ADDR, receive, 8); // 读取该地址下的数据放到receive
UART_Send((char *)receive, 8); // 擦除后所有位都为1,十六进制显示每个字节都是FF
UART_Send_Bit(0x0d); // 发送换行
UART_Send_Bit(0x0a);
SPI1_Write_FLASH(ADDR, data, 8); // 发送温度 以转换好的数组的形式发送 到xt25
SPI1_Read_FLASH(ADDR, receive, 8); // 读取该地址下的数据放到receive
UART_Send((char *)receive, 8); // 串口发送收到的数据
UART_Send_Bit(0x0d);//发送换行
UART_Send_Bit(0x0a);
ADDR = 0x010000; // 第二块扇区
uint8_t data2[] = "20250217";
SPI1_Write_FLASH(ADDR, data2, 8); // 发送温度 以转换好的数组的形式发送 到xt25
SPI1_Read_FLASH(ADDR, receive, 8); // 读取该地址下的数据放到receive
UART_Send((char *)receive, 8); // 串口发送收到的数据
UART_Send_Bit(0x0d);//发送换行
UART_Send_Bit(0x0a);
ADDR = 0x000000;
XT25_EraseSector(ADDR); // 擦除第一块扇区
SPI1_Read_FLASH(ADDR, receive, 8);
UART_Send((char *)receive, 8); // 又是八个0xFF
UART_Send_Bit(0x0d);//发送换行
UART_Send_Bit(0x0a);
while (1)
{
}
}
XT25.c
#include "XT25.h"
/*
*********************************************************************************************************
* 函 数 名: XT25_WriteEnable()
* 功能说明: 写入使能
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void XT25_WriteEnable()
{
SSP1_LOW(); // 开始通信
SPI1_comunication(WREN);// 写入使能
SSP1_HIGH(); // 结束通信
}
/*
*********************************************************************************************************
* 函 数 名: XT25_ReadSR()
* 功能说明: 读状态寄存器
* 形 参:无
* 返 回 值: sr状态寄存器数据
*********************************************************************************************************
*/
uint8_t XT25_ReadSR()
{
uint8_t sr; // 定义一个变量来存储读取到的状态寄存器数据
SSP1_LOW(); // 拉低SPI的片选信号,开始与SPI设备通信
SPI1_comunication(RDSR); // 向外设发送读取状态寄存器(RDSR)命令
sr = SPI1_comunication(0xff); // 发送一个填充字节0xff以读取状态寄存器的数据
SSP1_HIGH(); // 拉高SPI的片选信号,结束与SPI设备通信
return sr; // 返回读取到的状态寄存器数据
}
/*
*********************************************************************************************************
* 函 数 名: XT25_Write_Wait()
* 功能说明: 忙碌等待 写入等待
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void XT25_Write_Wait()
{
uint8_t stat_code;
do {
stat_code = XT25_ReadSR();
} while (stat_code & 0x01); // 等待 BUSY 位为 0
}
/*
*********************************************************************************************************
* 函 数 名: XT25_Read_Wait()
* 功能说明: 忙碌等待 读出等待
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void XT25_Read_Wait()
{
int stat_code=0; // 用于存储读取的状态寄存器值
while(1)
{
stat_code=XT25_ReadSR();
if((stat_code&1)==0)
break;
}
}
/*
*********************************************************************************************************
* 函 数 名: XT25_EraseAll()
* 功能说明: 擦除整个芯片 需要等待1.7 - 5 S
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void XT25_EraseAll()
{
XT25_WriteEnable();//写入使能
SSP1_LOW();
SPI1_comunication(XT25_CMD_ERASE_ALL);//擦除整个芯片
SSP1_HIGH();
}
/*
*********************************************************************************************************
* 函 数 名: XT25_RUID(uint8_t *res)
* 功能说明: 发送读取唯一标识符命令
* 形 参:16位数组头地址
* 返 回 值: 无
*********************************************************************************************************
*/
void XT25_RUID(uint8_t *res)
{
XT25_WriteEnable();//写入使能
SSP1_LOW();
SPI1_comunication(XT25_CMD_RUID);// 发送读取唯一标识符指令
SPI1_comunication(0x00);
SPI1_comunication(0x00);
SPI1_comunication(0x00);
uint8_t i;
for(i = 0; i < 16; i ++)
{
res[i] = SPI1_comunication(0xFF);
}
SSP1_HIGH();
}
/*
*********************************************************************************************************
* 函 数 名: XT25_EraseSector(uint32_t address)
* 功能说明: 通过 SPI 向闪存芯片发送擦除命令,要求芯片擦除指定的扇区,相应地址分3段发送
温度25~85度等待75-1000ms、 -40~25度等待75-2000ms
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void XT25_EraseSector(uint32_t address)
{
XT25_WriteEnable();//写入使能
SSP1_LOW();
SPI1_comunication(SECTOR_ERASE);// 发送擦除扇区指令
SPI1_comunication(address >> 16); // 发送地址的高8位
SPI1_comunication(address >> 8); // 发送地址的中间8位
SPI1_comunication(address); // 发送地址的低8位
SSP1_HIGH();// 拉高CS
}
/*
*********************************************************************************************************
* 函 数 名: XT25_WriteSR(uint8_t sr)
* 功能说明: 通过 SPI 接口将一个字节(sr)写入闪存芯片的状态寄存器
* 形 参:sr要写入的状态寄存器值
* 返 回 值: 无
*********************************************************************************************************
*/
void XT25_WriteSR(uint8_t sr)
{
SSP1_LOW(); // 拉低CS
SPI1_comunication(WRSR); // 发送写入状态寄存器指令
SPI1_comunication(sr); // 发送状态寄存器值
SSP1_HIGH(); // 拉高CS
}
XT25.h
#ifndef _XT25_H_
#define _XT25_H_
#include <LPC11XX.h>
#include "SPI.h"
void XT25_WriteEnable(void);//写入使能
uint8_t XT25_ReadSR(void);//读状态寄存器
void XT25_Write_Wait(void);//忙碌等待 写入等待
void XT25_Read_Wait(void);//忙碌等待 读出等待
void XT25_EraseAll(void);//擦除整个芯片
void XT25_RUID(uint8_t *res);//读取唯一标识符指令
void XT25_EraseSector(uint32_t address);//擦除扇区
void XT25_WriteSR(uint8_t sr);//写入状态寄存器
#define WREN 0X06//写入使能
#define WRDI 0X04//写入禁止
#define RDSR 0X05//读取状态寄存器
#define WRSR 0X01//写入状态寄存器
#define SECTOR_ERASE 0x20
#define XT25_CMD_ERASE_ALL 0xC7
#define XT25_CMD_RUID 0x4B
#define CHIP_ERASE 0xC7 // 擦除整个芯片的指令代码
#endif
SPI.c
#include "SPI.h"
#include <stdio.h>
uint8_t src_addr[16]; //写
uint8_t dest_addr[16];//读
/*Delay 1s函数*/
void Delay_1s(void)
{
int i=SystemCoreClock/500;//0.01s
while(--i);
}
/*
*********************************************************************************************************
* 函 数 名: SSP1_IOConfig()
* 功能说明: 配置 MISO、MOSI 和 SCK(时钟)引脚
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void SSP1_IOConfig()
{
LPC_SYSCON->SYSAHBCLKCTRL |=((1<<6)|(1<<16)); //IO 和GPIO
LPC_IOCON->PIO2_2 &=~(0X07);
LPC_IOCON->PIO2_2 |=0X02;// 把PIO2_3选择为MISO
LPC_IOCON->PIO2_3 &=~(0X07);
LPC_IOCON->PIO2_3 |=0X02;//把PIO2_2选择为MOSI
LPC_IOCON->PIO2_1 &=~(0X07);
LPC_IOCON->PIO2_1 |=0X02;//把PIO2_1选择为LPC_SSP CLK
LPC_SYSCON -> SYSAHBCLKCTRL &= ~(1 << 16); // 禁能IOCON时钟
LPC_GPIO2->DIR |= (1<<0); //输出
LPC_GPIO2->DATA |= (1<<0); //片选信号 拉高
}
// 开始通信
void SSP1_LOW()
{
LPC_GPIO2->DATA &= ~(1<<0); //拉低
}
// 结束通信
void SSP1_HIGH()
{
LPC_GPIO2->DATA |= (1<<0); //拉高
}
/*
*********************************************************************************************************
* 函 数 名: SSPI1_Init()
* 功能说明: 初始化 SSP1 接口,配置其为 SPI 主设备模式,并准备好进行数据传输
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void SSPI1_Init()
{
uint8_t Dummy=Dummy; //解决编译产生的Warning:never used
uint8_t i;
LPC_SYSCON->PRESETCTRL |=1<<2; //禁止LPC_ssp1复位
LPC_SYSCON->SYSAHBCLKCTRL |=(1<<18); //ssp1 时钟使能
LPC_SYSCON->SSP1CLKDIV=0X06 ; //分频值 6 48/6=8MHz
SSP1_IOConfig(); //初始化SSP1 IO口
LPC_SSP1->CR0=0X0707; //0x00000111 00000111 CPSR=7 DATAbit= 8 CPOL=0 CPHA=0 SCR=7 模式0空闲低电平,上升沿采样
LPC_SSP1->CPSR=50; //0x06 偶数就行
LPC_SSP1->CR1 &=~(1<<0);//LBM=0 :正常模式
LPC_SSP1->CR1 &=~(1<<2);//MS=0 主机模式
LPC_SSP1->CR1 |=1<<1; //SSE=1 开启ssp1
//清空RXFIFO LPC1114收发均有8帧FIFO,每帧可放置4~16位数据
for(i=0 ; i < 8 ; i ++)
{
Dummy=LPC_SSP1->DR; // 读取寄存器DR将清空RxFIFO
}
for(i=0;i<16;i++)
{
dest_addr[i]=0;
src_addr[i]=0;
}
}
/*
*********************************************************************************************************
* 函 数 名: SPI1_comunication(uint8_t TxData)
* 功能说明: 通过 SPI 协议发送并接收数据
* 形 参:TxData发送数据
* 返 回 值: 从SPI接收到的数据
*********************************************************************************************************
*/
uint8_t SPI1_comunication(uint8_t TxData)
{
while(((LPC_SSP1->SR)&(1<<4))==(1<<4));//忙时等待
LPC_SSP1->DR=TxData; //发送数据到TxFIFO
while(((LPC_SSP1->SR)&(1<<2))!=(1<<2));//接收非空就接收,等待数据接收完
return (LPC_SSP1->DR); //接收返回的数据
}
/*
*********************************************************************************************************
* 函 数 名: SSP1_Send(uint8_t *data,uint8_t Length)
* 功能说明: 逐字节地发送一个数据数组
* 形 参:*data传入的要发送的数据数组的起始地址 Length需要发送的数据长度
* 返 回 值: 无
*********************************************************************************************************
*/
void SSP1_Send(uint8_t *data,uint8_t Length)
{
uint8_t i;
for(i=0;i<Length;i++)
{
SPI1_comunication(data[i]);
}
}
/*
*********************************************************************************************************
* 函 数 名: SSP1_Receive(uint8_t *data,int Length)
* 功能说明: 逐字节接收数据数组
* 形 参:*data接收数据的目标数组 Length要接收的数据长度
* 返 回 值: 无
*********************************************************************************************************
*/
void SSP1_Receive(uint8_t *data,int Length)
{
uint8_t Dummy=Dummy; //随机数 用于产生时钟
uint8_t i;
for(i=0 ; i<Length ;i++)
{
data[i]=SPI1_comunication(0xff);
}
}
/*
*********************************************************************************************************
* 函 数 名: SPI1_Write_FLASH(uint8_t *data, uint8_t Length)
* 功能说明: 写flash
* 形 参:*data要写的数据, Length数据长度
* 返 回 值: 无
*********************************************************************************************************
*/
void SPI1_Write_FLASH(uint32_t ADDR, uint8_t *data, uint8_t Length)
{
uint8_t i;
XT25_WriteEnable();//写入使能
src_addr[0]=WRITE;//页面编程开始
//地址1~3
src_addr[1]=(uint8_t)((ADDR)>>16);
src_addr[2]=(uint8_t)((ADDR)>>8);
src_addr[3]=(uint8_t) ADDR;
//写入的数据
for(i=0;i<Length;i++)
{
src_addr[i+4]=data[i];
}
XT25_Write_Wait(); //忙时等待
SSP1_LOW();//使能
SSP1_Send((uint8_t *)src_addr,4+Length);
SSP1_HIGH();//拉高
}
/*
*********************************************************************************************************
* 函 数 名: SPI1_Read_FLASH(uint8_t *data,uint8_t Length)
* 功能说明: 读flash
* 形 参:*data存储读的数据, Length数据长度
* 返 回 值: 无
*********************************************************************************************************
*/
void SPI1_Read_FLASH(uint32_t ADDR, uint8_t *data,uint8_t Length)
{
int i;
src_addr[0]=READ;
//读取的地址
src_addr[1]=(uint8_t)((ADDR)>>16);
src_addr[2]=(uint8_t)((ADDR)>>8);
src_addr[3]=(uint8_t) ADDR;
XT25_Read_Wait();
SSP1_LOW();
SSP1_Send((uint8_t *)src_addr,4);
SSP1_Receive((uint8_t *)dest_addr,Length);// 接收数据
SSP1_HIGH();
for(i=0;i<Length;i++)
data[i]=dest_addr[i];
}
SPI.h
#ifndef _SPI_H_
#define _SPI_H_
#include <LPC11XX.h>
#include "XT25.h"
//SSP1
void SSP1_IOConfig(void);//函数功能:SSP1IO初始化
void SSP1_LOW(void); // 拉低
void SSP1_HIGH(void); // 拉高
void SSPI1_Init(void);//函数功能:SSP1初始化
uint8_t SPI1_comunication(uint8_t TxData);//SSP1通信接受和发送一个字符
void SSP1_Send(uint8_t *data,uint8_t Length);//SSP1发送
void SSP1_Receive(uint8_t *data,int Length);//SSP1接收
void SPI1_Write_FLASH(uint32_t ADDR, uint8_t *data, uint8_t Length);//写FLASH
void SPI1_Read_FLASH(uint32_t ADDR, uint8_t *data,uint8_t Length);//读FLASH
void Delay_1s(void);
#define READ 0X03
#define WRITE 0X02
#endif
串口显示
十六进制显示,选中的为唯一编号

正常显示

更多推荐





所有评论(0)