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.
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
You have to set the CKP-bit even after a WRITE-operation.
Try to disable the HSEROUT-lines.
Maybe this command will alter the TRISC-register, which will kill the I2C-engine.
Sometime, you should clear the OV-bit...
PBP 2.50C, MCS+ 3.0.0.5, MPLAB 8, MPASM 5.14, ASIX Presto, PoScope, mE mikroBasic V7.2, PICKIT2
I have been trying to get a 18F2620 to run as a slave. i ran across this in the ERRATA for this device.
I have gotten sporadic results for the master reading the slave in the following code.Code:43. Module: MSSP (I2C Slave) The MSSP module operating in I2C, 7-Bit Slave mode (SSPM3:SSPM0 = 0110) may not send a NACK bit (/ACK) in response to receiving the slave address loaded in SSPADD<7:1>. Addresses are in one of these ranges: 0x00 to 0x07 0x78 to 0x7F These addresses were reserved by Philips® Semiconductors in The I2C Specification, Version 2.1, released January 2000. Section 10.1 Definition of bits in the first byte defines the purposes of these addresses. This specification can be found at: http://www.semiconductors.philips.com/i2c Work around This version of the silicon does not respond to slave addresses in the ranges previously listed. Use either of these work arounds: Change the 7-bit slave address in SSPADD to an address in the range of 0x08 to 0x77. Use Revision B silicon. This version of silicon removes this issues addressing restrictions.
Darrell's Instant Interrupt
The Interrupt handlerCode:' Interrupt definition ' ==================== ' USB interrupt used to keep USB connection alive INCLUDE "DT_INTS-18.bas" ' Base Interrupt System INCLUDE "ReEnterPBP-18.bas" ' Include if using PBP interrupts ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler SSP_INT, _I2C_Int, PBP, yes endm INT_CREATE ; Creates the interrupt processor endasm ''----------------- Initialization Done! ----------------------------- @ INT_ENABLE SSP_INT ; Master Synchronous Serial Port Interrupt Flag bit. The transmission/reception is complete 'txbuffer = 0
and the main loop. I want to send three bytes to the master. In this case "three sevens".Code:I2C_Int: If R_W = 0 then if D_A = 0 then address = SSPBUF else Still working on master to slave write ' if bf = 1 then ' if rxcnt <= rxbufferlen then ' datain[rxcnt] = SSPBUF ' rxcnt = rxcnt + 1 ' if rxcnt = rxbufferlen then rxcnt = 0 ' endif EndIF endif else dataout = SSPBUF 'dummy read if txcnt > 0 then SSPBUF = txbuffer[txoutptr] txoutptr = txoutptr + 1 if txoutptr = txbufferlen then txoutptr = 0 txcnt = txcnt - 1 else 'no byte to send endif endif CKP = 1 @ INT_RETURN
I did the same slave program in "C" and it works well.Code:Main: SSPOV = 0 WCOL = 0 if txcnt < txbufferlen - 1 then TxBuffer[txinptr] = 7 txinptr = txinptr + 1 if txinptr = txbufferlen then txinptr = 0 txcnt = txcnt + 1 endif WrData=0 goto main end
The Master is reading and writing to a RTC module and a bank of 4 24lc256 EEProms and a I2C Port expander with out any problems.
It is getting close
Take care
Dave
Although the 16F guys have been having good luck with low addresses, it makes sense that the errata sheet would point out the old Phillips rule about low addresses. I haven't tried an address above $08 before... gotta go give that a shot too. I'll report back with any results, good or bad.
Rswain
Today I tried changing the Master and Slave addresses to higher numbers. I tried $26, $A6, and $02 just for good measure. They all responded with the same results; the slave sees the address, matches to its own, sets the interrupt flag, sets the Buffer Full flag, loads the address byte into the SSPBUF and I can read it from there. Although I reported before that the Slave wasn't sending an ACK, I think I was wrong. When I poll the ACKSTAT in the Master, it comes back with a "0" which I thought was NO ACK, but in fact a 0 is reporting a good ACK.
I've also switched to 18F4685 on both Master and Slave just eliminate the possiblilty of bad chips. Same results.
I took Daniel's suggestion to try to read from the Slave instead of sending to it. The slave responds by loading the first digit in its SSPBUF but I'm not seeing it show up at the Master.
I notice that the Slave's D_A (SSPSTAT.5 ' SSP Data not Address) is always showing "1" for DATA and never have I seen a "0" for ADDRESS. Is that OK? How would that bit get changed?
Rswain
Last edited by rswain; - 14th March 2009 at 02:55.
I'll try to buy a 18F2620 this week and run a few testHope I can get it here, I live in Argentina, it's not always easy to find those "big brothers" ...
EDIT: I found a 18F452 laying around on the desk, will this serve the purpose???
Last edited by DanPBP; - 14th March 2009 at 03:47.
Bookmarks