Hi,
I have been struggling for the past few days trying to interface an I2C pressure sensor from SensorTechnics with the PIC16F1827. I successfully bit banged the sensor using a Basic Stamp II a few weeks ago so I know that the sensor is working properly. However, even when I convert the bit banging code to the PIC it still doesn't work, so I know I am doing something simple incorrectly.
I can see clock and data when I connect my oscilloscope to the I/O pins so I know their is activity on the ports, but the result is always filled 0's.
I2C DataSheet for Pressure Sensor
DataSheet for the PIC16F1827 chip
- When you use the I2CREAD command does it send a START condition?
- Using this syntax
Code:
I2CRead sda,scl,$F1,[result1,result2]
does the I2CREAD command send the device address? and an along with an Ack, Nak after the two bytes?
Do I need to use an I2CWRITE command to write the address to the I2C slave after manually generating a START condition myself?
Code:
DEFINE HSER_RCSTA 90h ' Define Receive Port
DEFINE HSER_TXSTA 24h ' Define Transmit Port
DEFINE HSER_BAUD 9600 ' Decalre 9600 Baud Rate for Serial Port
DEFINE OSC 20
scl VAR PORTB.4: TRISB.4 = 1 ' I2C clock input
sda VAR PORTB.1: TRISB.1 = 1 ' I2C data input
LED VAR PORTB.0 ' Assign name "LED" to PORTB.0
addr VAR Byte ' I2C Address Variable
result1 VAR BYTE ' I2C Result Variable
result2 VAR BYTE ' I2C Result Variable
result VAR WORD
ADDR = %11110001
'Reset Digi Xbee Module
LOW PORTB.3
HIGH PORTB.3
mainloop:
' *** Flash LED (HeartBeat)
High LED ' Turn on LED connected to PORTB.0
Pause 1000 ' Delay for .5 seconds
' *** Read I2C
Low LED ' Turn off LED connected to PORTB.0
Pause 1000 ' Delay for .5 seconds
TRISB.1 = 1
TRISb.4 = 1
HIGH SDA
HIGH SCL
LOW sda
I2CRead sda,scl,addr,[result1,result2], i2c_error
PAUSE 1000 ' Pause 1 Second for Read Operation to complete
HSEROUT ["Value:", BIN8 result1, BIN8 result2] ' Output Pressure reading through Serial Port
Goto mainloop ' Go back to loop and blink LED forever
End
' Trasnmit Error if Reading unable to occur
i2c_error:
HSEROUT ["Error"]
GOTO mainloop
Here is the bit banging code
Code:
DEFINE HSER_RCSTA 90h ' Define Receive Port
DEFINE HSER_TXSTA 24h ' Define Transmit Port
'DEFINE HSER_SPBRG 129
DEFINE OSC 20
DEFINE HSER_BAUD 9600 ' Declare 9600 Baud Rate for Serial Port
'Include Basic Stamp II Command Support
INCLUDE "modedefs.bas"
' ------------------------------------------------------------------------------ '
' I/O Definitions
' ------------------------------------------------------------------------------ '
SDA VAR PORTB.1 ' I2C serial data line
SCL VAR PORTB.4 ' I2C serial clock line
' ------------------------------------------------------------------------------ '
' Constants
' ------------------------------------------------------------------------------ '
Ack CON 0 ' acknowledge bit
Nak CON 1 ' no ack bit
slaveAddress CON %11110001 'SensorTechnics Slave Address
' ------------------------------------------------------------------------------ '
' Variables
' ------------------------------------------------------------------------------ '
i2cData VAR Word ' data to/from device
i2cWork VAR Byte ' work byte for TX routine
i2cAck VAR Bit ' Ack bit from device
' ------------------------------------------------------------------------------ '
' Initialization
'------------------------------------------------------------------------------ '
Init:
PAUSE 250
i2cACK = 0
' Reset XBee
LOW PORTB.3
HIGH PORTB.3
TRISB.1 = 0
TRISB.4 = 0
PAUSE 5000
' ------------------------------------------------------------------------------ '
' Program Code
' ------------------------------------------------------------------------------ '
Main:
GOSUB Read_Word
Hserout ["Current Pressure Reading (16 BITS): " , BIN16 i2cData]
PAUSE 1000
GOTO Main
END
' ------------------------------------------------------------------------------ '
' SensorTechnics Access Subroutines
' ------------------------------------------------------------------------------ '
' Read i2cData (16 bits) from Sensor
Read_Word:
GOSUB I2C_Start ' Send START Condition
i2cWork = slaveAddress ' Set Slave Address
GOSUB I2C_TX_Byte ' Send Slave Address
GOSUB I2C_RX_Byte
i2cData.HIGHBYTE = i2cWork ' Read high byte of data / send ack
GOSUB I2C_RX_Byte_Nak
i2cData.LOWBYTE = i2cWork ' Read low byte of data /send nack
GOSUB I2C_Stop ' Send STOP Command
RETURN
' ------------------------------------------------------------------------------ '
' Low Level I2C Subroutines
' ------------------------------------------------------------------------------ '
' --- Start ---
I2C_Start: ' I2C start bit sequence
TRISB.1 = 1
TRISB.4 = 1
'HIGH SDA ' Pull SDA High
'HIGH SCL ' Pull SCL High
LOW SDA ' SDA -> low while SCL high
Hserout ["Waiting for Clock"]
Clock_Hold:
IF (PORTB.4 = 0) THEN Clock_Hold ' device ready?
PAUSE 500
RETURN
' --- Transmit ---
I2C_TX_Byte:
SHIFTOUT SDA,SCL,MSBFIRST,[i2cWork\8] ' send byte to device
SHIFTIN SDA,SCL,MSBPRE,[i2cAck\1] ' get acknowledge bit
RETURN
' --- Receive ---
I2C_RX_Byte_Nak:
i2cAck = Nak ' no Ack = high
GOTO I2C_RX
I2C_RX_Byte:
i2cAck = Ack ' Ack = low
I2C_RX:
i2cWork = %00000000
SHIFTIN SDA,SCL,MSBPRE,[i2cWork\8] ' get byte from device
SHIFTOUT SDA,SCL,LSBFIRST,[i2cAck\1] ' send ack or nak
RETURN
' --- Stop ---
I2C_Stop: ' I2C stop bit sequence
LOW SDA
TRISB.1 = 1
TRISB.4 = 1
HIGH SCL
HIGH SDA ' SDA --> high while SCL high
RETURN
Any help would be appreciated, thanks in advance!
Ben
Bookmarks