Electronic Circuits and Projects Forum



languer

I2C Monitor– Implementation and Limitations

by languer , 13th March 2012 at 05:52 AM (1806 Views)
I2C Monitor– Implementation and Limitations

The implementation is shown on the next figure. For the quick prototype, the FTDI interface was replaced with the FTDI TTL cable. The implementation worked as expected with two caveats; the maximum bus supported speed is 100kHz, and if the internal buffer on the MCU overflows there is currently no indication for this. I was hoping to be able to operate up to 400kHz, but it’s not happening. Since this is good enough for what I targeted originally, it will suffice until next time. It looks like this is better suited for an FPGA application – live and learn I guess. Code is written in Oshonsoft Basic.

i2c monitor.png

Code
Code :
'Author: languer (©2012)
'Pin Allocation:
	'PIN# Main_Fn                 Secondary_Fn
	'RA0 -> not used
	'RA1 -> not used
	'RA2 -> not used
	'RA3 -> not used
	'RA4 -> not used
	'RA5 -> MCLR
	'RA6 -> OSC
	'RA7 -> OSC
	'RB0 -> I2C START Interrupt
	'RB1 -> TX_RS232 (PC_RX)
	'RB2 -> I2C STOP Interrupt
	'RB3 -> I2C SCL Interrupt (using CCP)
	'RB4 -> RX_RS232 (PC_TX)
	'RB5 -> not used
	'RB6 -> I2C SDA               PGC (Programming clock)
	'RB7 -> CTS#                  PGD (Programming data)
'Usage Information:
	'RS232 Baud Rate: 115.2kbps
'Version Info:
		'rs232 comms on array at main loop
		'max speed is 100kHz
		'no indication if buffer overflows
 
'General Configuration
'for external 10MHz w PLL (40MHz)
	Define CONFIG1L = 0x00
	Define CONFIG1H = 0x06
	Define CONFIG2L = 0x0a
	Define CONFIG2H = 0x00
	Define CONFIG3L = 0x00
	Define CONFIG3H = 0x80
	Define CONFIG4L = 0x80
	Define CONFIG4H = 0x00
	Define CONFIG5L = 0x03
	Define CONFIG5H = 0xc0
	Define CONFIG6L = 0x03
	Define CONFIG6H = 0xe0
	Define CONFIG7L = 0x03
	Define CONFIG7H = 0x40
 
'Oscillator/Clock Configuration
	Define CLOCK_FREQUENCY = 40
 
'HW UART Setup
	Hseropen 115200
 
'I2C Definitions
	Symbol io_i2cstart = RB0
	Symbol io_i2cstop = RB2
	Symbol io_i2cscl = RB3
	Symbol io_i2csda = RB6
 
'Constants
	Const trisa1 = %11111111
	Const trisb1 = %01111101
	Dim _true As Bit
	Dim _false As Bit
	_true = True
	_false = False
 
'Variables
	Dim flag_i2cstart As Bit
	Dim flag_i2cstop As Bit
	Dim i2cack As Byte
	Dim i2cdata As Byte
	Const i2cbuffersize = 200
	Dim i2carray(200) As Byte
	Dim i2cnextin As Byte
	Dim i2cnextout As Byte
	Dim bitcount As Byte
 
'Main Program
main:
	WaitMs 2500
	Call init()
 
	'enable interrupt routines
	INTCON.INT0IE = True  'enable RB0/I2CSTART interrupt
	CCP1CON = %00000101  'enable RB3/CCP1/I2CSCL
	Enable High  'enable general interrupt
 
	Dim data As Byte
	Dim cnt As Byte
	While _true
		If i2cnextout = i2cnextin Then
			'do nothing
		Else
			'loop-around buffer
			If i2cnextout = i2cbuffersize Then
				i2cnextout = 0
			Endif
			'hserout when TXREG is empty
			If PIR1.TXIF = True Then
				data = i2carray(i2cnextout)
				TXREG = data
				i2cnextout = i2cnextout + 1
			Endif
		Endif
	Wend
End                                               
 
Proc init()
	AllDigital
	TRISA = trisa1
	TRISB = trisb1
 
	flag_i2cstart = False
	flag_i2cstop = False
	i2cack = 0
	i2cdata = 255
	i2cnextin = 0
	i2cnextout = 0
	bitcount = 0
 
	'Hserout "Start...", CrLf
End Proc                                          
 
