I will be interested in your port to the 18F series, and it sounds like you will be willing to post your code. I have an upcoming project that will need it. I tried to get Soubie's code working about a year ago with no luck.
I will be interested in your port to the 18F series, and it sounds like you will be willing to post your code. I have an upcoming project that will need it. I tried to get Soubie's code working about a year ago with no luck.
Charles Linquist
Charles,
same problem, i also never got his code working.
I come back next week, hope with a working code.
Regards,
Ralf
Guys,
I've been working this problem for nearly a year now. I've tried Soubie's code with no luck, and the code from this thread isn't working either. I'm using the 18F4620 as the master talking to an 18F2620, the little brother of the 4620 as the slave. I've RTFM to the point I can recite it, and the Errata sheets, and I've tried countless logical, and even illogical options to trying to get it working.
The best I can get so far is the master sends the address byte and the slave accepts it when it matches its own address and ignores addresses not matching its own. When the address matches, the slave sets the Buffer Full and the Interrupt Flags, but for some reason won't send an ACK back to the master (at least that's what this thread's code [and my own polls of the master's ACK flag] are saying). I've made sure to clear all flags as the datasheet clearly directs, and still no luck. If the slave would ACK, the master would send the next byte and so on.
I'm operating both chips on their internal crystal (8 MHz) and using the 4x PLL (= 32MHz). Before you go there, I'm already successfully talking to an I2C real-time clock chip with no problems and I'm saving data to an external I2C EEPROM regularly with no problems. The I2C network is working with the PICs at 32 MHz. I'm on the right pins; I'm using the pull external pull-up resistors...
I've had this exact hardware working in the past when using MikroElektronika Basic, but I'm much happier in PBP. This one problem is holding up the entire project. Trying to get two 18F's to ping-pong data back and forth is a killer.
If someone has even a bit more success than what I've had, please post it and maybe together we can chip away at this challenge.
Well, the code provided by Al (aratti) and the one I posted works great both ways!
I don't know what to tell you without looking at your code, but I modified the one provided by Al just a little and worked right away!
Can you post your code? Maybe we can see something that you're not seeing.
I'll be able to devote some time to a group project in about two weeks. I will also have another issue - I'm forced to work with 10-bit addresses.
Charles Linquist
Here's my slave code that's not sending back the ACK. I appologize for the "dead code" and commented out parts in advance. Maybe you'll see something I'm missing...
Robert
----------------
Code:'Oscillator Initialization DEFINE OSC 32 ' Osc. in MHz OSCCON = %01110000 OSCTUNE.6 = 1 ADCON0.0 = 0 ' Turns off A-to-D module ADCON1 = $0F ' Makes 100% port A digital TRISA = %00000000 CMCON = 7 ' Comparators Off DEFINE I2C_HOLD 1 'DEFINE I2C_SLOW 1 ' Define used register flags SSPIF VAR PIR1.3 ' SSP (I2C) interrupt flag SSPIE VAR PIE1.3 ' SSP Int Enable 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 'STRETCH VAR SSPCON2.0 ' SSP (I2C) Clock stretch A var byte ' my counter variable for testing '---------------- Alias pins ----------------------------------- TRISC.3 = 1 ' input TRISC.4 = 1 ' input '--------------- Define used register flags ------------------- 'STAT_BF VAR SSPSTAT.0 ' SSP (I2C) Buffer Full 'STAT_RW VAR SSPSTAT.2 ' SSP (I2C) Read/Write 'STAT_DA VAR SSPSTAT.5 ' SSP (I2C) Data/Address CKE VAR SSPSTAT.6 ' SSP (I2C) Data/Address '------------------- Rx Buffer definition -------------------- RxBufferLEN con 3 RxBuffer var byte[Rxbufferlen] RxBufferIndex var byte '------------------ Tx Buffer definition ---------------------- TxBufferLEN con 3 TxBuffer var byte[txbufferlen] TxBufferIndex var byte '------------------ Define constants ------------------------ 'I2Caddress CON $2 ' Make address = 2 I2Caddress CON $06 ' Make address = 2 ' Define constants U8 var byte U17 var byte InByte var byte OutByte var byte readcnt VAR BYTE 'U8 = $06 U17 = $08 'STRETCH = 1 WRData var byte ' Initialize I2C slave mode 'SSPCON2 = 0 ' General call address disabled 'SSPADD = My_I2C_address ' Set our address SSPADD = I2Caddress ' Set our address SSPCON2.7 = 0 ' General call address disabled SSPCON1 = $36 ' Set to I2C slave with 7-bit address SSPSTAT = 0 SSPIE = 1 SSPIF = 0 RxBufferIndex = 0 TxBufferIndex = 0 bf = 0 SSPOV = 0 'Port C harware UART settings DEFINE HSER_RCSTA 90h DEFINE HSER_TXSTA 20h DEFINE HSER_BAUD 9600 DEFINE HSER_CLROERR 1 '----------------- Initialization Done! ----------------------------- rxbuffer[0] = 0 rxbuffer[1] = 0 rxbuffer[2] = 0 GoTo main I2C_Slave: ' I2C slave subroutine hserout ["SSPIF = ",#SSPIF," BF = ",#bf,13,10] hserout ["R_W = ",#R_w," D_A = ",#D_A,13,10] hserout ["SSPBUF = ",#SSPBUF,13,10] SSPIF = 0 ' Clear interrupt flag SSPov = 0 ' Clear interrupt flag bf = 0 ' clear buffer full IF R_W = 1 Then hserout ["R_W = 1, Read data from U8",13,10] goto I2C_Read ' Read data from us endif IF SSPBUF = I2Caddress Then hserout ["It's to me! ",#SSPBUF," = ",#I2Caddress,13,10] endif IF D_A = 1 Then hserout ["Data (not address)",13,10] goto I2C_Write ' Data for us (not address) endif GoTo I2C_Exit I2C_Write: ' I2C write data to us InByte = SSPBUF ' Put buffer data into array Rxbuffer[Rxbufferindex] = InByte rxbufferindex = rxbufferindex + 1 hserout ["SSPBUF Write = ",#SSPBUF,13,10] GoTo i2c_exit I2C_Read: ' I2C read data from us hserout ["SSPBUF Read = ",#SSPBUF,13,10] IF D_A = 0 Then TxBufferIndex = 0 EndIF while BF : wend ' loop while buffer is full wcol = 0 ' clear collision flag SSPBUF = TxBuffer[TxBufferIndex] while wcol wcol = 0 SSPBUF = TxBuffer[TxBufferIndex] wend hserout ["SSPBUF Outbyte = ",#SSPBUF," should be outbyte 16 or 31",13,10] CKP = 1 ' release clock, allowing read by master TxBufferIndex = TxBufferIndex + 1 ' increment index if TxBufferIndex = TxBufferlen then ' all bytes have been tx TxBufferIndex = 0 ' reset index endif I2C_Exit: Return main: pause 300 hserout [13,10,"Start of program U8",13,10] hserout ["RxBuffer = "] for a = 0 to 2 hserout [dec rxbuffer[a]," "] next a hserout [13,10] loop: ' IF SSPIF = 1 Then IF BF = 1 Then hserout [13,10,"Went into I2C_Slave routine",13,10] GoSub i2c_slave hserout ["RxBuffer = "] for a = 0 to 2 hserout [dec rxbuffer[a]," "] next a hserout [13,10] hserout ["SSPCON1 = ",hex sspcon1," ",bin sspcon1,13,10] hserout ["SSPCON2 = ",hex sspcon2," ",bin sspcon2,13,10] hserout ["SSPSTAT = ",hex sspstat," ",bin sspstat,13,10] hserout ["SSPBUF = ",#sspbuf,13,10] if rxbufferindex = RxBufferLEN then ' end of buffer transfer WrData = 1 rxbufferindex = 0 rxbuffer[0] = 0 rxbuffer[1] = 0 rxbuffer[2] = 0 hserout ["RxBuffer Cleared = "] for a = 0 to 2 hserout [dec rxbuffer[a]," "] next a hserout [13,10] endif endif SSPOV = 0 WCOL = 0 IF RxBuffer[0] = 15 Then hserout ["Got a 15",13,10] hserout [" Readcount is: ",#readcnt,13,10] hserout ["Have a 16 to send if asked",13,10] TxBuffer[0] = 16 EndIF IF RxBuffer[0] = 30 Then hserout ["Got a 30",13,10] hserout [" Readcount is: ",#readcnt,13,10] hserout ["Have a 31 to send if asked",13,10] TxBuffer[0] = 31 EndIF WrData=0 pause 50 GoTo loop End
Last edited by ScaleRobotics; - 22nd October 2010 at 13:24. Reason: added code tags
One thing I learn these days is that you cannot mess with the I2C timing.
Looking at your code, I guess those hserouts are killing the protocol.
I'll take a closer look at everything else tomorrow.
Try this code, I cleaned it up a lot. Slave address is 2.
1) From the master, try to read 12 from the slave
2) Try to send one byte (zero) to the slave and do something.
I don't have MPASM so, it could be some small errors, check them.
Code:'Oscillator Initialization DEFINE OSC 32 ' Osc. in MHz OSCCON = %01110000 OSCTUNE.6 = 1 ADCON0.0 = 0 ' Turns off A-to-D module ADCON1 = $0F ' Makes 100% port A digital TRISA = %00000000 CMCON = 7 ' Comparators Off DEFINE I2C_HOLD 1 ' Define used register flags SSPIF VAR PIR1.3 ' SSP (I2C) interrupt flag SSPIE VAR PIE1.3 ' SSP Int Enable 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 'STRETCH VAR SSPCON2.0 ' SSP (I2C) Clock stretch '---------------- Alias pins ----------------------------------- TRISC.3 = 1 ' input TRISC.4 = 1 ' input '--------------- Define used register flags ------------------- STAT_BF VAR SSPSTAT.0 ' SSP (I2C) Buffer Full STAT_RW VAR SSPSTAT.2 ' SSP (I2C) Read/Write STAT_DA VAR SSPSTAT.5 ' SSP (I2C) Data/Address CKE VAR SSPSTAT.6 ' SSP (I2C) Data/Address '------------------- Rx Buffer definition -------------------- RxBufferLEN CON 1 RxBuffer VAR BYTE[Rxbufferlen] RxBufferIndex VAR BYTE '------------------ Tx Buffer definition ---------------------- TxBufferLEN CON 1 TxBuffer VAR BYTE[txbufferlen] TxBufferIndex VAR BYTE '------------------ Define constants ------------------------ I2Caddress CON $2 ' Make address = 2 ' Define constants datain VAR BYTE readcnt VAR BYTE WRData VAR BYTE 'SSPADD = My_I2C_address ' Set our address SSPADD = I2Caddress ' Set our address SSPCON2.7 = 0 ' General call address disabled SSPCON1 = $36 ' Set to I2C slave with 7-bit address SSPSTAT = 0 SSPIE = 1 SSPIF = 0 RxBufferIndex = 0 TxBufferIndex = 0 bf = 0 SSPOV = 0 'Port C harware UART settings DEFINE HSER_RCSTA 90h DEFINE HSER_TXSTA 20h DEFINE HSER_BAUD 9600 DEFINE HSER_CLROERR 1 '----------------- Initialization Done! ----------------------------- GoTo main '------------------------------------------------------------------------------- I2C_Slave: ' I2C slave subroutine sspif = 0 ' clear interrupt flag IF r_w = 1 Then I2C_Read ' read data from us IF bf = 0 Then I2C_Exit ' nothing in buffer so exit IF d_a = 1 Then I2C_Write ' data for us (not address) IF sspbuf != i2caddress Then I2C_Exit ' clear the address from the buffer readcnt = 0 ' mark as first read GoTo I2C_Exit '------------------------------------------------------------------------------- I2C_Write: ' I2C write data to us datain = sspbuf ' put buffer data into array rxbuffer[rxbufferindex] = datain rxbufferindex=rxbufferindex + 1 IF rxbufferindex = rxbufferlen Then ' end of buffer transfer wrdata = 1 rxbufferindex = 0 EndIF GoTo i2c_exit '------------------------------------------------------------------------------- I2C_Read: ' I2C read data from us IF d_a = 0 Then txbufferindex = 0 EndIF While stat_bf : Wend ' koop while buffer is full wcol = 0 ' clear collision flag sspbuf = txbuffer[txbufferindex] While wcol wcol = 0 sspbuf = txbuffer[txbufferindex] Wend ckp = 1 ' release clock, allowing read by master txbufferindex = txbufferindex + 1 ' increment index IF txbufferindex = txbufferlen Then ' all bytes have been tx txbufferindex = 0 ' reset index EndIF GoTo i2c_exit '------------------------------------------------------------------------------- I2C_Exit: sspov = 0 wcol = 0 wrdata = 0 Return '------------------------------------------------------------------------------- '------------------------------------------------------------------------------- main: txbuffer[0] = 12 ' test value rxbuffer[0] = 0 IF sspif = 1 Then GoSub i2c_slave EndIF Select Case rxbuffer[0] Case 0 ' do something here, turn on LED for example. End Select GoTo main End
Bookmarks