PDA

View Full Version : Using SPI with External Interrupts



shaiqbashir
- 29th June 2008, 04:08
hi guys!

im making a project that has two PIC18f452. one pic is acting as SPI master, the other is acting as SPI slave. The master makes portB.0 of SPI slave low which it takes as INT0 interrupt. then master sends "?" through SPI, in return slave has to send "!" after which the master will send its data through SPI to slave. before using external interrupt(INT0), the SPI communication was working well. But when i enabled this interrupt, the slave is not sending the "!" to the master as a result master is unable to send its data to slave through SPI. Here is my coding of master:



Include "Modedefs.Bas"

DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_BAUD 9600
DEFINE HSER_SPBRG 25

define OSC 4

DEFINE ADC_BITS 8 ' Set number of bits in result
DEFINE ADC_CLOCK 2 ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in microseconds

' Set LCD Data port
DEFINE LCD_DREG PORTD
' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_DBIT 0
' Set LCD Register Select port
DEFINE LCD_RSREG PORTC
' Set LCD Register Select bit
DEFINE LCD_RSBIT 0
' Set LCD Enable port
DEFINE LCD_EREG PORTC
' Set LCD Enable bit
DEFINE LCD_EBIT 1
' Set LCD bus size (4 or 8 bits)
DEFINE LCD_BITS 8
' 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

SSPEN VAR SSPCON1.5 'SSP Enable bit
CKP VAR SSPCON1.4 'Clock Polarity Select
SMP VAR SSPSTAT.7 'Data input sample phase
CKE VAR SSPSTAT.6 'Clock Edge Select bit
SSPIF VAR PIR1.3 'SPI interrupt flag

i VAR BYTE 'loop counter
a VAR byte[6] 'Holds 6 characters read from slave
b VAR byte[6] 'Holds 6 characters read from slave
c var byte[6] 'Holds 6 characters read from slave

ADCON1 = 7 'Set PORTA and PORTE to digital
Low PORTE.2 'LCD R/W line low (W)
Pause 100 'Wait for LCD to start up

TRISC = %10010000 'set PORTC I/O

SSPEN = 1 'enable SPI pins
CKP = 0 'clock idle low
CKE = 0 'transmit on idle to active transition
SSPIF = 0 'clear buffer full status
SMP = 0 'sample in middle of data
SSPCON1.0 = 0
SSPCON1.1 = 0
SSPCON1.2 = 0
SSPCON1.3 = 0