On High Interrupt
	Dim hex1 As Byte
	Dim hex2 As Byte
 
	'START/RESTART Condition (3.6us / 29Tcy)
	If INTCON.INT0IF = True Then  'RB0/I2CSTART flag
		INTCON.INT0IF = False  'RB0/I2CSTART flag
		INTCON3.INT2IF = False  'RB2/I2CSTOP flag
		INTCON3.INT2IE = True  'enable RB2/I2CSTOP interrupt
		flag_i2cstop = False
		bitcount = 0
		PIR1.CCP1IF = False  'RB3/CCP/I2CSCL  flag
		PIE1.CCP1IE = True  'enable RB3/CCP/I2CSCL interrupt
		INTCON.PEIE = True  'enable peripheral interrupt (required for RB3/CCP/I2CSCL)
		'loop-around buffer
		If i2cnextin = i2cbuffersize Then
			i2cnextin = 0
		Endif
		If flag_i2cstart = True Then
			i2carray(i2cnextin) = "R"  'restart condition"
		Else
			flag_i2cstart = True
			i2carray(i2cnextin) = "S"  'start condition
		Endif
		i2cnextin = i2cnextin + 1
	Endif
 
	'STOP Condition (3.0us / 24Tcy)
	If INTCON3.INT2IF = True Then  'RB2/I2CSTOP flag
		INTCON3.INT2IE = False  'disable RB2/I2CSTOP interrupt
		INTCON3.INT2IF = False  'RB2/I2CSTOP flag
		INTCON.PEIE = False  'disable peripheral interrupt (required for RB3/CCP/I2CSCL)
		PIE1.CCP1IE = False  'disable RB3/CCP/I2CSCL interrupt
		PIR1.CCP1IF = False  'RB3/CCP/I2CSCL flag
		flag_i2cstart = False
		'loop-around buffer
		If i2cnextin = i2cbuffersize Then
			i2cnextin = 0
		Endif
		i2carray(i2cnextin) = "P"  'stop condition
		i2cnextin = i2cnextin + 1
	Endif
 
	'DATA Condition
	'(2.4us / 18Tcy for Bits 0-6)
	'(7.2us / 55Tcy for Bit 7)
	'(7.4us / 58Tcy for ACK/NACK)
	If PIR1.CCP1IF = True Then  'RB3/CCP/I2CSCL flag
		PIR1.CCP1IF = False  'RB3/CCP/I2CSCL flag
		Select Case bitcount
		Case < 7
			'shift data left and add new i2cdata bit
			'i2cdata = ShiftLeft(i2cdata, 1)
			ASM:        RLCF i2cdata,1
			If io_i2csda = True Then  'add
				i2cdata = i2cdata + 1
			Endif
			bitcount = bitcount + 1
		Case 7
			'shift data left and add last i2cdata bit
			'i2cdata = ShiftLeft(i2cdata, 1)
			ASM:        RLCF i2cdata,1
			If io_i2csda = True Then  'add
				i2cdata = i2cdata + 1
			Endif
			bitcount = bitcount + 1
			'store I2CDATA
			'loop-around buffer
			'hex1 = ShiftRight(i2cdata, 4)
			ASM:        movff i2cdata,hex1
			ASM:        movf hex1,w
			ASM:        andlw 0xf0
			ASM:        movwf hex1
			ASM:        RRNCF hex1,1
			ASM:        RRNCF hex1,1
			ASM:        RRNCF hex1,1
			ASM:        RRNCF hex1,1
			hex1 = LookUp("0123456789ABDCEF"), hex1
			'hex2 = i2cdata And 0x0f
			ASM:        movff i2cdata,hex2
			ASM:        movlw 0x0f
			ASM:        andwf hex2,1
			hex2 = LookUp("0123456789ABDCEF"), hex2
		Case Else
			'ACK/NACK bit
			If i2cnextin = i2cbuffersize Then
				i2cnextin = 0
			Endif
			i2carray(i2cnextin) = hex1
			i2cnextin = i2cnextin + 1
			If i2cnextin = i2cbuffersize Then
				i2cnextin = 0
			Endif
			i2carray(i2cnextin) = hex2
			i2cnextin = i2cnextin + 1
 
			bitcount = 0
 
			'store ack/nack STATUS
			If io_i2csda = True Then  'test for ACK/NACK
				i2cack = "A"
			Else
				i2cack = "N"
			Endif
			'loop - around buffer
			If i2cnextin = i2cbuffersize Then
				i2cnextin = 0
			Endif
			i2carray(i2cnextin) = i2cack
			i2cnextin = i2cnextin + 1
 
		EndSelect
	Endif
 
Resume
Attached Thumbnails Attached Images

Comments

Electronic Circuits  |  Learning Electronics

Join our community with over 100,000 Members! It's free, easy and when you're logged in you have many more features! Click to register.
Page Time: 0.07966 seconds      Memory: 7,818 KB      Queries: 25      Templates: 0