Pic18f4550 I2C通信故障:从机无应答问题求助
PIC18F4550 I2C通信故障排查与修复
问题描述
两块PIC18F4550单片机实现I2C通信:主机发送数据,从机接收后将数据输出到PORTD的LED。当前故障:主机地址发送后(LED2点亮),收不到从机应答(LED3不亮);从机地址匹配指示灯(MATCH)点亮,但数据LED无输出。
主机代码
//==================== Master I2C code========================= bit I2C_Write(unsigned char address, unsigned char *data, unsigned char datasize) { SSPCON2bits.SEN = 1; // 启动I2C起始条件,硬件自动清除 while (!PIR1bits.SSPIF); PIR1bits.SSPIF = 0; LED1 = 1; SSPBUF = address; while (!PIR1bits.SSPIF); PIR1bits.SSPIF = 0; LED2 = 1; // 此LED点亮,说明地址已发送 if (SSPCON2bits.ACKSTAT) { // 未收到应答,发送停止条件 SSPCON2bits.PEN = 1; while (SSPCON2bits.PEN); ACK = 1; return 0; } LED3 = 1; // 此LED不亮,说明未收到从机应答 int i; for (i = 0; i < datasize; i++) { SSPBUF = *data; while (!PIR1bits.SSPIF); PIR1bits.SSPIF = 0; if (SSPCON2bits.ACKSTAT) { SSPCON2bits.PEN = 1; while (SSPCON2bits.PEN); ERROR = 1; return 0; } LED = *data; data++; } LED4 = 1; SSPCON2bits.PEN = 1; // 发送I2C停止条件 while (SSPCON2bits.PEN); PIR1bits.SSPIF = 0; return 1; } //-----I2C初始化--------- void I2C_INIT(void) { SDA_dir = 1; SCL_dir = 1; ADCON1bits.PCFG = 0b1111; // 所有引脚设为数字IO SSPADD = _XTAL_FREQ / (4 * Baud_Rate) - 1; SSPSTATbits.SMP = 0; // 标准速度模式下禁用斜率控制 SSPCON1bits.SSPEN = 1; // 使能I2C模块 SSPCON1bits.SSPM = 0b1000; // I2C主机模式,时钟=FOSC/(4*(SSPADD+1)) } //-------主机调用示例-------- unsigned char data[5] = {0xA1, 0xB1, 0xC1, 0xD1, 0xE1}; I2C_Write(0b00111100, data, 5);
从机代码
//=======================Slave I2c code=========================== unsigned char Read_data; void __interrupt() ISR(void) { if (PIR1bits.SSPIF) { if (SSPSTATbits.D_NOT_A) { // 收到数据字节 Read_data = SSPBUF; // 读取数据 PORTD = Read_data; // 输出到PORTD的LED // 发送应答给主机 SSPCON2bits.ACKDT = 0; // 应答位设为0(应答) SSPCON2bits.ACKEN = 1; // 触发应答发送 while(SSPCON2bits.ACKEN); // 等待应答完成 } else { // 收到地址字节,匹配成功 MATCH = 1; unsigned char dummy = SSPBUF; // 读取地址清除BF位 // 发送应答给主机 SSPCON2bits.ACKDT = 0; SSPCON2bits.ACKEN = 1; while(SSPCON2bits.ACKEN); } PIR1bits.SSPIF = 0; // 清除中断标志 } } //--------从机初始化--------------------- void I2C_INIT(void) { SDA_dir = 1; SCL_dir = 1; ADCON1bits.PCFG = 0b1111; // 所有引脚设为数字IO SSPADD = 0b0011110; // 7位从机地址(注意:不是带读写位的8位) SSPSTATbits.SMP = 0; // 标准速度模式下禁用斜率控制 SSPCON1bits.SSPEN = 1; // 使能I2C模块 SSPCON1bits.SSPM = 0b1110; // I2C从机模式,7位地址,支持起始/停止中断 // 开启I2C中断 PIE1bits.SSPIE = 1; INTCONbits.PEIE = 1; // 使能外设中断 INTCONbits.GIE = 1; // 使能全局中断 }
故障原因与修复要点
- 从机地址配置错误:从机
SSPADD应设为7位地址0b0011110,而非带读写位的8位地址0b00111100,确保与主机发送的地址(7位左移+写位)匹配。 - 从机未发送应答:无论地址匹配还是数据接收,从机都需主动发送应答——设置
ACKDT=0、触发ACKEN=1并等待完成,否则主机收不到应答会终止传输。 - 从机中断未开启:必须开启
SSPIE、PEIE、GIE三个中断控制位,否则I2C中断无法触发,无法处理地址和数据。 - 从机SMP位设置错误:标准速度(100kHz)模式下,
SSPSTATbits.SMP需设为0,符合I2C时序规范。 - 主机代码语法错误:修复
I2C_INIT函数末尾的括号错误,停止条件发送需使用SSPCON2bits.PEN=1。 - 从机地址匹配时需读取SSPBUF:地址匹配后必须读取
SSPBUF清除BF标志,否则后续无法接收数据。
内容的提问来源于stack exchange,提问作者Aizaz
相关产品推荐
相关产品推荐

