PIC18F26Q43 SPI从机无法接收数据:双PIC18 SPI通信配置问题求助
结合你的描述和代码,我发现几个关键配置和逻辑问题,这些很可能是导致RX/TX中断不触发、无法接收数据的原因,咱们一步步梳理:
1. 全局中断与外设中断总开关未开启
你只配置了SPI相关的中断使能位,但如果没打开全局中断和外设中断总开关,所有中断都不会触发。必须在初始化代码中添加:
INTCONbits.GIE = 1; // 开启全局中断 INTCONbits.PEIE = 1; // 开启外设中断(SPI属于外设中断范畴)
2. SPI时序与主机不匹配
你的SPI1CON1设置为0b00000100,对应CKP=0、CKE=0,这意味着:
- 空闲时SCK为低电平
- 数据在SCK上升沿采样、下降沿发送
SPI通信要求主机和从机的时序完全一致,如果主机的CKP/CKE参数和从机不匹配,从机根本无法正确采样数据,自然不会触发RX中断。建议先统一主从机时序,比如改成常用的CKP=0, CKE=1模式,调整代码:
// 从机模式下SMP必须设为0,这里调整CKE为1,保证和主机时序匹配 SPI1CON1 = 0b00001100;
3. SS引脚配置缺失与模式错误
你把SS映射到了RA6,但没设置TRISA6=1——如果RA6是输出模式,根本无法正确接收主机的片选信号(哪怕你说SS中断正常,也可能是偶然或者其他地方的临时配置)。必须加上:
TRISA6 = 1; // 将SS引脚设为输入
另外,SPI1CON1的SSP位你设为1,这会让SS引脚失去从机选择功能(变成普通IO),从机模式下必须设为0,让SS引脚控制从机的使能状态:
SPI1CON1bits.SSP = 0;
4. 中断标志位未清除
你的中断处理程序中,处理SPI1RXIF和SPI1TXIF时没有清除对应的标志位!这会导致第一次触发后标志一直置位,要么重复进入中断,要么后续中断完全不触发。必须补充清除操作:
// byte received if (PIR3bits.SPI1RXIF == 1) { spiRecv.cBuf[spiRecvCsr++] = SPI1RXB; PIR3bits.SPI1RXIF = 0; // 清除RX中断标志 } // byte sent if (PIR3bits.SPI1TXIF == 1) { SPI1TXB = spiSend->cBuf[spiSendCsr++]; PIR3bits.SPI1TXIF = 0; // 清除TX中断标志 }
5. 中断使能重复配置
你同时开启了SPI1INTE里的SOSIE/EOSIE和SPI1SOSIE/SPI1EOSIE,这其实是同一组中断的别名(新型SPI模块的位命名有重复),重复开启可能导致冲突。建议只保留一组:
// 保留SPI1INTE里的核心中断使能即可 SPI1INTEbits.SOSIE = 1; SPI1INTEbits.EOSIE = 1; SPI1INTEbits.RXOIE = 1; // 开启RX FIFO溢出中断(如果需要) // 注释掉重复的配置 // SPI1INTEbits.SPI1EOSIE=1; // SPI1INTEbits.SPI1SOSIE=1;
6. FIFO初始化遗漏
你开启了TX/RX FIFO(SPI1CON2的TXR=1、RXR=1),但在SS中断触发时没有清空FIFO,残留的旧数据可能干扰新传输。建议在SS中断处理中添加:
SPI1FCLRbits.RXCLR = 1; // 清空RX FIFO SPI1FCLRbits.TXCLR = 1; // 清空TX FIFO
建议你先从全局中断和SS引脚配置入手调整,这两个是最容易忽略的基础问题,再逐步排查时序和中断标志位的问题。
内容的提问来源于stack exchange,提问作者user5717448

