PIC16LF18855自定义I2C库故障求助:SSP1IF未触发
PIC16LF18855 I2C库问题分析与修复
核心问题:引脚方向配置错误
I2C总线采用开漏输出机制,无论主机还是从机,SCL/SDA引脚都必须配置为输入模式(TRIS=1),由MSSP模块内部控制引脚电平变化。你的代码中错误地将TRISC3和TRISC4设为0(输出模式),导致硬件无法生成合法的起始位,进而SSP1STAT.S位和SSP1IF标志位无法触发。
具体修改点
修正引脚方向配置
在I2C_Init()函数中,将TRIS设置改为:TRISC3 = 1; TRISC4 = 1;修正I2C_SendDATA函数的等待逻辑
当前函数未等待数据发送完成就返回ACKSTAT1,导致结果不准确。添加等待BF1位清零的代码:uint8_t I2C_SendDATA(uint8_t data){ SSP1BUF = data; if(WCOL1){ WCOL1 = 0; return 1; } while(BF1); // 等待数据发送完成,BF1清零表示发送结束 return ACKSTAT1; }删除I2C_Write函数中的错误循环代码
函数内的if(i >= dataSize){i=0;}逻辑完全错误,会导致死循环,直接删除这两行:uint8_t I2C_Write(uint8_t adresse, uint8_t RW, uint8_t dataSize, uint8_t *dataArrayPointer){ I2C_Start(); SSP1BUF = (adresse << 1) + RW; if(WCOL1){ WCOL1 = 0; return 1; } while(BF1); for(int i = 0; i < dataSize; i++){ SSP1BUF = dataArrayPointer[i]; if(WCOL1){ WCOL1 = 0; return 1; } // 移除下面两行错误代码 // if(i >= dataSize){ // i = 0; // } while(BF1); } I2C_Stop(); return 0; }优化主循环的I2C启停逻辑
无需在每次循环中重复执行I2C_Open()和I2C_Close(),初始化后只需开启一次I2C即可:// 主函数初始化部分 I2C_Init(); I2C_Open(); while(1){ I2C_Start(); debuggVal = I2C_SendADD(0x7C, W); debuggVal = I2C_SendDATA(0xAF); I2C_Stop(); __delay_ms(100); // 添加延时避免总线频繁操作 }可选:修正I2C时钟配置(按需调整)
你的代码注释标注时钟为FOSC/32,但当前SSP1CON1=0x08(对应FOSC/(4*(SSPADD+1))),结合SSPADD=0x1F,实际时钟为FOSC/(4*32)=FOSC/128,与注释不符。若需FOSC/32,可调整:// 方式1:使用FOSC/(4*(SSPADD+1)) SSP1CON1 = 0x08; SSP1ADD = 0x07; // 4*(0x07+1)=32 → 时钟=FOSC/32 // 方式2:使用FOSC/(16*(SSPADD+1)) SSP1CON1 = 0x09; SSP1ADD = 0x01; //16*(0x01+1)=32 → 时钟=FOSC/32
验证要点
修改后,重新调试时可观察:
SSP1STAT.S位在调用I2C_Start()后是否置位SSP1IF标志位是否在起始位生成、数据发送完成后正常触发- 总线波形是否符合I2C协议规范
内容的提问来源于stack exchange,提问作者quang
相关产品推荐
相关产品推荐

