I read that all i2c libraries now have a timout. How do you use that? Is it a setting?
(my code still hangs if the i2c bus has problems, not acceptable...)
i2c timeout
Re: i2c timeout
I tried to build muy own (non-blocking) i2c library, but somehow it doesn't work. (for the PIC24FJ256GA108, i2c port #1):
(AFAIK I've followed the guidlines in the Microchip AN's)
(AFAIK I've followed the guidlines in the Microchip AN's)
Code: Select all
module __lib_i2c_nb
Const I2CTimeOut = 100
Sub Procedure I2CInit()
Sub Function I2CStart() As Byte
Sub Function I2CRestart() As Byte
Sub Function I2CIdle() As Byte
Sub Function I2CRead(Dim pAck As Byte) As Byte
Sub Function I2CWrite(Dim pDat As Byte) As Byte
Sub Function I2CStop() As Byte
Sub Procedure I2CClose()
implements
'--------------------------------------------------------------------------------------------------
Sub Procedure I2Cinit()
'--------------------------------------------------------------------------------------------------
I2CEN_bit = 1
I2C1BRG = 37
End Sub
'--------------------------------------------------------------------------------------------------
Sub Function I2CStart() As Byte ' OK
'--------------------------------------------------------------------------------------------------
Result = I2CIdle()
If Result Then SEN_bit = 1 End If
End Sub
'--------------------------------------------------------------------------------------------------
Sub Function I2CRestart() As Byte ' OK
'--------------------------------------------------------------------------------------------------
Result = I2CIdle()
If Result Then delay_us(10) RSEN_bit = 1 End If
End Sub
'--------------------------------------------------------------------------------------------------
Sub Function I2CIdle() As Byte ' OK
'--------------------------------------------------------------------------------------------------
Dim lCnt As Byte
For lCnt = 0 To I2CTimeOut
If (I2C1Con And 0x001F) = 0 Then Break End If
delay_us(5)
Next lCnt
Result = (I2C1Con And 0x1F) Xor 1
End Sub
'--------------------------------------------------------------------------------------------------
Sub Function I2CRead(Dim pAck As Byte) As Byte ' OK
'--------------------------------------------------------------------------------------------------
If I2CIdle() Then
delay_us(10)
RCEN_bit = 1
If I2CIdle Then
Result = I2C1RCV
If I2CIdle() Then
If pAck Then ACKDT_bit = 0 Else ACKDT_bit = 1 End If
ACKEN_bit = 1
I2CIdle()
End If
End If
End If
End Sub
'--------------------------------------------------------------------------------------------------
Sub Function I2CWrite(Dim pDat As Byte) As Byte ' OK
'--------------------------------------------------------------------------------------------------
Result = I2CIdle()
If Result Then delay_us(10) I2C1TRN = pDat End If
End Sub
'--------------------------------------------------------------------------------------------------
Sub Function I2CStop() As Byte ' OK
'--------------------------------------------------------------------------------------------------
Result = I2CIdle()
If Result Then delay_us(10) PEN_bit = 1 End If
End Sub
'--------------------------------------------------------------------------------------------------
Sub Procedure I2CClose() ' OK
'--------------------------------------------------------------------------------------------------
I2CEN_bit = 0
End Sub
end.
Regards,
Peter.
Peter.
- dusan.poluga
- mikroElektronika team
- Posts: 780
- Joined: 02 Feb 2017 14:21
Re: i2c timeout
Hi,
It stops at the function because when you debug your code it is easier to find where your code isn't working.
Most times it stops at the i2c function when the i2c bus address is wrong or when you do not receive the ACK signal from the chip you are trying to talk to.
Regards,
It stops at the function because when you debug your code it is easier to find where your code isn't working.
Most times it stops at the i2c function when the i2c bus address is wrong or when you do not receive the ACK signal from the chip you are trying to talk to.
Regards,
Dusan Poluga.
Re: i2c timeout
Yes,
But I read that the 7.0 libraries have a time out on errors? (it doesn't work here...)
Without a time-out your whole application is dead/frozen if a bus error occurs, that's not acceptable in most cases...
But I read that the 7.0 libraries have a time out on errors? (it doesn't work here...)
Without a time-out your whole application is dead/frozen if a bus error occurs, that's not acceptable in most cases...
Regards,
Peter.
Peter.
- dusan.poluga
- mikroElektronika team
- Posts: 780
- Joined: 02 Feb 2017 14:21
Re: i2c timeout
Hi,
I have tested this with a couple click boards but did not come across a timeout error.
Only time the error gets presented when i make an error by changing the i2c address to something that does not exist on the bus or i unplug the board from the bus.
Regards,
I have tested this with a couple click boards but did not come across a timeout error.
Only time the error gets presented when i make an error by changing the i2c address to something that does not exist on the bus or i unplug the board from the bus.
Regards,
Dusan Poluga.
Re: i2c timeout
I had a broken pull-up resistor on the i2c bus, this will hang the system indefinitely.
Whatever error occurs on the i2c bus, the system should never hang.
(you can't even warn the user in that case that something is wrong)
Working non-blocking version (I2C1, 16MHz Fcy, 400kHz i2c, i2cstatus holds errors on exit):
Whatever error occurs on the i2c bus, the system should never hang.
(you can't even warn the user in that case that something is wrong)
Working non-blocking version (I2C1, 16MHz Fcy, 400kHz i2c, i2cstatus holds errors on exit):
Code: Select all
module lib_i2c
Const I2CTimeOut = 200
Dim I2cStatus As Byte
'Statusbits: 00000001 - Start
' 00000010 - Restart
' 00000100 - Stop
' 00001000 - Write
' 00010000 - Read
' 00100000 - Idle
' 01000000 - Receive buffer
Sub Procedure I2CInit()
Sub Procedure I2CStart()
Sub Procedure I2CRestart()
Sub Procedure I2CStop()
Sub Procedure I2CWrite(Dim pDat As Byte)
Sub Procedure I2CIdle()
Sub Function I2CRead(Dim pAck As Byte) As Byte
implements
'==================================================================================================
Sub Procedure I2CIdle() 'Wait for bus idle
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
For lCnt = 0 To I2CTimeout '
If (I2C1CON And 0x1F) = 0 then break end if '
Next lCnt '
I2cStatus.5 = (I2C1CON And 0x1F) '
End Sub '
'==================================================================================================
Sub Procedure I2Cinit() 'Init I2C1 peripheral (400kHz)
'--------------------------------------------------------------------------------------------------
I2C1BRG = 0x0025 '(Fcy/scl)-(Fcy/10000000) -1
I2CEN_Bit = 1 'Enable I2C1
Delay_ms(10) '
I2C1STAT = 0 '
End Sub '
'==================================================================================================
Sub Procedure I2CStart() 'Start bus
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
I2CIdle() 'Wait for bus idle
SEN_Bit = 1 'Set start bit
For lCnt = 0 To I2CTimeout 'Wait for bit to clear
If (SEN_Bit = 0) Then Break End If '
Next lCnt '
I2cStatus = SEN_bit 'Errorstatus
End Sub '
'==================================================================================================
Sub Procedure I2CRestart() 'Restart bus
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
I2CIdle() 'Wait for bus idle
RSEN_Bit = 1 'Set repeated start bit
For lCnt = 0 To I2CTimeout 'Wait for bit to clear
If (RSEN_Bit = 0) Then Break End If '
Next lCnt '
I2cStatus.1 = RSEN_bit 'Errorstatus
End Sub '
'==================================================================================================
Sub Procedure I2CStop() 'Stop bus
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
I2CIdle() 'Wait for bus idle
PEN_Bit = 1 'Set stop bit
For lCnt = 0 To I2CTimeout 'Wait for bit to clear
If (PEN_Bit = 0) Then Break End If '
Next lCnt '
I2cStatus.2 = PEN_Bit 'Errorstatus
End Sub '
'==================================================================================================
Sub Procedure I2CWrite(Dim pDat As Byte) 'Write byte pDat to bus
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
I2CIdle() 'Wait for bus idle
MI2C1IF_Bit = 0 'Clear interruptflag
I2C1TRN = pDat 'Data to send into buffer
For lCnt = 0 To I2CTimeout 'Wait for interruptflag to
If MI2C1IF_bit Then Break End If 'get set
Next lCnt '
I2cStatus.3 = MI2C1IF_Bit Xor 1 'Errorstatus
End Sub
'==================================================================================================
Sub Function I2CRead(Dim pAck As Byte) As Byte 'Read byte of bus(1=Nack/0=Ack)
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
I2CIdle() 'Wait for bus idle
MI2C1IF_Bit = 0 'Clear interruptflag
RCEN_Bit = 1 '
For lCnt = 0 To I2cTimeout 'Wait for buffer
If RBF_Bit Then Break End If '
Next lCnt '
I2cStatus.6 = RBF_Bit Xor 1 'Errorstatus
Result = I2C1RCV 'Get received byte
ACKDT_Bit = pAck 'Send Ack/Nack
ACKEN_Bit = 1 '
For lCnt = 0 To I2CTimeout '
If MI2C1IF_Bit Then Break End If '
Next lCnt '
I2cStatus.4 = MI2C1IF_Bit Xor 1 'Errorstatus
End Sub '
end.
'==================================================================================================
Last edited by arco on 14 Mar 2017 18:00, edited 1 time in total.
Regards,
Peter.
Peter.
- dusan.poluga
- mikroElektronika team
- Posts: 780
- Joined: 02 Feb 2017 14:21
Re: i2c timeout
Hi,
Yes you are correct. The system should not stop working.
Our libraries are written for ease of use and for ease for debugging.
For that some sacrifices need to be made.
Regards,
Yes you are correct. The system should not stop working.
Our libraries are written for ease of use and for ease for debugging.
For that some sacrifices need to be made.
Regards,
Dusan Poluga.
Re: i2c timeout
Sacrifices aren't nessecairy. My code is non-blocking and sets errorflags if something goes wrong...
Regards,
Peter.
Peter.
- dusan.poluga
- mikroElektronika team
- Posts: 780
- Joined: 02 Feb 2017 14:21
Re: i2c timeout
Hi,
Yes that is one way of solving the problem.
Thank you for sharing.
Regards,
Yes that is one way of solving the problem.
Thank you for sharing.
Regards,
Dusan Poluga.