PDA

View Full Version : HI2CREAD for 18Fs



Charles Linquis
- 25th October 2008, 20:22
I have seen several examples of hardware I2C slaves on this forum. When I try to implement them, they never work. Most of the code is for 16F devices, which I avoid like the plague. I'm sure the problem is in front of my keyboard, but realizing that doesn't get my project working.

Is anyone willing to provide me with a block of tested code for 18Fs?

BigWumpus
- 25th October 2008, 23:20
I have an 18F252 as a I2C-Slave in PBP using ASM-code for the I2C-interrupts.
OK ?

Charles Linquis
- 26th October 2008, 00:41
I'm happy that you have that code... Would you care to share, or is it in some 'public' place already?

bcd
- 26th October 2008, 11:35
I'd also love to see that. Getting my hands dirty with HW I2C isn't quite as much fun as I though it might be...

bill.

BigWumpus
- 26th October 2008, 13:42
Hello,

find attached my code (2 years old and not the best!).
I have removed the maincode.
I2C reads in bytes and fills up a buffer I2C_In.
The maincode generates data in a second buffer I2C_Out.

The incoming bytes are only single bytes, I don't know if the routine will manage more than 1 data in a message.

Just read the code and try to understand the statemachine of the I2C-hardware.

Charles Linquis
- 26th October 2008, 15:43
Thanks! And fortunately for me - my wife speaks German!

DaveC3
- 26th October 2008, 22:31
Here is a little program that drives a LCD as a I2C slave




*
'* Version : 1.0 *
'* Notes : PIC 18F4550 *
'* : *
'************************************************* ***************
define LOADER_USED 1
define RESET_ORG 800h
define INTERRUPT_ORG 808h
DEFINE OSC 48



'**** LCD ************************************************** *****
'Set LCD Data port
DEFINE LCD_DREG PORTA
'Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_DBIT 0
'Set LCD Register Select port
DEFINE LCD_RSREG PORTA
'Set LCD Register Select bit
DEFINE LCD_RSBIT 4
'Set LCD Enable port
DEFINE LCD_EREG PORTA
'Set LCD Enable bit
DEFINE LCD_EBIT 5
'LCD RW Register PORT
'DEFINE LCD_RWREG PORTB
'LCD read/write pin bit
'DEFINE LCD_RWBIT 5
'Set LCD bus size (4 or 8 bits)
DEFINE LCD_BITS 4
'Set number of lines on LCD
DEFINE LCD_LINES 2
'Set command delay time in us
DEFINE LCD_COMMANDUS 2000
'Set data delay time in us
DEFINE LCD_DATAUS 50

' Initialize ports and directions
ADCON1 = $F 'port A digital
CMCON = 7 'PortA Digital
' PicBasic Pro I2C slave program
' Alias pins
scl VAR PORTB.1 ' I2C clock input
sda VAR PORTB.0 ' I2C data input

' Define used register flags
SSPIF VAR PIR1.3 ' SSP (I2C) interrupt flag
BF VAR SSPSTAT.0 ' SSP (I2C) Buffer Full
R_W VAR SSPSTAT.2 ' SSP (I2C) Read/Write
D_A VAR SSPSTAT.5 ' SSP (I2C) Data/Address
CKP VAR SSPCON1.4 ' SSP (I2C) SCK Release Control
SSPEN VAR SSPCON1.5 ' SSP (I2C) Enable
SSPOV VAR SSPCON1.6 ' SSP (I2C) Receive Overflow Indicator
WCOL VAR SSPCON1.7 ' SSP (I2C) Write Collision Detect

' Define constants
I2Caddress CON $A2 ' Make our address 2

' Allocate RAM
result VAR BYTE ' ADC result
datain VAR BYTE ' Data in
dataout VAR BYTE[8] ' Data out array
readcnt VAR BYTE ' I2C read count

readcnt = 0 ' Zero counter

pause 500
lcdout $FE,1," I2C LCD"
lcdout $FE,$C0," Ready"
trisb = %00000000
portb.0 = 0
portb.1 = 0
TRISB = %11111111
'pause 500

' Initialize I2C slave mode
SSPADD = I2Caddress ' Set our address
SSPCON2 = $0 ' General call address disabled
SSPCON1 = $36 ' Set to I2C slave with 7-bit address
GoTo mainloop ' Skip over subroutines

i2cslave: ' I2C slave subroutine
SSPIF = 0 ' Clear interrupt flag
IF R_W = 1 Then goto i2crd ' Read data from us
IF BF = 0 Then goto i2cexit ' Nothing in buffer so exit
IF D_A = 1 Then goto i2cwr ' Data for us (not address)
IF SSPBUF != I2Caddress Then goto i2cexit ' Clear the address from the buffer
readcnt = 0 ' Mark as first read
GoTo i2cexit

i2cwr: ' I2C write data to us
datain = SSPBUF ' Put data into array
lcdout datain
GoTo i2cexit

i2crd: ' I2C read data from us
IF D_A = 0 Then
readcnt = 0 ' Mark as first read
EndIF
SSPBUF = dataout[readcnt] ' Get data from array
CKP = 1 ' Release SCL line
readcnt = readcnt + 1 ' Move along read count
GoTo i2cexit ' That's it
i2cexit:
Return

mainloop: ' Main program loop
IF SSPIF = 1 Then ' Check for I2C interrupt flag
GoSub i2cslave

EndIF
GoTo mainloop ' Do it all forever



I think I found this on this forum.

aa222k
- 26th October 2008, 22:53
Thanks so much

Charles Linquis
- 27th October 2008, 01:21
And thanks from me as well. I'm certain I can get something working now.

bcd
- 27th October 2008, 09:50
Thanks for both those examples - that should help a lot.

bill.