You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何PIC32与ESP32S3进行I2C通信时无法获取ACK位?

PIC32MK与ESP32S3 I2C通信ACK问题排查

我正在开发一个项目,使用PIC32MK1024MCM064作为I2C主机,与ESP32S3从机和PCF8574 IO扩展器(驱动16x2 LCD)通信。目前PIC32与PCF8574通信完全正常,LCD工作完美,但和ESP32S3通信时遇到ACK位问题——推测是PIC32未释放SDA线,导致ESP32S3无法拉低SDA发送ACK。

已确认的信息:

  • 使用5.1k上拉电阻
  • I2C速率为标准100Kbit/s,实际测得95-97Kbit/s,在可接受范围内
  • 接线和设备地址均正确
  • ESP32S3从机代码在两台ESP32S3(主从模式)测试时能正常收到带ACK的数据包

现在不同MCU间通信无法获取ACK,怀疑是配置问题(比如时钟匹配或其他未知参数),求排查建议。


主程序代码(main.c)

#include <xc.h> 
#include "configurations_bits.h"                                                                     

#include <stddef.h>                                                                               
#include <stdint.h>                     
#include <stdbool.h>                     
#include <stdlib.h> 
#include "stdio.h" 
#include <sys/attribs.h> 

#include "delay.h"                                                                               
#include "inter_integrated_circuit_protocol.h" 

#define ESP32 (0B1100000)   //Write address
#define LCD (0B1000000)     //Write address

 uint8_t Number = 0x71;  //Random value

    int main(void) {    

    ANSELA = 0x00000000;                                                                     
    ANSELB = 0x00000000;                                                                      
    ANSELC = 0x00000000;                                                                      
    ANSELE = 0x00000000;                                                                      
    ANSELG = 0x00000000;                                                                      

    TRISCbits.TRISC11 = 0b1;           //RC11 PIN_24 ADC pin for battery 
    TRISAbits.TRISA1 = 0b1;            //RA1 PIN_14 Particle detection 
    TRISCbits.TRISC7 = 0b1;            //RC7 PIN_51 First GUI button
    TRISCbits.TRISC8 = 0b1;            //RC8 PIN_52 Second GUI button
    TRISEbits.TRISE15 = 0b1;           //RE15 PIN_30 Third GUI button
    TRISEbits.TRISE14 = 0b1;           //RE14 PIN_29 Fourth GUI button
    TRISDbits.TRISD5 = 0b1;            //RD5 PIN_53 Encoder channel A
    TRISDbits.TRISD6 = 0b1;            //RD5 PIN_54 Encoder channel B
    TRISGbits.TRISG6 = 0b1;            //RG6 PIN_4 ESP32 -> PIC32 communication
    TRISAbits.TRISA11 = 0b1;           //RA11 PIN_12 ESP32 -> PIC32 communication
    TRISAbits.TRISA12 = 0b1;           //RA12 PIN_11 ESP32 -> PIC32 communication
    TRISAbits.TRISA0 = 0b1;            //RA0 PIN_13 UART RX

    Inter_Integrated_Circuit_Setup ();                                                        
    Inter_Integrated_Circuit_Enable ();                                                        

    //First I2C operation writing something to PCF8574 IO expander (I am getting ACK)
    Inter_Integrated_Circuit_Start();
    Inter_Integrated_Circuit_Write(LCD);
    Inter_Integrated_Circuit_Write(Number); 
    Inter_Integrated_Circuit_Stop();
    
    //Second I2C operation writing something to ESP32S3 (I am getting NACK)
    Inter_Integrated_Circuit_Start();
    Inter_Integrated_Circuit_Write(ESP32);
    Inter_Integrated_Circuit_Write(Number); 
    Inter_Integrated_Circuit_Stop();

        while (true){    

        }

return (EXIT_FAILURE);}

I2C头文件(inter_integrated_circuit_protocol.h)

//************************************************************************** 
// INTER INTEGRATED CIRCUIT PROTOCOL HEADER FILE
//**************************************************************************

void Inter_Integrated_Circuit_Setup (void);
    
void Inter_Integrated_Circuit_Enable (void);
    
void Inter_Integrated_Circuit_Disable (void);
    
void Inter_Integrated_Circuit_State (void);
    
void Inter_Integrated_Circuit_Start (void);
    
void Inter_Integrated_Circuit_Stop (void);
    
void Inter_Integrated_Circuit_Repeated_Start (void);
    
void Inter_Integrated_Circuit_Write (uint8_t I2C_data);
    
uint8_t Inter_Integrated_Circuit_Read (void);

I2C源文件(inter_integrated_circuit_protocol.c)

//************************************************************************** 
// INTER INTEGRATED CIRCUIT PROTOCOL SOURCE FILE
//**************************************************************************

#include <xc.h>                                                                                 

#include <stdint.h>

#include "inter_integrated_circuit_protocol.h" 

#include "delay.h"

void Inter_Integrated_Circuit_Setup (void){

    I2C1BRG = 0xEC;                                                                        
    I2C1CON = 0x00000000;                                                                     
    I2C1CONbits.SDAHT = 0b0;                                                                    
    I2C1CONbits.SIDL = 0b0;                                                                    
    I2C1CONbits.SCLREL = 0b1;                                                                  
    I2C1CONbits.STREN = 0b0;                                                                    
    I2C1CONbits.DISSLW = 0b1;                                                                  
    I2C1CONbits.SMEN = 0b0;                                                                     
  }

void Inter_Integrated_Circuit_Enable (void){
    
    I2C1CONbits.ON = 0b1;                                                                      
 }

void Inter_Integrated_Circuit_Disable (void){
    
    I2C1CONbits.ON = 0b0;                                                                      
 }
 
void Inter_Integrated_Circuit_State (void){
   
    while( (I2C1CON & 0x0000001F) || (I2C1STAT & 0x00000004) );                                
}

void Inter_Integrated_Circuit_Start (void){
    
    Inter_Integrated_Circuit_State ();                                                         
    I2C1CONbits.SEN = 0b1;                                                                     
 }

void Inter_Integrated_Circuit_Stop (void){
    
    Inter_Integrated_Circuit_State ();                                                        
    I2C1CONbits.PEN = 0b1;                                                                     
}

void Inter_Integrated_Circuit_Repeated_Start (void){
    
    Inter_Integrated_Circuit_State ();
    I2C1CONbits.RSEN = 0b1;                                                                     
 }

void Inter_Integrated_Circuit_Write (uint8_t I2C_data){
    
    Inter_Integrated_Circuit_State ();                                                         
    while(I2C1STATbits.TBF != 0);                                                               
    while(I2C1STATbits.TRSTAT != 0);                                                           
    I2C1TRN = I2C_data;

}

uint8_t Inter_Integrated_Circuit_Read (void){
    
    uint8_t I2C_data = 0;
    Inter_Integrated_Circuit_State ();                                                         
    I2C1CONbits.RCEN = 0b1;                                                                     
    while(I2C1STATbits.RBF != 0);                                                               
    I2C_data = (I2C1RCV & 0x000000FF);                                                            
    I2C1CONbits.ACKEN = 0b1;                                                                   
    return (I2C_data);
 }

内容的提问来源于stack exchange,提问作者Vilius Žalėnas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:27:02