Microchip
直播中

陈游斗

7年用户 1133经验值
擅长:控制/MCU
私信 关注
[问答]

PIC18F25K42 i2c从器件识别地址但不会发送ACK

以MCC生成的I2C从配置为起点,也是ISR(随着修改次数的增加)!读取和写入奴隶产生相同的结果:地址被复制到ADB0,ADRIF被设置。但是从来没有ACK:SDA在地址字节之后仍然很高。查看错误,唯一标志的是NACKIF和NACKIF。在清除ADRIF后,它们在CycCurn2C1后标记。然后不要走。已经尝试了地址掩码设置在0x00和0x7f。有很多寄存器,甚至尝试迫使一些(Akdt=1)尝试获得一个ACK…其他设备在同一网络上反应良好,这个PIC运行在64 MHz,而I2C是63kHz。有什么想法吗?

以上来自于百度翻译


      以下为原文

    Took MCC generated i2c Slave configuration as starting point & also their ISR (with an increasing number of modifications!).

Reading and Writing to the slave produce the same result: the address is copied to ADB0 and ADRIF is set.

But there is never an ACK: instead SDA remains high after the address byte.

Looking at the ERRbits, the only ones that ever flag are NACK1IF and NACKIF. They flag up after clearing I2C1IF, after clearing ADRIF. And then don't go away.

Have tried with the address mask set both at 0x00 and 0x7F.

There are a lot of registers and have even tried forcing some (ACKDT=1) to try to get an ACK... To no avail.

Other devices respond fine on the same network and this PIC is running at 64MHz whilst the i2c is 63kHz.

Any ideas?

回帖(11)

孙丽萍

2018-11-28 17:05:41
您是否将I2CXCNT寄存器设置为被转换的字节数?

以上来自于百度翻译


      以下为原文

    Have you set the I2CxCNT register with the number of bytes that are being exchnaged? 
举报

李涛

2018-11-28 17:25:07
这是单程列车,不是交换车。“有什么主意吗?”这可能是一百万件事。

以上来自于百度翻译


      以下为原文

    It's a one way train, not an exchange.
 
"Any ideas?"
It could be a million things.
举报

何元

2018-11-28 17:37:41
PIC是奴隶,所以不知道需要多少字节。在接收到匹配的地址后,它被偷窃。不理解。ISR -无论是被写入还是读取,在访问适当的ADRIF部分(有一个匹配和ADB0中有一个匹配ADR0的数字)之后,它会转到NACK部分。在数据表页554,从接收到的步骤8,它会说:如果有任何预错误的错误条件,例如接收缓冲器溢出或传输缓冲器欠流错误,从将强制NACK和模块变为空闲。然而,在ERRbits中没有设置任何其他错误的比特。在文本传输中没有等价的段落,在地址匹配之后,我得到相同的NACK问题。

以上来自于百度翻译


      以下为原文

    The PIC is the slave so doesn't know how many bytes to expect.
 
It's NACKing after receiving an address that matches. Don't understand.
 

 
// ADR 32;
I2C1ADR0 = 0x20;
// ADR 127;
I2C1ADR1 = 0xFE;
// ADR 0;
I2C1ADR2 = 0x00;
// ADR 0;
I2C1ADR3 = 0x00;
// TXU 0; CSD Clock Stretching enabled; ACKT 0; RXO 0; ACKDT Acknowledge; ACKSTAT ACK received; ACKCNT Acknowledge;
I2C1CON1 = 0x00;
// ABD enabled; GCEN disabled; ACNT disabled; SDAHT 300 ns hold time; BFRET 8 I2C Clock pulses; FME disabled;
I2C1CON2 = 0x00;
// CLK Fosc/4;
I2C1CLK = 0x00;
// CNT 0;
I2C1CNT = 0x00;
// CSTR Enable clocking; S Cleared by hardware after Start; MODE four 7-bit address; EN enabled; RSEN disabled;
I2C1CON0 = 0x80;

PIR2bits.I2C1RXIF=0;
PIR3bits.I2C1TXIF=0;
PIR3bits.I2C1EIF=0;
I2C1ERRbits.NACKIF=0;
PIR3bits.I2C1IF=0;
I2C1PIRbits.PCIF=0;
I2C1PIRbits.ADRIF=0;

PIE2bits.I2C1RXIE=1;//enable I2C RX interrupt
PIE3bits.I2C1TXIE=1;//enable I2C TX interrupt
PIE3bits.I2C1EIE=1;//enable I2C error interrupt
I2C1ERRbits.NACKIE=1;//enable I2C error interrupt for NACK
PIE3bits.I2C1IE=1;//enable I2C interrupt
I2C1PIEbits.PCIE=1;//enable I2C interrupt for stop condition
I2C1PIEbits.ADRIE=1;//enable I2C interrupt for I2C address match condition


