如何通过SPI读取Flash ID?PIC32与MX25L51245G调试故障求助
问题分析与解决方案
一、SPI配置的核心故障点(SPI1CON)
你的SPI初始化代码存在两个关键错误,直接导致无法正确读取Flash ID:
1. 错误设置16位传输模式
你在SPI1CONSET中加入了SPI1_CON_MODE_32_MODE_16宏,将SPI1设置为16位传输模式,但主程序是按8位字节发送命令和接收数据的,两者完全不匹配:
- 16位模式下,每次写入
SPI1BUF会发送16位数据(低16位有效),你写入的0x9F实际会被发送为0x009F(两个字节),Flash收到的第一个字节是无效的0x00,自然不会触发读取ID的操作,返回乱码。 - 接收时
SPI1BUF返回16位数据,用uint8_t类型接收会截断高8位,进一步加剧数据错误。
修复方法:移除SPI1_CON_MODE_32_MODE_16宏,SPI默认是8位模式,无需额外设置。
2. SPI时钟模式不匹配MX25L51245G要求
MX25L51245G支持SPI Mode 0(CPOL=0,CPHA=0)或Mode 3(CPOL=1,CPHA=1),你的当前配置CKP=1+CKE=1不符合这两种模式:
- CKP=1表示SCK空闲时为高电平,CKE=1表示数据在SCK从有效态(低)转为空闲态(高)时变化,和Flash的时序要求不匹配。
- 你设置了
SMP=1(数据在传输末尾采样),对于Mode 0来说,应该设置SMP=0(数据在时钟周期中间采样)才能正确读取Flash输出的数据。
推荐的SPI1CON配置:
SPI1CONSET = (SPI1_CON_CKE | SPI1_CON_MSTEN); // 解释: // - MSTEN=1:主机模式 // - CKP=0(默认,不设置SPI1_CON_CKP):SCK空闲低电平(Mode 0) // - CKE=1:数据在SCK从空闲态到有效态(低→高)时变化,对应Flash在上升沿输出数据 // - SMP=0(默认,不设置SPI1_CON_SMP):在时钟周期中间采样数据,匹配Flash的输出时序
二、示波器探头影响测试结果的原因
示波器探头本身带有负载(比如10X探头通常是10MΩ电阻+~10pF电容),会对被测信号造成干扰:
- 探头连接SO和SI时:SO是MX25L的输出引脚,驱动能力较弱(Flash的IO驱动电流通常在mA级别),探头的电容和电阻会拉低SO信号幅度、减缓边沿速度,导致PIC32的SPI接收器无法正确识别电平,因此接收不到任何数据。
- 探头连接CS#和SI时:CS#是PIC32的输出引脚,驱动能力较强,但探头的电容会使CS#的边沿变缓,导致Flash对CS#的采样时机出现偏差,每次复位后时序的微小差异会导致返回的ID数据随机变化。
三、其他需要检查的细节
- CS#引脚控制:确保
nCS和DIS_nCS宏正确控制Flash的CS#引脚,且该引脚被设置为输出(比如TRISBbits.TRISB2 = 0,对应你初始化中的LATBSET = (1 << 2))。 - SPI引脚映射:确认PIC32的SPI1引脚(SDO/RF6→Flash SI,SDI/RF7→Flash SO,SCK/RF8→Flash SCK)连接正确,引脚方向设置无误。
- 主程序接收逻辑:在8位模式下,发送命令后Flash会在后续每个时钟周期返回一个字节,你的主程序逻辑是正确的,但要确保读取
SPI1BUF前等待SPIRBF标志位为1,避免读取空数据。
修复后的SPI初始化代码示例
void SPI1_Initialize ( void ) { uint32_t rdata; /* Disable SPI1 Interrupts */ IEC0CLR = 0x800000; IEC0CLR = 0x2000000; IEC0CLR = 0x1000000; /* STOP and Reset the SPI */ SPI1CON = 0; /* Clear the Receiver buffer */ rdata = SPI1BUF; rdata = rdata; /* Clear SPI1 Interrupt flags */ IFS0CLR = 0x800000; IFS0CLR = 0x2000000; IFS0CLR = 0x1000000; /* Set CS# pin as output and initial high */ TRISBbits.TRISB2 = 0; LATBSET = (1 << 2); // Set SS1 high /* BAUD Rate register Setup */ SPI1BRG = 39; // 假设PBCLK是40MHz,SPI时钟=40/(2*(39+1))=500kHz,符合Flash要求 /* Clear the Overflow */ SPI1STATCLR = _SPI1STAT_SPIROV_MASK; /* Set SPI pin directions */ TRISFbits.TRISF6 = 0; // SDO (RF6) output TRISFbits.TRISF7 = 1; // SDI (RF7) input TRISFbits.TRISF8 = 0; // SCK (RF8) output PORTFbits.RF6 = 0; PORTFbits.RF8 = 0; /* Configure SPI Mode 0 */ SPI1CONSET = (SPI1_CON_CKE | SPI1_CON_MSTEN); // 移除16位模式、CKP、SMP设置,使用默认8位、CKP=0、SMP=0 /* Initialize global variables */ spi1Obj.transferIsBusy = false; spi1Obj.callback = NULL; spi1Obj.txBuffer = NULL; spi1Obj.rxBuffer = NULL; spi1Obj.txSize = 0; spi1Obj.rxSize = 0; spi1Obj.txCount = 0; spi1Obj.rxCount = 0; spi1Obj.dummySize = 0; /* Enable SPI1 */ SPI1CONSET = _SPI1CON_ON_MASK; }
内容的提问来源于stack exchange,提问作者kkyleyang
相关产品推荐
相关产品推荐

