Hi all
This code can you free use. Please send me tips, improvements or testcode.
i2c_lpt (i2c via the parallelport) not 100% tested
$USE "inpout32.lib"
$INCLUDE "i2c_lpt.inc"
'
'12.0 De I2C - bus
'------------------
' - De I2C bus is een 2-draads dataverbinding tussen ÃÆ'Ã,©ÃÆ'Ã,©n of meer processoren (masters) en speciale periferie
' componenten (slaves)
' - Al deze componenten zijn op dezelfde bus aangesloten en hebben elk hun eigen UNIEK ADRES.
' - Deze bus maakt een eenvoudige verbinding mogelijk tussen vele IC's, waarbij uitbreidingen kunnen worden
' gerealiseerd
' - Op de I2C bus kunnen alle IC's worden aangesloten die het I2C busprotocol beheersen
' - Voorbeelden : RAM -, EEPROM -, I/O -, ADC -, DAC -, Timers -, Displaydrivers -, IC Televisie.
' Al deze IC's kunnen zonder meer via 2 aansluitingen van de parallelle poort van de PC worden aangestuurd
' - We kunnen ook deze IC's aansturen met de RS232 interface
' - De bus maakt gebruik van de seriÃÆ'Ã,«le datalijn (SDA) en het kloksignaal (SCL).
' - DATA en ADRESSEN worden, net als bij een schuifregister, samen met het kloksignaal verzonden.
' - Beide lijnen kunnen in BEIDE RICHTINGEN worden gebruikt
' - Ze zijn van een pullup weerstand voorzien en kunnen door elk aangesloten IC met behulp van open - collector
' of open - drain uitgangen naar massa worden getrokken
'
' - Figuur 12.1
' ===========
' * Niet actieve buselementen zijn HOOGOHMIG, maar houden (uiteraard) wel de bussignalen in de gaten
' * Wanneer een systeem 1 MASTER wordt gebruikt : levert deze als enige het kloksignaal
' De data kunnen echter zowel van de MASTER als ÃÆ'Ã,©ÃÆ'Ã,©n van de SLAVES afkomstig zijn
' * Hoe kunnen we herkennen als elke busdeelnemer het begin en einde van een bericht + adressering.
'
' STAP 1 : RUSTTOESTAND
' =====================
' - SDA en SCL = HOOG
'
' STAP 2 : START CONDITIE (SDA : H -> L)
' ======================================
' - SDA wordt door de MASTER LAAG gemaakt
' - SCL = HOOG
'
' STAP 3 : STOP CONDITIE (SDA : L -> H)
' =====================================
' - SDA gaat van LAAG naar HOOG
' - SCL = HOOG
'
' STAP 4 : DATA OVERDRACHT
' ========================
' - De TRANSMITTER zet 1 byte op de datalijn (SDA), die door de klokpulsen van de MASTER op de kloklijn
' SCL verder worden geschoven
' - Overdracht begint steeds met het MSB bit
'
' STAP 5 : BEVESTIGING (ACK)
' ==========================
' - De RECEIVER bevestigt de ontvangst van een byte door de SDA lijn LAAG te maken tot de MASTER
' de 9 klokpuls op de SCL heeft gezet.
' - Deze bevestiging houdt meteen in dat een volgend byte ontvangen kan worden.
' - Wannneer de communicatie moet worden stopgezet wordt dit kenbaar gemaakt door het uitblijven van ACK
' - Met de STOP conditie wordt de communicatie gestopt
'
' - ADRESSEN worden op exact DEZELFDE manier verzonden als DATA, en de ontvangst wordt net zo bevestigd met de ACK
' In het eenvoudigste geval van DATA - overdracht van MASTER naar SLAVE : bvb : een I/O IC vinden de onderstaande
' processen plaats:
'
' STAP 1
' ======
' * De MASTER geeft het STARTSIGNAAL en verzendt dan in bits 7...1 het UNIEKE ADRES van het I/0 IC
'
' STAP 2
' ======
' * In bit 0 de richting van het dataverkeer R/W :
' W = 0 : schrijven
' R = 1 : lezen
' * De ontvangst van het ADRES wordt door de betreffende SLAVE bevestigd met een ACK bit
'
' STAP 3
' ======
' * Vervolgens verzendt de MASTER het DATABYTE, waarvan de ontvangst eveneens wordt ACK.
' * Nu kan de MASTER de verbinding verbreken door middel van een STOPSIGNAAL, of nog meer bytes naar de SLAVE
' te sturen
'
' STAP 4
' ======
' * Wanneer DATA uit de SLAVE moet worden uitgelezen, moet het richtingsbit R = 1 gemaakt worden.
' * De MASTER zet dan 8 klokpulsen op de kloklijn SCL.
' * en kan 8 databits in ontvangst nemen.
' * Zolang hij de ontvangst daarvan bij de 9 klokpuls door een ACK, kan hij bytes blijven ontvangen.
' * De overdracht wordt uiteindelijk door de MASTER stopgezet door het niet meer versturen van een ACK en door
' vervolgens een STOPSIGNAAL te verzenden
'
' - Elke I2C component heeft een VAST UNIEK ADRES dat deels door type component wordt bepaald en deels via extern
' toegankelijke adreslijnen kan worden beÃÆ'Ã,¯nvloed.
' - De maximale klokfrequentie voor de I2C bus bedraagt 100 kHz
'==================================================================================================================
'
'
'12.1 Aansturing via de LPT port
'-------------------------------
'
' - De I2C bus kan bijzonder gemakkelijk aan de parallelle poort (LPT - port) worden gekoppeld, omdat de
' bi-directionele aansluitingen STROBE en AUTO FEED direct als SDA en SCL kunnen worden gebruikt
' - Alle procedures die klokpulsen genereren zijn voorzien van delay loops.
' - In de praktijk is een waarde van 5 voor de delay loops optimaal gebleken bij een AT-386 met een klok
' frequentie van 25 MHz.
' - Voor snellere PC's moet deze waarde worden verhoogd, zodat de klokfrequentie op de SCL lijn ONDER de
' maximale waarde van 100 kHz blijft.
'============================================================================================================'
'============================================================================================================'
' ImpOut32.dll '
DECLARE IMPORT, Inp32(PortAddr : WORD), WORD '
DECLARE IMPORT, Out32(PortAddr : WORD, PortData : WORD) '
'============================================================================================================'
'============================================================================================================'
' MSVC70.dll '
DECLARE EXTERN _sscanf(STRING buf, STRING format,...),INT '
DECLARE EXTERN sprintf(POINTER p, POINTER p, ...), INT '
DECLARE EXTERN ReadKey alias __getch(),INT '
DECLARE EXTERN KeyPressed alias __kbhit(),INT '
'============================================================================================================'
'============================================================================================================'
' kernel32.dll '
DECLARE IMPORT, Sleep(int time) '
'============================================================================================================'
EXPORT i2c_Init
EXPORT i2c_Start
EXPORT i2c_Stop
EXPORT i2c_Ack
EXPORT i2c_NoAck
EXPORT i2c_Write
EXPORT i2c_Read
SUB i2c_Init()
Out32 ((LPT1 + 0x02), 0x00) 'SCL = 1, SDA = 1 (0000 0000)
RETURN
ENDSUB
SUB i2c_Start()
Out32 ((LPT1 + 0x02), 0x01) 'SCL = 1, SDA = 0 (0000 0001)
Out32 ((LPT1 + 0x02), 0x03) 'SCL = 0, SDA = 0 (0000 0011)
RETURN
ENDSUB
SUB i2c_Stop()
Out32 ((LPT1 + 0x02), 0x03) 'SCL = 0, SDA = 0 (0000 0011)
Out32 ((LPT1 + 0x02), 0x01) 'SCL = 1, SDA = 0 (0000 0001)
Out32 ((LPT1 + 0x02), 0x00) 'SDA = 1, SDA = 1 (0000 0000)
RETURN
ENDSUB
SUB i2c_Ack()
Out32 ((LPT1 + 0x02), 0x03) 'SCL = 0, SDA = 0 (0000 0011)
Out32 ((LPT1 + 0x02), 0x01) 'SCL = 1, SDA = 0 (0000 0001)
'FOR m = 1 TO 5 : NEXT m
Sleep(5)
Out32 ((LPT1 + 0x02), 0x03) 'SCL = 0, SDA = 0 (0000 0011)
RETURN
ENDSUB
SUB i2c_NoAck()
Out32 ((LPT1 + 0x02), 0x02) 'SCL = 0, SDA = 1 (0000 0010)
Out32 ((LPT1 + 0x02), 0x00) 'SCL = 1, SDA = 1 (0000 0000)
'FOR m = 1 TO 5 : NEXT m
Sleep(5)
Out32 ((LPT1 + 0x02), 0x02) 'SCL = 0, SDA = 1 (0000 0010)
RETURN
END SUB
SUB i2c_Write(DataWoord AS CHAR)
DEF BitWoord : CHAR
DEF PortWoord : CHAR
DEF n : CHAR
BitWoord = 0x80
FOR n = 1 TO 8
IF (DataWoord & BitWoord) = BitWoord THEN
PortWoord = 0x02 '(0000 0010)
ELSE
PortWoord = 0x03 '(0000 0011)
END IF
Out32 ((LPT1 + 0x02), PortWoord) ' SDA = setten
Out32 ((LPT1 + 0x02), PortWoord - 0x02) ' SCL = HOOG
Sleep(5)
'FOR m = 1 TO 5 : NEXT m ' delay loop
Out32 ((LPT1 + 0x02), PortWoord) ' SCL = reset
Out32 ((LPT1 + 0x02), BitWoord >> 0x01) '
NEXT n
Out32 ((LPT1 + &H02), 0x02) 'SCL = 0, SDA = 1 (0000 0010)
Out32 ((LPT1 + &H02), 0x00) 'SCL = 1, SDA = read (0000 0000)
Sleep(5)
'FOR m = 1 TO 5 : NEXT m ' delay loop
IF (Inp32(LPT1 + 0x02) & 0x01) = 0 THEN PRINT "IC Antwoord niet"
Out32 ((LPT1 + &H02), 0x02) 'SCL = 0, SDA = 1 (0000 0010)
RETURN
END SUB
SUB i2c_Read(), CHAR
DEF BitWoord : CHAR
DEF DataWoord : CHAR
DEF n : CHAR
Out32 ((LPT1 + 0x02), 0x02) 'SCL = 0, SDA = 1 (0000 0010)
BitWoord = 0x80
DataWoord = 0x00
FOR n = 1 TO 8
Out32 ((LPT1 + 0x02), 0x00) 'SCL = 1, SDA = 1 (0000 0000)
Sleep(5)
'FOR m = 1 TO 5 : NEXT m ' delay loop
IF (Inp32(LPT1 + 0x02) & 0x01) = 0 THEN
DataWoord += BitWoord
END IF
Out32 ((LPT1 + 0x02), 0x02) 'SCL = 0, SDA = 1 (0000 0010)
BitWoord = BitWoord >> 0x01
NEXT n
RETURN DataWoord
ENDSUB
include file
DECLARE IMPORT, i2c_Init()
DECLARE IMPORT, i2c_Start()
DECLARE IMPORT, i2c_Stop()
DECLARE IMPORT, i2c_Ack()
DECLARE IMPORT, i2c_NoAck()
DECLARE IMPORT, i2c_Write(DataWoord AS CHAR)
DECLARE IMPORT, i2c_Read(), CHAR
CONST LPT1 = 0x378
CONST LPT2 = 0x278
CONST LPT3 = 0x3BC
CONST STROBE = 0x01
CONST AUTO_FEED = 0x02
CONST INIT = 0x04
CONST SLCTIN = 0x08
CONST ERROR = 0x08
CONST SELECTS = 0x10
CONST PE = 0x20
CONST ACK = 0x40
CONST BUSY = 0x80