I2C1PIR = 0;// ;Clear all the error flags
I2C1ERR = 0;
 

 
and the ISR - whether being written to or read from, after visiting the appropriate ADRIF section (there's a match and ADB0 is populated with a number that matches ADR0) it then goes to the NACK part.
 

 
void I2C1_ISR ( void )
{
 
uint8_t I2C1_data = 0x55;
if ((I2C1STAT1bits.RXBF)||(PIR2bits.I2C1RXIF)) // RXBF = receive buffer full; I2C1RXIF = interrupt for that
{
PIR2bits.I2C1RXIF=0;
I2C1_data = I2C1RXB; // clear the register quick!
}
if(1 == I2C1STAT0bits.R) // if address match READ bit is set
{
 
if (I2C1PIRbits.PCIF) // if a stop condition
{
I2C1PIRbits.PCIF=0;
PIR3bits.I2C1IF=0;
I2C1STAT1bits.CLRBF=1;//clear I2C1TXB and TXBE
}
if (I2C1ERRbits.NACKIF) // if a nack - then that's the end of the read
{
I2C1ERRbits.NACKIF=0;
PIR3bits.I2C1EIF=0;
I2C1STAT1bits.CLRBF=1;//clear I2C1TXB and TXBE
I2C1_StatusCallback(I2C1_SLAVE_READ_COMPLETED);
}
else if(PIR3bits.I2C1TXIF) // transmit interrupt
{
PIR3bits.I2C1TXIF=0;
// callback routine should write data into I2C1TXB

I2C1_StatusCallback(I2C1_SLAVE_READ_A_BYTE);

}
if (I2C1PIRbits.ADRIF) // if an address flag
{
I2C1PIRbits.ADRIF=0;
PIR3bits.I2C1IF=0;
I2C1_StatusCallback(I2C1_SLAVE_READ_SET_POINTER);
}
 
}
else if((I2C1PIRbits.ADRIF)) // ADDRESS interrupt flag (and and not a READ => WRITE)
{
I2C1PIRbits.ADRIF=0;
PIR3bits.I2C1IF=0;
// callback routine should prepare to receive data from the master
I2C1_StatusCallback(I2C1_SLAVE_WRITE_REQUEST);
}
else // a write and this is the DATA
{
I2C1_slaveWriteData = I2C1_data; // transfer the copy of the register to a global variable for treatment by callbacks
 
// callback routine should process I2C1_slaveWriteData from the master
I2C1_StatusCallback(I2C1_SLAVE_WRITE_UNDERWAY);
}
I2C1CON0bits.CSTR=0; // clock stretching....
 
}
 
 
 

 
In datasheet page 554, step 8 of slave reception, it does say:
 
If there are any previous error conditions, e.g. Receive buffer overflow or transmit buffer under- flow errors, Slave will force a NACK and the module becomes Idle. 
However there are no other bits set in ERRbits suggesting anything wrong. And there is no equivalent paragraph in the text on Slave Transmission, where I get the same NACK problem after address match.
举报

何元

2018-11-28 17:51:12
仍然试图理解为什么在地址匹配之后进行打盹。P597数据表:NACKIF:NACK检测中断标志位1=何时(SMA=1μm MMA=1),并且在BxNACKIF上检测到NACK也设置在任何TXWRE、RXRDE、TXUF、RXOVR位被设置时。0=NACK没有设置NACK/Debug检测码。发送不匹配的从属AddiSerStSU和RXO(TXUF和RXOVR是上面给出的不正确名称)在CON1中,而不是STEXXWE,RXRE(TXWRE和RXRDE似乎也是不正确的名称)在STAT1中,也没有看到它们被设置。在从接收(7位寻址)描述中模式)在P55中没有提到在接收到地址之后读取缓冲器的任何义务(为了清除它)。这不是我习惯的。MCC生成的代码不尝试这样做。我尝试了在清除ADRIF等之后——读取Adress缓冲区并授权ACK:I2C1YODATA=I2C1ADB0;I2C1CON1BITS.ACKDT=1;但这似乎不起作用。(对我来说没有圣诞节。

以上来自于百度翻译


      以下为原文

    Still trying to understand why Nacking after an address match.
 
p587 datasheet:
NACKIF: NACK Detect Interrupt Flag bit
1= When(SMA=1||MMA=1)and a NACK is detected on the bus
NACKIF is also set when any of the TXWRE, RXRDE, TXUF, RXOVR bits are set.
0 = No NACK/Error detected
NACKIF is not set by the NACK send for non-matching slave addresses 
 
TXU and RXO (TXUF and RXOVR are incorrect names given above) are in CON1 and are not being set
TXWE and RXRE (TXWRE and RXRDE seem to be incorrect names too) are in STAT1 and don't see them being set either.
 
In the description of Slave Reception (7-bit Addressing Mode) on p554 there's no mention of any obligation to read a buffer AFTER an address has been received (in order to clear it). Which is not what I'm used to. The MCC generated code doesn't try to do that.
 
I tried - after clearing ADRIF etc. - reading the Adress buffer and authorising an ACK:
 
I2C1_data = I2C1ADB0; 
I2C1CON1bits.ACKDT = 1;
 
But that didn't seem to work. ;(
 
No Christmas for me.
举报

更多回帖

发帖
×
20
完善资料,
赚取积分