loop:
high portB.0
HSERIN [WAIT("a"),STR a\4\"\"]
pause 50
hserout["ok",13,10]
pause 50
HSERIN [WAIT("a"),STR b\4\"\"]
pause 50
hserout["ok",13,10]
pause 50
HSERIN [WAIT("a"),STR c\4\"\"]
pause 50
hserout["ok",13,10]
pause 50
low portB.0
GoSub senddata 'initiate conversion and receive data
GoTo loop 'do it forever

senddata:
SSPBUF = "?" 'send ? to start conversion
hserout["? sent",13,10]
GoSub letclear 'wait for buffer to clear
IF SSPBUF<>"!" Then senddata 'wait for reply (!)

For i = 0 to 4 'loop for 6 characters
SSPBUF = 0 'write to SSPBUF to start clock
GoSub letclear 'wait for receipt
SSPBUF=a[i] 'store received character in array
Next i 'get next character

For i = 0 to 4 'loop for 6 characters
SSPBUF = 0 'write to SSPBUF to start clock
GoSub letclear 'wait for receipt
SSPBUF=b[i] 'store received character in array
Next i

For i = 0 to 4 'loop for 6 characters
SSPBUF = 0 'write to SSPBUF to start clock
GoSub letclear 'wait for receipt
SSPBUF=c[i] 'store received character in array
Next i

Return

letclear:

IF SSPIF = 0 Then letclear 'wait for SPI interupt flag
PauseUs 25 '25uS fudge factor
SSPIF = 0 'reset flag
Return



and here is my coding for the slave:



Include "Modedefs.Bas"

DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_BAUD 9600
DEFINE HSER_SPBRG 25

define osc 4

DEFINE ADC_BITS 8 ' Set number of bits in result
DEFINE ADC_CLOCK 8 ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in microseconds

dataout VAR BYTE[8] 'Data out array
dataout2 var byte[8]
dataout3 var byte[8]

SSPEN VAR SSPCON1.5 'SSP Enable bit
CKP VAR SSPCON1.4 'Clock Polarity Select
SMP VAR SSPSTAT.7 'Data input sample phase
CKE VAR SSPSTAT.6 'Clock Edge Select bit
SSPIF VAR PIR1.3 'interrupt flag - last bit set

SCL Var PortB.6 ' I2C data pin
SDA Var PortB.7 ' I2C clock pin

i VAR BYTE 'loop counter
a VAR BYTE[6] 'Holds 6 characters of data
addr var word
E_ByteOut Var Byte ' Data byte to be written to the Eeprom
E_ByteIn Var Byte
b var byte
c var byte

Define I2C_SCLOUT 1

on interrupt goto DECIDE
INTCON.7=1
INTCON.6=1
INTCON.4=1
INTCON2.7=0
INTCON2.6=0
INTCON2.4=0
INTCON2.5=0
INTCON3.7=0
INTCON3.6=1
INTCON3.4=1
INTCON3.3=1


find:
HIGH PORTC.1
PAUSE 100
LOW PORTC.1
PAUSE 100
goto find



TRISC = %11011111 'set PORTC I/O
SSPCON1 = %00000101 'configure SPI slave, no SS

CKP = 0 'clock idle low
CKE = 0 'transmit on idle to active transition
SSPIF = 0 'clear SPI interrupt
SMP = 0 'sample in middle of data

ADCON1 = $00 'PORTA.0 analog, rest PORTA and PORTE pins to digital

loop:
DISABLE
toggle intcon2.6
intcon.1=0
if portB.0=0 then HSEROUT["INT1 CONNECTED ",13,10]
if portB.0=1 then HSEROUT["INT1 REMOVED ",13,10]
hserout["hello",13,10]
gosub letclear
SSPEN = 0 'disable/enable SSP to reset port
hserout["hello1",13,10]
SSPEN = 1
'hserout["hello2",13,10]
hserout["ok",13,10]
GoSub letclear 'wait for byte received
IF (SSPBUF <> "?") Then loop 'wait for ? to start conversion
hserout["? received",13,10]
GoSub getdata 'send "!" and string of data

hserout[str dataout\5,13,10]
hserout[str dataout2\5,13,10]
hserout[str dataout3\5,13,10]
b=0
c=0

for addr=0 to 5
e_byteout=dataout[addr]
hserout[E_byteout,13,10]
gosub EWrite
next

for addr=6 to 11
e_byteout=dataout2[b]
b=b+1
hserout[E_byteout,13,10]
gosub EWrite
next

for addr=12 to 17
e_byteout=dataout3[c]
c=c+1
hserout[E_byteout,13,10]
gosub EWrite
next

pause 1000

for addr=0 to 17
a[addr]=E_bytein
gosub ERead
next

hserout[str a\18,13,10]
hserout["read done",13,10]

resume
enable
GoTo loop 'do it forever

getdata:
GoSub letclear 'wait until buffer ready
SSPBUF = "!" 'send reply
gosub letclear
SSPBUF = 0

For i = 0 to 4 'loop for 6 array locations
gosub letclear 'wait until buffer ready
dataout[i]=SSPBUF 'send array variable
Next i 'next location

For i = 0 to 4 'loop for 6 array locations
gosub letclear 'wait until buffer read
dataout2[i]=SSPBUF 'send array variable
Next i

For i = 0 to 4 'loop for 6 array locations
gosub letclear 'wait until buffer read
dataout3[i]=SSPBUF 'send array variable
Next i

Return

letclear:
hserout["letclear entered",13,10]
IF SSPIF = 0 Then letclear 'wait for interrupt flag
pauseus 25
hserout["sspif",13,10]
SSPIF = 0 'reset flag
hserout["return",13,10]
Return

EWrite:
I2CWRITE SDA,SCL,%10100000,Addr,[E_ByteOut] ' Write out the byte
Pause 10 ' Delay 10ms after each write
Return


ERead:
I2CREAD SDA,SCL,%10100000,Addr,[E_ByteIn] ' Read in the byte
Return

myint2:
hserout["int 2 is not defined",13,10]
goto find

myint3:
hserout["int 3 is not defined",13,10]
goto find

decide:
disable
if intcon.1=1 then loop
if intcon3.0=1 then myint2
if intcon3.1=1 then myint3



One very important thing that i want to tell you in the slave program is this, that if you see the loop label in this program, the control successfuly displays "INT1 connected" then "hello", then "hello1", then "hello2", then "ok" but then when it comes to GOSUB letclear statement, it doesnt executes it at all. and nothing happens then. PLease see what is the problem,