A short video:
The master on the left, a 16F877 is telling the first 16F88 (on the top) to turn on/off the LED, and then reads 24 from it. After that, the master tells the second 16F88 (on the bottom) to turn on/off the LED, and then reads 12 from it.
It's in slow motion because I was testing everything, but I discovered that the I2C protocol is very fast!
Al, thanks a lot one more time!
Daniel.
Master 16f877 - External 4Mhz Crystal:
'------------------------------------------------------------------------------- '------------------------------------------------------------------------------- ' Master '------------------------------------------------------------------------------- '------------------------------------------------------------------------------- DEFINE OSC 4 'OPTION_REG.7 = 0 ADCON1 = 7 '------------------------------------------------------------------------------ DEFINE I2C_SLOW 1 TRISB.5 = 1 TRISB.7 = 1 '------------------------------------------------------------------------------ scl VAR PORTB.5 ' i2c clock input sda VAR PORTB.7 ' i2c data input '------------------------------------------------------------------------------ I2Caddress VAR BYTE valor VAR BYTE '------------------------------------------------------------------------------ ' Set LCD Data port DEFINE LCD_DREG PORTD ' Set starting Data BIT (0 OR 4) IF 4-BIT bus DEFINE LCD_DBIT 4 ' Set LCD Register Select port DEFINE LCD_RSREG PORTC ' Set LCD Register Select BIT DEFINE LCD_RSBIT 6 ' Set LCD Enable port DEFINE LCD_EREG PORTC ' Set LCD Enable BIT DEFINE LCD_EBIT 7 ' 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 '------------------------------------------------------------------------------ Pause 500 ' Wait for LCD to startup LCDOut $fe, 1 LCDOut $fe, "Daniel" Pause 500 ' Wait for LCD to startup valor = 0 '------------------------------------------------------------------------------ main: I2Caddress = $3 LCDOut $fe, 1 LCDOut "Writting 1 - LED ON..." Pause 500 I2CWrite SDA, SCL, I2Caddress, [6], bogus ' Write offset to slave Pause 500 LCDOut $fe, 1 LCDOut "Writting 1 - LED OFF..." Pause 500 I2CWrite SDA, SCL, I2Caddress, [8], bogus ' Write to slave Pause 500 LCDOut $fe, 1 LCDOut "Reading 1..." Pause 500 I2CRead SDA, SCL, I2Caddress, [valor], bogus ' Read from slave LCDOut $fe, 1 LCDOut "Value: ", DEC valor Pause 500 '-------- I2Caddress = $5 LCDOut $fe, 1 LCDOut "Writting 2 - LED ON..." Pause 500 I2CWrite SDA, SCL, I2Caddress, [4], bogus ' Write to slave Pause 500 LCDOut $fe, 1 LCDOut "Writting 2 - LED OFF..." Pause 500 I2CWrite SDA, SCL, I2Caddress, [10], bogus ' Write to slave Pause 500 LCDOut $fe, 1 LCDOut "Reading 2..." Pause 500 I2CRead SDA, SCL, I2Caddress, [valor], bogus ' Read from slave LCDOut $fe, 1 LCDOut "Value: ", DEC valor Pause 500 '-------- GoTo main ' Do it forever '------------------------------------------------------------------------------- bogus: LCDOut $fe,1, "Time out" ' I2C command timed out Pause 500 GoTo main '------------------------------------------------------------------------------- End '------------------------------------------------------------------------------- '-------------------------------------------------------------------------------
'------------------------------------------------------------------------------ '------------------------------------------------------------------------------ ' Slave '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ @ device pic16f88, intrc_osc_noclkout ' system clock options @ device pic16f88, wdt_on ' watchdog timer @ device pic16f88, pwrt_on ' power-on timer @ device pic16f88, mclr_off ' master clear options (internal) @ device pic16f88, protect_off ' code protect off '--- set device --------------------------------------------------------------- DEFINE OSC 8 OSCCON = %01110001 '8mhz '------------------------------------------------------------------------------ CMCON = 7 ADCON1 = 0 ' Disable A/D converter ADCON0 = 0 ANSEL = 0 ' all analog pins to digital '--- tris port config here (don't use SCL & SDA pins other than I2C) ---------- DEFINE I2C_HOLD 1 TRISB.1 = 1 TRISB.4 = 1 '--- Alias pins --------------------------------------------------------------- SDADIR VAR TRISB.1 SCLDIR VAR TRISB.4 '--- Define here your variables and alias ------------------------------------- LEDT VAR PORTA.2 LEDL VAR PORTB.7 LEDM VAR PORTB.6 LEDR VAR PORTB.5 readcnt VAR BYTE datain VAR BYTE WrData VAR BYTE '--- Define used register flags ------------------------------------------------ SSPIF VAR PIR1.3 ' SSP (I2C) interrupt flag SSPIE VAR PIE1.3 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 SSPCON.4 ' SSP (I2C) SCK Release Control SSPEN VAR SSPCON.5 ' SSP (I2C) Enable SSPOV VAR SSPCON.6 ' SSP (I2C) Receive Overflow Indicator WCOL VAR SSPCON.7 ' SSP (I2C) Write Collision Detect 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 defintion ------------------------------------------------------ RxBufferLEN CON 1 RxBuffer VAR BYTE[Rxbufferlen] RxBufferIndex VAR BYTE '--- Tx Buffer defintion ------------------------------------------------------ TxBufferLEN CON 1 TxBuffer VAR BYTE[txbufferlen] TxBufferIndex VAR BYTE '--- Define constants --------------------------------------------------------- I2Caddress CON $3 ' Make address = 3 '--- Initialize I2C slave mode ------------------------------------------------ SCLDIR = 1 ' SCL must be an input before enabling interrupts SDADIR = 1 SSPADD = I2Caddress ' Set our address SSPCON = $36 ' Set to I2C slave with 7-bit address SSPSTAT = 0 SSPIE = 1 SSPIF = 0 RxBufferIndex = 0 TxBufferIndex = 0 '--- Initialization Done! ----------------------------------------------------- GoTo main '--- I2C subroutine ---------------------------------------------------------- i2cslave: ' I2C slave subroutine SSPIF = 0 ' Clear interrupt flag IF R_W = 1 Then i2crd ' Read data from us IF BF = 0 Then i2cexit ' Nothing in buffer so exit IF D_A = 1 Then i2cwr ' Data for us (not address) IF SSPBUF != I2Caddress Then i2cexit ' Clear the address from the buffer readcnt = 0 ' Mark as first read GoTo i2cexit i2cwr: ' 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 i2cexit i2crd: ' I2C read data from us IF D_A = 0 Then TxBufferIndex = 0 EndIF While STAT_BF : Wend ' loop 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 i2cexit: Return '--- End I2C subroutine ------------------------------------------------------ Main: txbuffer = 12 IF SSPIF = 1 Then GoSub i2cslave EndIF SSPOV = 0 WCOL = 0 Select Case RxBuffer[0] Case 6 High LEDT Case 8 Low LEDT End Select WrData=0 GoTo Main '------------------------------------------------------------------------------ End '------------------------------------------------------------------------------ '------------------------------------------------------------------------------
'------------------------------------------------------------------------------ '------------------------------------------------------------------------------ ' Slave '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ @ device pic16f88, intrc_osc_noclkout ' system clock options @ device pic16f88, wdt_on ' watchdog timer @ device pic16f88, pwrt_on ' power-on timer @ device pic16f88, mclr_off ' master clear options (internal) @ device pic16f88, protect_off ' code protect off '--- set device --------------------------------------------------------------- DEFINE OSC 8 OSCCON = %01110001 '8mhz '------------------------------------------------------------------------------ CMCON = 7 ADCON1 = 0 ' Disable A/D converter ADCON0 = 0 ANSEL = 0 ' all analog pins to digital '--- tris port config here (don't use SCL & SDA pins other than I2C) ---------- DEFINE I2C_HOLD 1 TRISB.1 = 1 TRISB.4 = 1 '--- Alias pins --------------------------------------------------------------- SDADIR VAR TRISB.1 SCLDIR VAR TRISB.4 '--- Define here your variables and alias ------------------------------------- LEDT VAR PORTA.2 LEDL VAR PORTB.7 LEDM VAR PORTB.6 LEDR VAR PORTB.5 readcnt VAR BYTE datain VAR BYTE WrData VAR BYTE '--- Define used register flags ------------------------------------------------ SSPIF VAR PIR1.3 ' SSP (I2C) interrupt flag SSPIE VAR PIE1.3 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 SSPCON.4 ' SSP (I2C) SCK Release Control SSPEN VAR SSPCON.5 ' SSP (I2C) Enable SSPOV VAR SSPCON.6 ' SSP (I2C) Receive Overflow Indicator WCOL VAR SSPCON.7 ' SSP (I2C) Write Collision Detect 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 defintion ------------------------------------------------------ RxBufferLEN CON 1 RxBuffer VAR BYTE[Rxbufferlen] RxBufferIndex VAR BYTE '--- Tx Buffer defintion ------------------------------------------------------ TxBufferLEN CON 1 TxBuffer VAR BYTE[txbufferlen] TxBufferIndex VAR BYTE '--- Define constants --------------------------------------------------------- I2Caddress CON $5 ' Make address = 5 '--- Initialize I2C slave mode ------------------------------------------------ SCLDIR = 1 ' SCL must be an input before enabling interrupts SDADIR = 1 SSPADD = I2Caddress ' Set our address SSPCON = $36 ' Set to I2C slave with 7-bit address SSPSTAT = 0 SSPIE = 1 SSPIF = 0 RxBufferIndex = 0 TxBufferIndex = 0 '--- Initialization Done! ----------------------------------------------------- GoTo main '--- I2C subroutine ---------------------------------------------------------- i2cslave: ' I2C slave subroutine SSPIF = 0 ' Clear interrupt flag IF R_W = 1 Then i2crd ' Read data from us IF BF = 0 Then i2cexit ' Nothing in buffer so exit IF D_A = 1 Then i2cwr ' Data for us (not address) IF SSPBUF != I2Caddress Then i2cexit ' Clear the address from the buffer readcnt = 0 ' Mark as first read GoTo i2cexit i2cwr: ' 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 i2cexit i2crd: ' I2C read data from us IF D_A = 0 Then TxBufferIndex = 0 EndIF While STAT_BF : Wend ' loop 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 i2cexit: Return '--- End I2C subroutine ------------------------------------------------------ Main: txbuffer = 24 IF SSPIF = 1 Then GoSub i2cslave EndIF SSPOV = 0 WCOL = 0 Select Case RxBuffer[0] Case 4 High LEDT Case 10 Low LEDT End Select WrData=0 GoTo Main '------------------------------------------------------------------------------ End '------------------------------------------------------------------------------ '------------------------------------------------------------------------------
Re: SERIN2 Receiving Wrong Data
The sending device has the typical 18F4550 USB setup and it is set to "Define OSC 48". The receiving device is set to "DEFINE OSC 16".
rsocor01 Yesterday, 19:56