I2C slave problem
Indisputable Attitude
Posts: 10
I'm trying to get an I2C slave module working on the SX, and I can't seem to get it right at all. I manually typed in the Guenther Daubach program and ran it, in Debug mode, and I got this message:
"Bit_Co is not a valid integer"
So, I just try to run the program in "Run" mode, and all that happens is the heat sink gets really hot. I have 4 LED's connected to PORTB's lower 4 bits so that I can see the counting up. But... nothing.
I also have a very minimal data analyzer hooked up, and I don't see anything going on.
Could someone please give me some tips?
I don't need any wires hooked up to SDA and SCL, do I? Besides the data analyzer, I mean. Are all my settings OK for it to
send data to itself? I'm still kind of unsure about DeviceType. It can only be a 1 or a 0, so if you are trying to prioritize which Master has priority on the bus, you're not getting much of a selection there.
Also, like I said, I have 4 LED's hooked up to portB, so I can see it work. Maybe I didn't put that data line in the right spot???
Thanks for any and all help.
[noparse][[/noparse]code];==================================
; Programming the SX Microcontroller
; App025.src
;=======================================
include "Setup28.inc"
;--Modify these definitions as needed
;
SELF_TEST equ 1
SCOPE equ 1
DEV_TYPE equ 1
DEV_ID equ 3
BIT_COUNT equ 16
WAIT_IDLE equ 4
REPEAT_SEND equ 5
I2C_PORT equ ra
SCL_BIT equ 0
SDA_BIT equ 1
I2C_BIT_MASK equ %11111100
INT_PERIOD equ 125
;
;-- Internal definitions
ifdef SELF_TEST
DEV_ADDR equ ((DEV_TYPE * 8) + DEV_ID) * 16
else
DEV_ADDR equ (((1-DEV_TYPE) * 8) + DEV_ID) * 16
endif
; DEV_ADDR equ 0xA0
TRIS equ 00fh
LVL equ 00dh
INT_ON equ %10011110 ;Enable RTCC interrupt
SCL equ I2C_PORT.SCL_BIT
SDA equ I2C_PORT.SDA_BIT
SDA_LOW macro
clrb TrisMask.SDA_BIT
endm
SDA_HIGH macro
setb TrisMask.SDA_BIT
endm
SCL_LOW macro
clrb TrisMask.SCL_BIT
endm
SCL_HIGH macro
setb TrisMask.SCL_BIT
endm
SkipIfNotSda macro
snb SDA
endm
SkipIfScl macro
sb SCL
endm
SkipIfNotScl macro
snb SCL
endm
StartTx macro
setb Flags.0
endm
StopTx macro
clrb Flags.0
endm
SkipIfTxNotBusy macro
snb Flags.0
endm
SetTxError macro
setb Flags.1
endm
ClrTxError macro
clrb Flags.1
endm
SkipIfNoTxError macro
snb Flags.1
endm
SetRxData macro
setb Flags.2
endm
ClrRxData macro
clrb Flags.2
endm
SkipIfNoRxData macro
snb Flags.2
endm
;-- Global Variables
org $08
Flags ds 1
DevAddr ds 1
Timer ds 3
;--Variables for the I2C master
org $50
I2C_Tx equ $
TxData ds 2
TxBuffer ds 2
TxState ds 1
TxSubState ds 1
TxRepeat ds 1
TxBitCount ds 1
TxTimer ds 1
TrisMask ds 1
TxTimeout ds 1
;--Varibles for the I2C slave
org $70
I2C_Rx equ $
RxData ds 2
RxBitCount ds 1
RxState ds 1
RxSubState ds 1
RxTimeout ds 1
;--ISR
org $00
call @I2CTX
call @I2CRX
bank I2C_Tx
and I2C_PORT, #I2C_BIT_MASK
mov !I2C_PORT, TrisMask
mov w, #-INT_PERIOD
retiw
;--Initialize the ports
InitPorts
mode TRIS
mov !rb, #%11110000
mode LVL
mov w, #%11111100
mov !I2C_PORT, w
mode TRIS
ifdef SCOPE
mov !rc, #%11111110
endif
ret
org $100
Start ;Mainline program
include "Clr2x.inc"
call InitPorts
mov DevAddr, #DEV_ADDR
bank I2C_Tx
mov TxData, DevAddr
mov TrisMask, #I2C_BIT_MASK
setb TrisMask.SCL_BIT
setb TrisMask.SDA_BIT
mov !I2C_PORT, TrisMask
mov !option, #INT_ON
mov Timer+1, #5
Main ;Main Program Loop
SkipIfNoRxData
;nop
;mov rb, RxData + 1
SkipIfTxNotBusy
jmp Main
[noparse]:D[/noparse]elay
decsz Timer
jmp [noparse]:D[/noparse]elay
StartTx
decsz Timer+1
jmp Main
add TxData+1, #1
addb TxData, c
and TxData, #$0f
or TxData, DevAddr
jmp Main
org $200
;--I2C master
bank I2C_Tx
ClockHigh
SCL_HIGH
inc TxSubState
retp
ClockLow
ifdef SCOPE
clrb rc.0
endif
SCL_LOW
inc TxSubState
retp
DataHigh
SDA_HIGH
inc TxSubState
retp
WaitClockHigh;
SkipIfNotScl
inc RxSubState
retp
I2CTX ;I2C Master
mov w, TxState
jmp pc + w
:TxIdle
jmp :Idle
:TxInit
jmp :InitSend
jmp :SetStart
jmp :SendData
jmp :GetAck
jmp :SetStop
:TxError
jmp :HandleError
:Idle
mov TxRepeat, #REPEAT_SEND+1
SDA_HIGH
SCL_HIGH
SkipIfTxNotBusy
inc TxState
retp
:InitSend
mov TxBuffer, TxData
mov TxBuffer+1, TxData+1
ifdef SCOPE
setb rc.0
endif
mov TxBitCount, #BIT_COUNT
ClrTxError
clr TxTimeout
clr TxSubState
inc TxState
retp
:SetStart
mov w, TxSubState
jmp pc+w
jmp :StartInit
jmp :WaitIdle
:StartInit
SCL_HIGH
SDA_HIGH
mov TxTimer, #WAIT_IDLE
inc TxSubState
retp
:WaitIdle
dec TxTimeout
snz
jmp :HandleError
sb SCL
jmp :NotIdle
sb SDA
jmp :NotIdle
dec TxTimer
sz
retp
clr TxTimeout
SDA_LOW
clr TxSubState
inc TxState
retp
:NotIdle
mov TxTimer, #4
retp
:SendData
mov w, TxSubState
jmp pc+w
jmp ClockLow
jmp :SetDataBit
jmp ClockHigh
jmp :CheckClockHigh
:SetDataBit
SDA_HIGH
sb TxBuffer.7
SDA_LOW
inc TxSubState
retp
:CheckClockHigh
dec TxTimeout
snz
jmp :HandleError
sb SCL
retp
sb TxBuffer.7
jmp :PrepareNext
SkipIfNotSda
jmp :PrepareNext
mov TxState, #(:TxError-:TxIdle)
retp
:PrepareNext
clr TxTimeout
rl TxBuffer + 1
rl TxBuffer
clr TxSubState
dec TxBitCount
sz
retp
inc TxState
retp
:GetAck
mov w, TxSubState
jmp pc+w
jmp ClockLow
jmp DataHigh
jmp ClockHigh
jmp :CheckClockHighAck
:CheckClockHighAck
dec TxTimeout
snz
jmp :HandleError
sb SCL
retp
inc TxState
clr TxSubState
SkipIfNotSda
SetTxError
retp
:SetStop
mov w, TxSubState
jmp pc+w
jmp ClockLow
jmp [noparse]:D[/noparse]ataLow
jmp ClockHigh
jmp DataHigh
jmp DataHigh
jmp :TxFinish
[noparse]:D[/noparse]ataLow
SDA_LOW
inc TxSubState
retp
:TxFinish
inc TxState
SkipIfNoTxError
retp
clr TxState
StopTx
retp
:HandleError
SCL_HIGH
SDA_HIGH
clr TxSubState
clr TxState
dec TxRepeat
mov w, #(:TxInit - :TxIdle)
sz
mov TxState, w
StopTx
SetTxError
retp
org $400
I2CRX
bank I2C_Rx
SkipIfNoRxData
retp
dec RxTimeout
snz
jmp :RxError
mov w, RxState
jmp pc+w
jmp :RxDetectStart
jmp :RxGetBits
jmp :RxSendAck
:RxDetectStart
mov w, RxSubState
jmp pc + w
jmp :WaitSdaHigh
jmp :WaitSdaLow
:WaitSdaHigh
SkipIfNotSda
inc RxSubState
retp
:WaitSdaLow
SkipIfNotSda
retp
SkipIfScl
jmp :RxError
mov RxBitCount, #BIT_COUNT
clr RxSubState
inc RxState
retp
:RxGetBits
mov w, RxSubState
jmp pc+w
jmp :WaitClockHigh
jmp :GetDataBit
:GetDataBit
clc
SkipIfNotSda
stc
rl RxData +1
rl RxData
decsz RxBitCount
jmp :SetupNext
clr RxSubState
inc RxState
retp
:SetupNext
dec RxSubState
retp
:RxSendAck
mov w, RxSubState
jmp pc+w
jmp :WaitClockLowAck
jmp :WaitClockHigh
jmp :WaitClockLow
:WaitClockLowAck
SkipIfNotScl
retp
mov w, RxData
ifndef SELF_TEST
xor w, #%10000000
endif
bank I2C_Tx
and w, #$f0
mov w, DevAddr-w
snz
SDA_LOW
bank I2C_Rx
inc RxSubState
retp
:WaitClockHigh
SkipIfNotScl
inc RxSubState
retp
:WaitClockLow
SkipIfNotScl
retp
ifndef SELF_TEST
bank I2C_Tx
SDA_HIGH
bank I2C_Rx
endif
SetRxData
:RxError
clr RxState
clr RxSubState
clr RxTimeout
retp
RESET Main
"Bit_Co is not a valid integer"
So, I just try to run the program in "Run" mode, and all that happens is the heat sink gets really hot. I have 4 LED's connected to PORTB's lower 4 bits so that I can see the counting up. But... nothing.
I also have a very minimal data analyzer hooked up, and I don't see anything going on.
Could someone please give me some tips?
I don't need any wires hooked up to SDA and SCL, do I? Besides the data analyzer, I mean. Are all my settings OK for it to
send data to itself? I'm still kind of unsure about DeviceType. It can only be a 1 or a 0, so if you are trying to prioritize which Master has priority on the bus, you're not getting much of a selection there.
Also, like I said, I have 4 LED's hooked up to portB, so I can see it work. Maybe I didn't put that data line in the right spot???
Thanks for any and all help.
[noparse][[/noparse]code];==================================
; Programming the SX Microcontroller
; App025.src
;=======================================
include "Setup28.inc"
;--Modify these definitions as needed
;
SELF_TEST equ 1
SCOPE equ 1
DEV_TYPE equ 1
DEV_ID equ 3
BIT_COUNT equ 16
WAIT_IDLE equ 4
REPEAT_SEND equ 5
I2C_PORT equ ra
SCL_BIT equ 0
SDA_BIT equ 1
I2C_BIT_MASK equ %11111100
INT_PERIOD equ 125
;
;-- Internal definitions
ifdef SELF_TEST
DEV_ADDR equ ((DEV_TYPE * 8) + DEV_ID) * 16
else
DEV_ADDR equ (((1-DEV_TYPE) * 8) + DEV_ID) * 16
endif
; DEV_ADDR equ 0xA0
TRIS equ 00fh
LVL equ 00dh
INT_ON equ %10011110 ;Enable RTCC interrupt
SCL equ I2C_PORT.SCL_BIT
SDA equ I2C_PORT.SDA_BIT
SDA_LOW macro
clrb TrisMask.SDA_BIT
endm
SDA_HIGH macro
setb TrisMask.SDA_BIT
endm
SCL_LOW macro
clrb TrisMask.SCL_BIT
endm
SCL_HIGH macro
setb TrisMask.SCL_BIT
endm
SkipIfNotSda macro
snb SDA
endm
SkipIfScl macro
sb SCL
endm
SkipIfNotScl macro
snb SCL
endm
StartTx macro
setb Flags.0
endm
StopTx macro
clrb Flags.0
endm
SkipIfTxNotBusy macro
snb Flags.0
endm
SetTxError macro
setb Flags.1
endm
ClrTxError macro
clrb Flags.1
endm
SkipIfNoTxError macro
snb Flags.1
endm
SetRxData macro
setb Flags.2
endm
ClrRxData macro
clrb Flags.2
endm
SkipIfNoRxData macro
snb Flags.2
endm
;-- Global Variables
org $08
Flags ds 1
DevAddr ds 1
Timer ds 3
;--Variables for the I2C master
org $50
I2C_Tx equ $
TxData ds 2
TxBuffer ds 2
TxState ds 1
TxSubState ds 1
TxRepeat ds 1
TxBitCount ds 1
TxTimer ds 1
TrisMask ds 1
TxTimeout ds 1
;--Varibles for the I2C slave
org $70
I2C_Rx equ $
RxData ds 2
RxBitCount ds 1
RxState ds 1
RxSubState ds 1
RxTimeout ds 1
;--ISR
org $00
call @I2CTX
call @I2CRX
bank I2C_Tx
and I2C_PORT, #I2C_BIT_MASK
mov !I2C_PORT, TrisMask
mov w, #-INT_PERIOD
retiw
;--Initialize the ports
InitPorts
mode TRIS
mov !rb, #%11110000
mode LVL
mov w, #%11111100
mov !I2C_PORT, w
mode TRIS
ifdef SCOPE
mov !rc, #%11111110
endif
ret
org $100
Start ;Mainline program
include "Clr2x.inc"
call InitPorts
mov DevAddr, #DEV_ADDR
bank I2C_Tx
mov TxData, DevAddr
mov TrisMask, #I2C_BIT_MASK
setb TrisMask.SCL_BIT
setb TrisMask.SDA_BIT
mov !I2C_PORT, TrisMask
mov !option, #INT_ON
mov Timer+1, #5
Main ;Main Program Loop
SkipIfNoRxData
;nop
;mov rb, RxData + 1
SkipIfTxNotBusy
jmp Main
[noparse]:D[/noparse]elay
decsz Timer
jmp [noparse]:D[/noparse]elay
StartTx
decsz Timer+1
jmp Main
add TxData+1, #1
addb TxData, c
and TxData, #$0f
or TxData, DevAddr
jmp Main
org $200
;--I2C master
bank I2C_Tx
ClockHigh
SCL_HIGH
inc TxSubState
retp
ClockLow
ifdef SCOPE
clrb rc.0
endif
SCL_LOW
inc TxSubState
retp
DataHigh
SDA_HIGH
inc TxSubState
retp
WaitClockHigh;
SkipIfNotScl
inc RxSubState
retp
I2CTX ;I2C Master
mov w, TxState
jmp pc + w
:TxIdle
jmp :Idle
:TxInit
jmp :InitSend
jmp :SetStart
jmp :SendData
jmp :GetAck
jmp :SetStop
:TxError
jmp :HandleError
:Idle
mov TxRepeat, #REPEAT_SEND+1
SDA_HIGH
SCL_HIGH
SkipIfTxNotBusy
inc TxState
retp
:InitSend
mov TxBuffer, TxData
mov TxBuffer+1, TxData+1
ifdef SCOPE
setb rc.0
endif
mov TxBitCount, #BIT_COUNT
ClrTxError
clr TxTimeout
clr TxSubState
inc TxState
retp
:SetStart
mov w, TxSubState
jmp pc+w
jmp :StartInit
jmp :WaitIdle
:StartInit
SCL_HIGH
SDA_HIGH
mov TxTimer, #WAIT_IDLE
inc TxSubState
retp
:WaitIdle
dec TxTimeout
snz
jmp :HandleError
sb SCL
jmp :NotIdle
sb SDA
jmp :NotIdle
dec TxTimer
sz
retp
clr TxTimeout
SDA_LOW
clr TxSubState
inc TxState
retp
:NotIdle
mov TxTimer, #4
retp
:SendData
mov w, TxSubState
jmp pc+w
jmp ClockLow
jmp :SetDataBit
jmp ClockHigh
jmp :CheckClockHigh
:SetDataBit
SDA_HIGH
sb TxBuffer.7
SDA_LOW
inc TxSubState
retp
:CheckClockHigh
dec TxTimeout
snz
jmp :HandleError
sb SCL
retp
sb TxBuffer.7
jmp :PrepareNext
SkipIfNotSda
jmp :PrepareNext
mov TxState, #(:TxError-:TxIdle)
retp
:PrepareNext
clr TxTimeout
rl TxBuffer + 1
rl TxBuffer
clr TxSubState
dec TxBitCount
sz
retp
inc TxState
retp
:GetAck
mov w, TxSubState
jmp pc+w
jmp ClockLow
jmp DataHigh
jmp ClockHigh
jmp :CheckClockHighAck
:CheckClockHighAck
dec TxTimeout
snz
jmp :HandleError
sb SCL
retp
inc TxState
clr TxSubState
SkipIfNotSda
SetTxError
retp
:SetStop
mov w, TxSubState
jmp pc+w
jmp ClockLow
jmp [noparse]:D[/noparse]ataLow
jmp ClockHigh
jmp DataHigh
jmp DataHigh
jmp :TxFinish
[noparse]:D[/noparse]ataLow
SDA_LOW
inc TxSubState
retp
:TxFinish
inc TxState
SkipIfNoTxError
retp
clr TxState
StopTx
retp
:HandleError
SCL_HIGH
SDA_HIGH
clr TxSubState
clr TxState
dec TxRepeat
mov w, #(:TxInit - :TxIdle)
sz
mov TxState, w
StopTx
SetTxError
retp
org $400
I2CRX
bank I2C_Rx
SkipIfNoRxData
retp
dec RxTimeout
snz
jmp :RxError
mov w, RxState
jmp pc+w
jmp :RxDetectStart
jmp :RxGetBits
jmp :RxSendAck
:RxDetectStart
mov w, RxSubState
jmp pc + w
jmp :WaitSdaHigh
jmp :WaitSdaLow
:WaitSdaHigh
SkipIfNotSda
inc RxSubState
retp
:WaitSdaLow
SkipIfNotSda
retp
SkipIfScl
jmp :RxError
mov RxBitCount, #BIT_COUNT
clr RxSubState
inc RxState
retp
:RxGetBits
mov w, RxSubState
jmp pc+w
jmp :WaitClockHigh
jmp :GetDataBit
:GetDataBit
clc
SkipIfNotSda
stc
rl RxData +1
rl RxData
decsz RxBitCount
jmp :SetupNext
clr RxSubState
inc RxState
retp
:SetupNext
dec RxSubState
retp
:RxSendAck
mov w, RxSubState
jmp pc+w
jmp :WaitClockLowAck
jmp :WaitClockHigh
jmp :WaitClockLow
:WaitClockLowAck
SkipIfNotScl
retp
mov w, RxData
ifndef SELF_TEST
xor w, #%10000000
endif
bank I2C_Tx
and w, #$f0
mov w, DevAddr-w
snz
SDA_LOW
bank I2C_Rx
inc RxSubState
retp
:WaitClockHigh
SkipIfNotScl
inc RxSubState
retp
:WaitClockLow
SkipIfNotScl
retp
ifndef SELF_TEST
bank I2C_Tx
SDA_HIGH
bank I2C_Rx
endif
SetRxData
:RxError
clr RxState
clr RxSubState
clr RxTimeout
retp
RESET Main
Comments
It sounds like the SX28 is supposed to be a slave device. What device is the master and what are you trying to send to it. How are they connected? Are you trying to send data to a pin configured as a output instead of an input?
A schematic would only show a Parallax protoboard with 4 LED's coming out of port b with 4 4700 ohm resistors used to keep each LED from "letting the smoke out".
The heatsink on the Parallax protoboard sold by Parallax. There's just 4 LED's connected to port b's lowest 4 bits, that's all right now. The program is supposed to be able to send a message to itself, according to the book by Mr. Daubach. Later on, after I get it talking to itself, I'll disable the Master I2C section, and just have the Slave part running. A PIC16F690 will be the Master. Later on, the SX will be the slave only, rather than a master and a slave at the same time.
I've been fiddling around with this for a while, and before on a different setup, with it connected to the PIC16f690, I tried using the SXBasic software but that didn't work either. The PIC sent out a nice I2C wave packet, but when I hooked it up to the SX, it got all messy.
I'd rather use the SX assembly I2C, because the rest of the program will be in assembly. Here's how the waveforms look using SXB, and the following very simple code:
Like I said, though, I'd rather do the whole program in SX assembly.
Post Edited (Indisputable Attitude) : 3/12/2010 8:24:06 PM GMT
I just don't know why the SX software doesn't grab the data packets. Does anyone have a copy of Guenther Daubach's program that is confirmed OK? Is it possible that the problem has something to do with the Debug error message?
I don't get that either. Why would the Debug come up with an error, and then gray-out the Run button, but I can run the program no problem when I run it by hitting Control-A?
Someone out there PLZ help.
A couple things come to mind regarding the debug issue. That is usually grayed out when ever the resonator is left in the circuit. If you are using a resonator it must be pulled out for debugging to work. For programming and normal operation it can be left in place. Are you using a 4Mhz resonator? If so are you leaving the SX-key plugged in after programming? Another question is if you are using the older Serial version of the SX-Key or the newer USB version.
I went back and searched the SX forum and found some threads talking about I2C which may help:
http://forums.parallax.com/forums/default.aspx?f=7&m=333732
http://forums.parallax.com/forums/default.aspx?f=7&m=312895
http://forums.parallax.com/forums/default.aspx?f=7&m=269425
http://forums.parallax.com/forums/default.aspx?f=7&m=236034
http://forums.parallax.com/forums/default.aspx?f=7&m=252244
The SX/B code changed a bit with newer versions of the compiler. Depending upon what version you're using that may be a factor.
http://www.sxlist.com/techref/scenix/lib/io/osi2/i2c/i2c_slave.src
I really am using 4700 ohm resistors with the LED's. I can still see them just fine for testing purposes, and I know I'm way under the current maximum, even without having to do a calculation.
I have an older 9-pin D-sub connector style SX-Key, that says, "Revision F" on it. I've run many programs on it without any problems. I've pulled the oscillator out, so that can't be the problem.
Still, the program seems to be doing something when I use the I2C example in the "Programming the SX Microcontroller" book. I was hoping someone would find a line out of place.
BTW... in the i2cs.src program, he allows you to choose whichever two port pins you want. But... isn't the SX hardware set up so that only PortB can trigger interrupts? So wouldn't that mean that I can't use PortA?
Anyway, thanks for the tips and advice, please keep them coming. I'll post in this thread after I run the i2cs.src program.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-MH