Here is an example on how to use the Master Synchronous Serial Port (MSSP). Have not tested on other devices or generalized the InitI2C sub to handle other devices if so required? Comments welcome.
Sorry for no indents, maybe code tags will come along in the future.
The header file is in another post to keep it short.
Kent
'-------------------------------------------------------
'Master I2C Mode (Hardware-Synchronous)
'By Kent Schafer June 20, 2007
'This is a port of Microchip Tutorial "I2C Master Mode"
'and AN976
'-------------------------------------------------------
'setup I2C
#include <MasterI2C.h>
#define eeprom_write b'10100000' '24lc256 address write
#define eeprom_read b'10100001' '24lc256 address read
'SSPADD (ClockValue) equals (FOSC / (4 * Baud)) - 1
'For example for 20mhz clock and 100,000bps baud = 49
'At this time be sure to define ClockValue in binary form
#define ClockValue b'00110001'
Dir PortC.3 In 'SCL Port Pin
Dir PortC.4 In 'SDA Port Pin
Dim addr as Word
Dim RxWord as Word
Dim test as Word
cls
test = 7777
'Initialize MSSP to enable I2c and master mode
InitI2C
'Send out data to eeprom address
addr = 1
WriteID = eeprom_write
ReadID = eeprom_read
For count = 1 to 10
testl = test
testh = test_H
For I2CWord = 1 to 2
If I2CWord = 1 Then 'First loop thru
addr = addr + 1
LowAddr = addr
HighAddr = addr_h
I2CWrite(WriteID,HighAddr, LowAddr, testh)
wait 5 ms 'Need some delay here for proper operation
End if
If I2CWord = 2 Then
addr = addr + 1
LowAddr = addr
HighAddr = addr_h
I2CWrite(WriteID,HighAddr, LowAddr, testl)
wait 5 ms 'Need some delay here for proper operation
End if
Next
test = test + 1000
Next
Main:
'Read the test data at eeprom address
addr = 1
For count = 1 to 10
For I2CWord = 1 to 2
If I2CWord = 1 Then 'Read in High byte first
addr = addr + 1
LowAddr = addr
HighAddr = addr_h
RxHigh = I2CRead(WriteID,HighAddr,LowAddr,ReadID)
wait 5 ms 'Need some delay here for proper operation
End if
If I2CWord = 2 Then 'Read in Low byte next
addr = addr + 1
LowAddr = addr
HighAddr = addr_h
RxLow = I2CRead(WriteID,HighAddr,LowAddr,ReadID)
wait 5 ms 'Need some delay here for proper operation
End if
Next
Hey man,
I tried ur code n found an error where it said the I2CWrite(WriteID,HighAddr, LowAddr, testl) has syntax error
And I just cannot figured out what is the syntax error. Anyone can help?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Not able to re-run the code from my location to tell if something is broke. But the first inclination is if you have the the MasterI2C.h file saved in the GCBasic include folder? The procedure for doing that has been covered in a previous forum post.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yeah I have it
Here is the code I copied from the one of the post. I think there are maybe error within it?
I'm really stuck with the I2C kent... :(
Can u see any error within the MasterI2c.h?
This is abit out of the box but after I tried the MasterI2C.h not successfully I wrote this one to test but also not working:
----------------------------------------My test code------------------------------------------------
#chip 18F452, 4
ADoff
#include <MasterI2C.h>
#define I2CPORT PORTC
#define SDA_PORT 4
#define SCL_PORT 3
#define SDA I2CPORT.SDA_PORT
#define SCL I2CPORT.SCL_PORT
Main:
Address = b'00001111'
I2C_Data = b'00000010'
ICC_initialize
ICC_START
ICC_send(b'10110000')
wait 5 us
ICC_send(Address)
wait 5 us
ICC_send(I2C_Data)
wait 5 us
ICC_send(b'10110000')
wait 5 us
ICC_send(b'00000000')
wait 5 us
ICC_send(b'00110010')
ICC_STOP
wait 5 s
goto Main
'Restart
'Address = b'00000000'
'I2C_Data = b'00110010'
'I2CWrite(0xB0, Address, I2C_Data)
'wait 2 s
'goto Main
end
Sub ICC_START
Set SDA ON // i2c start bit sequence
wait 5 us
Set SCL ON
wait 5 us
Set SDA OFF
wait 5 us
Set SCL OFF
wait 5 us
End Sub
Sub ICC_STOP
SET SDA OFF // i2c stop bit sequence
wait 5 us
Set SCL ON
wait 5 us
Set SDA ON
wait 5 us
End Sub
sub ICC_send(XMIT)
'subroutine to send 8 bits
DIR SDA OUT 'set SDA as output
SET SCL OFF
wait 5 us
for counter = 1 to 8
SET SDA OFF 'clear SDA
ROTATE XMIT LEFT 'if bit of XMIT is 1, set SDA
IF STATUS.C ON THEN SET SDA ON
SET SCL ON 'take SCL high
wait 5 us 'delay 5micro second
SET SCL OFF 'take SCL low
wait 5 us
NEXT 'proceed with rest of bits in XMIT
'NOW acknowledge send
DIR SDA IN 'set SDA as input
SET SCL ON 'take SCL high
wait 5 us 'delay 5microseconds
SET SCL OFF 'take SCL low
wait 5 us
DIR SDA OUT 'set SDA as output
end sub
sub ICC_initialize
ADOff 'make port digital
DIR I2CPORT b'00000000' 'make SCL and SDA outputs
DIR SDA OUT
DIR SCL OUT
SET SDA ON 'bring both SCL and SDA high
wait 5 us
SET SCL ON
wait 5 us
'SSPADD = 249
'SSPCON1 = b'00001000'
end sub
------------------------------------------------MasterI2C.h-----------------------------------------------------------
'--------------------------------------------------------
'Header file name MasterI2c.h
'Master I2C Mode (Hardware-Synchronous)
'By Kent Schafer June 21, 2007
'This is a port of Microchip Tutorial "I2C Master Mode"
'and AN976
'
'This header is currently set up for word size addressing
'like in the larger size eeproms.
'No polling is taking place after writes or reads
'A suitable delay is required (5 ms or ??)
'--------------------------------------------------------
sub InitI2C 'Disable slew rate control (SMP)
SSPSTAT = b'1000000' 'ClockValue or SSPADD = (FOSC / (4 * Baud)) - 1
SSPADD = ClockValue 'Clear the register, only cleared on POR
SSPCON2 = 0 'Set SSPEN and SSPMx bits for SSP Enable and Master I2C mode
SSPCON = b'00101000'
SET PIR1.SSPIF OFF
SET PIR2.BCLIF OFF
end sub
sub Start
Set PIR1.SSPIF Off 'Clear SSP interrupt flag
Set SSPCON2.SEN On 'set start condition
waitstart:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitstart
end if
end sub
sub Restart
Set PIR1.SSPIF Off 'Clear SSP interrupt flag
Set SSPCON2.RSEN On 'set stop condition
waitRestart:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitRestart
end if
end sub
sub TxI2C(SendByte)
Set PIR1.SSPIF Off
SSPBUF = SendByte
'Wait for acknowledge
waitTx:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitTx
end if
waitAck:
If SSPCON2.ACKSTAT On Then
goto waitAck
end if
end sub
sub RxI2C
Set PIR1.SSPIF Off
Set RCEN On 'Initiate reception
waitRx1:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitRx1
end if
ReadByte = SSPBUF 'Read byte in buffer
'Wait for Not acknowledge
Set PIR1.SSPIF Off
Set SSPCON2.ACKEN On 'Select to send NO ACK
waitNoAck:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitNoAck
end if
end sub
sub Stop
Set PIR1.SSPIF Off
Set SSPCON2.PEN On 'Set Stop condition
waitStop:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitStop
end if
end sub
'sub Poll
' For pollcount = 1 to 40
' Restart
' TxI2C(eeprom_write)
'end sub
Function I2CWrite(WriteID, HighAddr, LowAddr, I2Cdata)
Start
TxI2C(WriteID) 'Device ID write byte
TxI2C(HighAddr) 'Send word address high byte
TxI2C(LowAddr) 'Send word address low byte
TxI2C(I2Cdata) 'Send out data byte to slave
Stop
'Poll
end Function
Function I2CRead(WriteID,HighAddr,LowAddr,ReadID)
Start
TxI2C(WriteID) 'Device ID read byte
TxI2C(HighAddr) 'Send word address high byte
TxI2C(LowAddr) 'Send word address low byte
Restart
TxI2C(ReadID) 'Device ID read byte
Set SSPCON2.ACKDT On 'Send no acknowledge
RxI2C 'Receive data byte from slave
I2CRead = ReadByte
Stop
end function
sub I2CWriteTemp(WriteID,command)
Start
TxI2C(WriteID) 'Device ID write byte
TxI2C(command) 'Send byte size data
Stop
end sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry about the late response, but will not be back to my stuff for several weeks yet. When using the 18f4620, the MasterI2C.h didn't work either. So here was the header file work around. An if statement, or script checking for 16 bit device would be more elegant.
Hope this works for you.
sub InitI2C 'Disable slew rate control (SMP)
SSPSTAT = b'1000000' 'ClockValue or SSPADD = (FOSC / (4 * Baud)) - 1
SSPADD = ClockValue 'Clear the register, only cleared on POR
SSPCON2 = 0 'Set SSPEN and SSPMx bits for SSP Enable and Master I2C mode
;SSPCON = b'00101000'
SSPCON1 = b'00101000' '18f needs SSPCON1
SET SSPIF OFF 'SET PIR1.SSPIF OFF
SET BCLIF OFF 'SET PIR2.BCLIF OFF
end sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Here is an example on how to use the Master Synchronous Serial Port (MSSP). Have not tested on other devices or generalized the InitI2C sub to handle other devices if so required? Comments welcome.
Sorry for no indents, maybe code tags will come along in the future.
The header file is in another post to keep it short.
Kent
'-------------------------------------------------------
'Master I2C Mode (Hardware-Synchronous)
'By Kent Schafer June 20, 2007
'This is a port of Microchip Tutorial "I2C Master Mode"
'and AN976
'-------------------------------------------------------
'Chip model
#chip 16f877A,20
#config _CP_OFF & CPD_OFF &_WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _LVP_OFF
'Setup 4 bit LCD
#define LCD_IO 4
#define LCD_DB4 PORTD.4
#define LCD_DB5 PORTD.5
#define LCD_DB6 PORTD.6
#define LCD_DB7 PORTD.7
#define LCD_RS PORTC.7
#define LCD_RW PORTC.6
#define LCD_Enable PORTC.5
'setup I2C
#include <MasterI2C.h>
#define eeprom_write b'10100000' '24lc256 address write
#define eeprom_read b'10100001' '24lc256 address read
'SSPADD (ClockValue) equals (FOSC / (4 * Baud)) - 1
'For example for 20mhz clock and 100,000bps baud = 49
'At this time be sure to define ClockValue in binary form
#define ClockValue b'00110001'
Dir PortC.3 In 'SCL Port Pin
Dir PortC.4 In 'SDA Port Pin
Dim addr as Word
Dim RxWord as Word
Dim test as Word
cls
test = 7777
'Initialize MSSP to enable I2c and master mode
InitI2C
'Send out data to eeprom address
addr = 1
WriteID = eeprom_write
ReadID = eeprom_read
For count = 1 to 10
testl = test
testh = test_H
For I2CWord = 1 to 2
If I2CWord = 1 Then 'First loop thru
addr = addr + 1
LowAddr = addr
HighAddr = addr_h
I2CWrite(WriteID,HighAddr, LowAddr, testh)
wait 5 ms 'Need some delay here for proper operation
End if
If I2CWord = 2 Then
addr = addr + 1
LowAddr = addr
HighAddr = addr_h
I2CWrite(WriteID,HighAddr, LowAddr, testl)
wait 5 ms 'Need some delay here for proper operation
End if
Next
test = test + 1000
Next
Main:
'Read the test data at eeprom address
addr = 1
For count = 1 to 10
For I2CWord = 1 to 2
If I2CWord = 1 Then 'Read in High byte first
addr = addr + 1
LowAddr = addr
HighAddr = addr_h
RxHigh = I2CRead(WriteID,HighAddr,LowAddr,ReadID)
wait 5 ms 'Need some delay here for proper operation
End if
If I2CWord = 2 Then 'Read in Low byte next
addr = addr + 1
LowAddr = addr
HighAddr = addr_h
RxLow = I2CRead(WriteID,HighAddr,LowAddr,ReadID)
wait 5 ms 'Need some delay here for proper operation
End if
Next
RxWord = RxLow
RxWord_H = RxHigh
cls
LCDWord (RxWord)
wait 5 sec
Next
Goto Main
Hey man,
I tried ur code n found an error where it said the I2CWrite(WriteID,HighAddr, LowAddr, testl) has syntax error
And I just cannot figured out what is the syntax error. Anyone can help?
Not able to re-run the code from my location to tell if something is broke. But the first inclination is if you have the the MasterI2C.h file saved in the GCBasic include folder? The procedure for doing that has been covered in a previous forum post.
Yeah I have it
Here is the code I copied from the one of the post. I think there are maybe error within it?
I'm really stuck with the I2C kent... :(
Can u see any error within the MasterI2c.h?
This is abit out of the box but after I tried the MasterI2C.h not successfully I wrote this one to test but also not working:
----------------------------------------My test code------------------------------------------------
#chip 18F452, 4
ADoff
#include <MasterI2C.h>
#define I2CPORT PORTC
#define SDA_PORT 4
#define SCL_PORT 3
#define SDA I2CPORT.SDA_PORT
#define SCL I2CPORT.SCL_PORT
Dim Address, I2C_Data as byte
#define ClockValue b'00110001' ;ClockValue or SSPADD = (FOSC / (4 * Baud)) - 1
Main:
Address = b'00001111'
I2C_Data = b'00000010'
ICC_initialize
ICC_START
ICC_send(b'10110000')
wait 5 us
ICC_send(Address)
wait 5 us
ICC_send(I2C_Data)
wait 5 us
ICC_send(b'10110000')
wait 5 us
ICC_send(b'00000000')
wait 5 us
ICC_send(b'00110010')
ICC_STOP
wait 5 s
goto Main
'Restart
'Address = b'00000000'
'I2C_Data = b'00110010'
'I2CWrite(0xB0, Address, I2C_Data)
'wait 2 s
'goto Main
end
Sub ICC_START
Set SDA ON // i2c start bit sequence
wait 5 us
Set SCL ON
wait 5 us
Set SDA OFF
wait 5 us
Set SCL OFF
wait 5 us
End Sub
Sub ICC_STOP
SET SDA OFF // i2c stop bit sequence
wait 5 us
Set SCL ON
wait 5 us
Set SDA ON
wait 5 us
End Sub
sub ICC_send(XMIT)
'subroutine to send 8 bits
DIR SDA OUT 'set SDA as output
SET SCL OFF
wait 5 us
for counter = 1 to 8
SET SDA OFF 'clear SDA
ROTATE XMIT LEFT 'if bit of XMIT is 1, set SDA
IF STATUS.C ON THEN SET SDA ON
SET SCL ON 'take SCL high
wait 5 us 'delay 5micro second
SET SCL OFF 'take SCL low
wait 5 us
NEXT 'proceed with rest of bits in XMIT
'NOW acknowledge send
DIR SDA IN 'set SDA as input
SET SCL ON 'take SCL high
wait 5 us 'delay 5microseconds
SET SCL OFF 'take SCL low
wait 5 us
DIR SDA OUT 'set SDA as output
end sub
sub ICC_initialize
ADOff 'make port digital
DIR I2CPORT b'00000000' 'make SCL and SDA outputs
DIR SDA OUT
DIR SCL OUT
SET SDA ON 'bring both SCL and SDA high
wait 5 us
SET SCL ON
wait 5 us
'SSPADD = 249
'SSPCON1 = b'00001000'
end sub
------------------------------------------------MasterI2C.h-----------------------------------------------------------
'--------------------------------------------------------
'Header file name MasterI2c.h
'Master I2C Mode (Hardware-Synchronous)
'By Kent Schafer June 21, 2007
'This is a port of Microchip Tutorial "I2C Master Mode"
'and AN976
'
'This header is currently set up for word size addressing
'like in the larger size eeproms.
'No polling is taking place after writes or reads
'A suitable delay is required (5 ms or ??)
'--------------------------------------------------------
sub InitI2C 'Disable slew rate control (SMP)
SSPSTAT = b'1000000' 'ClockValue or SSPADD = (FOSC / (4 * Baud)) - 1
SSPADD = ClockValue 'Clear the register, only cleared on POR
SSPCON2 = 0 'Set SSPEN and SSPMx bits for SSP Enable and Master I2C mode
SSPCON = b'00101000'
SET PIR1.SSPIF OFF
SET PIR2.BCLIF OFF
end sub
sub Start
Set PIR1.SSPIF Off 'Clear SSP interrupt flag
Set SSPCON2.SEN On 'set start condition
waitstart:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitstart
end if
end sub
sub Restart
Set PIR1.SSPIF Off 'Clear SSP interrupt flag
Set SSPCON2.RSEN On 'set stop condition
waitRestart:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitRestart
end if
end sub
sub TxI2C(SendByte)
Set PIR1.SSPIF Off
SSPBUF = SendByte
'Wait for acknowledge
waitTx:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitTx
end if
waitAck:
If SSPCON2.ACKSTAT On Then
goto waitAck
end if
end sub
sub RxI2C
Set PIR1.SSPIF Off
Set RCEN On 'Initiate reception
waitRx1:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitRx1
end if
ReadByte = SSPBUF 'Read byte in buffer
'Wait for Not acknowledge
Set PIR1.SSPIF Off
Set SSPCON2.ACKEN On 'Select to send NO ACK
waitNoAck:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitNoAck
end if
end sub
sub Stop
Set PIR1.SSPIF Off
Set SSPCON2.PEN On 'Set Stop condition
waitStop:
If PIR1.SSPIF Off Then 'Check if operation complete
goto waitStop
end if
end sub
'sub Poll
' For pollcount = 1 to 40
' Restart
' TxI2C(eeprom_write)
'end sub
Function I2CWrite(WriteID, HighAddr, LowAddr, I2Cdata)
Start
TxI2C(WriteID) 'Device ID write byte
TxI2C(HighAddr) 'Send word address high byte
TxI2C(LowAddr) 'Send word address low byte
TxI2C(I2Cdata) 'Send out data byte to slave
Stop
'Poll
end Function
Function I2CRead(WriteID,HighAddr,LowAddr,ReadID)
Start
TxI2C(WriteID) 'Device ID read byte
TxI2C(HighAddr) 'Send word address high byte
TxI2C(LowAddr) 'Send word address low byte
Restart
TxI2C(ReadID) 'Device ID read byte
Set SSPCON2.ACKDT On 'Send no acknowledge
RxI2C 'Receive data byte from slave
I2CRead = ReadByte
Stop
end function
sub I2CWriteTemp(WriteID,command)
Start
TxI2C(WriteID) 'Device ID write byte
TxI2C(command) 'Send byte size data
Stop
end sub
Sorry about the late response, but will not be back to my stuff for several weeks yet. When using the 18f4620, the MasterI2C.h didn't work either. So here was the header file work around. An if statement, or script checking for 16 bit device would be more elegant.
Hope this works for you.
sub InitI2C 'Disable slew rate control (SMP)
SSPSTAT = b'1000000' 'ClockValue or SSPADD = (FOSC / (4 * Baud)) - 1
SSPADD = ClockValue 'Clear the register, only cleared on POR
SSPCON2 = 0 'Set SSPEN and SSPMx bits for SSP Enable and Master I2C mode
;SSPCON = b'00101000'
SSPCON1 = b'00101000' '18f needs SSPCON1
SET SSPIF OFF 'SET PIR1.SSPIF OFF
SET BCLIF OFF 'SET PIR2.BCLIF OFF
end sub