jimbostlawrence
- 20th October 2011, 14:39
Hi,
I'm having trouble with a PIC18LF45K22 and a 1GB SD card.
I've been looking at the SDFS file and tried to write directly to the SD card which has already been formatted FAT16. I've managed to have it initialise the card, set the block length etc and send out 512 bytes of data to a sector, it then reads that sector and displays the ASCII (sends data/response via RS232 to RealTerm).
2 issues:
1. When I write to the card, and it reads the same sector back, if I then place this card in my laptop and use a hexeditor, I cannot find the string ANYWHERE!!! But I know it's on the card as I've written to different sectors and stuff from previous hours remains!
2. If I issue a second readsector command (say for instance I wanted to read consecutive sectors, or even re-read the same sector) I get a non-zero SDC_response value and the routine fails!
I feel I've done pretty well here but my head is getting sore!
If I post the code here, is there any chance someone could have a look please?
Many thanks in advance
Jimbo
define OSC 16
DEFINE HSER_BAUD 19200
DEFINE HSER_CLROERR 1 ' Auto clear over-run errors
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 20h
OSCCON = OSCCON | %01110000 ' set internal clock to 16 MHz incase of switchover
SDI Var PORTC.4 ' SPI data in
SDI_TRIS Var TRISC.4 ' SPI data in direction
SCL Var PORTC.3 ' SPI clock
SCL_TRIS Var TRISC.3 ' SPI clock direction
SD_CS Var PORTA.5 ' SD card chip select
SD_CS_TRIS Var TRISA.5 ' SD card chip select direction
SD_CD Var PORTB.4 ' SD card detect
SD_CD_TRIS Var TRISB.4 ' SD card detect direction
SDO Var PORTC.5 ' SPI data out
SDO_TRIS Var TRISC.5 ' SPI data out direction
i2cSDA VAR PORTD.1
i2cSCL VAR PORTD.0
SSPEN Var SSPCON1.5 ' SSP enable
WCOL Var SSPCON1.7 ' SSP write collision
BF Var SSPSTAT.0 ' SSP buffer full
SSPIF Var PIR1.3 ' SSP interrupt flag
accx var byte
accx2 var byte
accx_axis var word
fail var byte
read_loop var byte
NODATA Con 0
MOREDATA Con 1
MEDIA_SECTOR_SIZE Con 512
FAT_BUFFER_SIZE Con MEDIA_SECTOR_SIZE
' Indexes into command table
GO_IDLE_STATE Con 0
SEND_OP_COND Con 1
SET_BLOCKLEN Con 2
READ_SINGLE_BLOCK Con 3
WRITE_SINGLE_BLOCK Con 4
CRC_ON_OFF Con 5
sdcCardDataRejected Con 8
SDC_address Var Long
SDC_buffer Var Byte[MEDIA_SECTOR_SIZE]
SDC_cmd Var Byte
SDC_CmdCode Var Byte
SDC_CRC Var Byte
SDC_data_in Var Byte
SDC_data_out Var Byte
SDC_index Var Word
SDC_moredataexpected Var Byte
SDC_response Var Byte
SDC_sector_addr Var Long
SDC_status Var Byte
SDC_timeout Var Long
SDC_timeout1 Var Word
sdcValid Con 0
sdcCardInitCommFailure Con 1
sdcCardNotInitFailure Con 2
sdcCardInitTimeout Con 3
FAT_error Var Byte
FAT_error = 0
DATA_START_TOKEN Con $fe
DATA_ACCEPTED Con $05
SDC_FLOATING_BUS Con $ff
SDC_BAD_RESPONSE Con SDC_FLOATING_BUS
FALSE Con 0
TRUE Con 1
'SDC_UseHardSPI Var Byte
'Include "SDFS.PBP"
trisa = %00000000
trisd = %00000000
trisc = %00000000
adcon0.0 = 0
ANSELA = 0
ANSELB = 0
ANSELC = 0
ANSELD = 0
ANSELE = 0
ADCON1 = 15 ' All I/O pins digital
pause 1000
I2CWRITE i2cSDA,i2cSCL, $a6, $2d, [0]
pauseus 5
I2CWRITE i2cSDA,i2cSCL, $a6, $2d, [16]
pauseus 5
I2CWRITE i2cSDA,i2cSCL, $a6, $2d, [8]
pauseus 5
I2CWRITE i2cSDA,i2cSCL, $a6, $31, [8]
pause 1000
i2cread i2cSDA,i2cSCL,$a7,50,[accx,accx2],error
accx_axis = accx+(accx2 &03)*256
hserout [$d,$a,#accx_axis,$d,$d]
fail = 0
'while (fail <5 & FAT_error != 0)
fail = fail+1
SD_CS = 1 ' SD card not selected.
SD_CS_TRIS = 0 ' Output SD card chip select.
SD_CD_TRIS = 1 ' Input card detect.
'SD_WE_TRIS = 1 ' Input write protect.
SDO = 1 ' Start SPI data out high.
SDO_TRIS = 0 ' Output SPI data out.
SDI_TRIS = 1 ' Input SPI data in.
SCL = 1 ' SPI clock idles high.
SCL_TRIS = 0 ' Output SPI clock.
pause 1
SSPSTAT = %00000000 ' Sample at middle of data output time, Mode 1, 1: Transmit on idle to active clock transition.
SSPCON1 = %00010010 ' SPI master mode, clock = Fosc/64, Mode 1, 1: Clock idle high.
SSPEN = 1 ' Enable hardware SPI port.
pause 1
For SDC_timeout1 = 1 To 10
hserout [$d,$a,"sdc timeout: ",#SDC_timeout1]
SDC_data_out = $ff ' Data pin must be high.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = SDC_data_out' Send the byte.
If (WCOL) Then Return' Check for write collision.
While !SSPIF ' Wait for send to complete.
Wend
Next SDC_timeout1
pause 1
hserout [$d,$a,"Go idle"]
SDC_cmd = GO_IDLE_STATE
SDC_address = 0
gosub send_receive_SD_loop
SDC_data_out = $ff ' Data pin must be high.
gosub write_byte
If (!SDC_moredataexpected) Then
SD_CS = 1
Endif
If (SDC_response = SDC_BAD_RESPONSE) Then
SDC_status = sdcCardInitCommFailure
Goto InitError
Endif
If ((SDC_response & $F7) != $01) Then
SDC_status = sdcCardNotInitFailure
Goto InitError
Endif
For SDC_timeout1 = $fff To 0 Step -1
hserout [$d,$a,"Op cond"]
SDC_cmd = SEND_OP_COND
SDC_address = 0
gosub send_receive_SD_loop
' Generate 8 clock cycles.
SDC_data_out = $ff ' Data pin must be high.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = SDC_data_out ' Send the byte.
If (WCOL) Then Return ' Check for write collision.
While !SSPIF ' Wait for send to complete.
Wend
If (!SDC_moredataexpected) Then
SD_CS = 1
Endif
If (SDC_response = $00) Then SDC_timeout1 = 0 ' Got a response, end the loop.
Next SDC_timeout1
If (SDC_response != $00) Then
SDC_status = sdcCardInitTimeout
Goto InitError
Endif
Pause 1
SSPSTAT = %00000000 ' Sample at middle of data output time, Mode 1, 1: Transmit on idle to active clock transition.
SSPCON1 = %00010000 ' SPI master mode, clock = Fosc/64, Mode 1, 1: Clock idle high.
SSPEN = 1
hserout [$d,$a,"CRC On/Off"]
SDC_cmd = CRC_ON_OFF
SDC_address = 0
gosub send_receive_SD_loop
SDC_data_out = $ff
gosub write_byte
If (!SDC_moredataexpected) Then
SD_CS = 1
Endif
hserout [$d,$a,"Set Block Length"]
SDC_cmd = SET_BLOCKLEN
SDC_address = MEDIA_SECTOR_SIZE
gosub send_receive_SD_loop
SDC_data_out = $ff
gosub write_byte
pause 1
'################################################# #############
'SectorWrite:
hserout[$d,$a,"Sector write"]
SDC_sector_addr = 200
SDC_cmd = WRITE_SINGLE_BLOCK
SDC_address = SDC_sector_addr << 9
gosub send_receive_SD_loop
If (SDC_response != 0) Then
hserout[$d,$a,"Not accepted!",$d,$a]
gosub stop_read
else
hserout[$d,$a,"Accepted!",$d,$a]
endif
SDC_data_out = DATA_START_TOKEN
Gosub write_byte
SDC_data_out = 72 'store 'HELLO'
Gosub write_byte
SDC_data_out = 69
Gosub write_byte
SDC_data_out = 76
Gosub write_byte
SDC_data_out = 76
Gosub write_byte
SDC_data_out = 79
Gosub write_byte
For SDC_index = 0 To (MEDIA_SECTOR_SIZE - 6)
hserout[$d,#SDC_index]
SDC_data_out = $47
Gosub write_byte
Next SDC_index
' Send the CRC bytes.
SDC_data_out = $ff
gosub write_byte ' Just sends 16 1s.
gosub write_byte
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Get the byte.
If ((SDC_data_in & $0f) != DATA_ACCEPTED) Then
SDC_status = sdcCardDataRejected
hserout[$d,$a,"Rejected!"]
gosub stop_read
Else
' The card is writing data into the storage media.
' Wait for the card to return non-zero (not busy) or a timeout.
For SDC_timeout = 0 To 10000
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Get the byte.
If (SDC_data_in != 0) Then
hserout[$d,$a,"Got a write response at ",#SDC_timeout]
SDC_timeout = 10000 ' Got a response, end the loop.
endif
Next SDC_timeout
hserout[$d,$a,"SDC data in = ",#SDC_data_in]
If (SDC_data_in = 0) Then
hserout[$d,$a,"SDC Card timeout"]
gosub stop_read
endif
Endif
SDC_data_out = $ff ' Data pin must be high.
gosub write_byte
SD_CS = 1
'################################################# #################
pause 1
for read_loop = 10 to 12
hserout[$d,$a,"SDC sector address: ",#read_loop]
gosub SectorRead
next read_loop
End
error:
HSEROUT["Error"]
RETURN
InitError:
HSEROUT [$d,$a,"Error unknown", $d, $a]
return
write_byte:
' Write Byte SDC_data_out.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = SDC_data_out ' Send the byte.
If (WCOL) Then
HSEROUT [$d,$a,"Error: collision", $d, $a]
Return ' Check for write collision.
endif
While !SSPIF ' Wait for send to complete.
Wend
return
write_SPI:
SD_CS = 0
Lookup SDC_cmd, [$40, $41, $50, $51, $58, $7b], SDC_CmdCode
Lookup SDC_cmd, [$95, $f9, $ff, $ff, $ff, $25], SDC_CRC
Lookup SDC_cmd, [NODATA, NODATA, NODATA, MOREDATA, MOREDATA, NODATA], SDC_moredataexpected
SDC_data_out = SDC_CmdCode
gosub write_byte
SDC_data_out = SDC_address.Byte3
gosub write_byte
SDC_data_out = SDC_address.Byte2
gosub write_byte
SDC_data_out = SDC_address.Byte1
gosub write_byte
SDC_data_out = SDC_address.Byte0
gosub write_byte
SDC_data_out = SDC_CRC
gosub write_byte
return
send_receive_SD_loop:
SD_CS = 0
pause 1
gosub write_SPI
hserout [$d,$a,"Test card for response: ",$d,$a]
For SDC_timeout = 8 To 0 Step -1
' Read Byte SDC_data_in from SPI bus. Returns SDC_data_in.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Get the byte.
hserout ["Countdown timeout: ",#SDC_timeout,$d,$a]
SDC_response = SDC_data_in
If (SDC_response != SDC_FLOATING_BUS) Then
hserout ["Got a response at: ",#SDC_timeout]
SDC_timeout = 0 ' Got a response, end the loop.
endif
Next SDC_timeout
hserout[$d,$a,"SDC_response: ",#SDC_response]
return
SectorRead:
hserout[$d,$a,$a,"Entering SectorRead loop"]
SDC_sector_addr = 200
SDC_status = sdcValid ' Set default error code.
SDC_cmd = READ_SINGLE_BLOCK
SDC_address = SDC_sector_addr << 9
Gosub send_receive_SD_loop ' Send Byte SDC_cmd to Long SDC_address, Returns Word SDC_response.
hserout[$d,$a,"SectorRead error: ",bin SDC_response,8]
If (SDC_response != 0) Then
Gosub send_receive_SD_loop ' Try once more to send Byte SDC_cmd to Long SDC_address, Returns Word SDC_response.
If (SDC_response != 0) Then
hserout[$d,$a,"Not accepted!"]
hserout[$d,$a,"SectorRead error: ",bin SDC_response,8]
gosub stop_read 'stops the algorithm totally
else
hserout[$d,$a,"Accepted on 2nd attempt!",$d,$a]
Endif
Endif
hserout[$d,$a,"Passed initial read command and address send",$d,$a]
Pauseus 40 ' Timing delay- at least 8 clock cycles.
For SDC_timeout = $2ff To 0 Step -1
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Read Byte SDC_data_in from SPI bus. Returns SDC_data_in.
Pauseus 40 ' Timing delay- at least 8 clock cycles.
If (SDC_data_in != SDC_FLOATING_BUS) Then SDC_timeout = 0 ' Got a response, end the loop.
Next SDC_timeout
If (SDC_data_in != DATA_START_TOKEN) Then
hserout["Timeout!!!!"]
gosub stop_read 'stops the algorithm totally
else
hserout["Data token received!",$d,$a]
endif
For SDC_index = 0 To (MEDIA_SECTOR_SIZE - 1)
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Read Byte SDC_data_in from SPI bus. Returns SDC_data_in.
hserout[SDC_data_in]
Next SDC_index
SDC_data_out = $ff ' Data pin must be high.
Gosub write_byte ' Just sends 16 clocks.
gosub write_byte
SD_CS = 1 ' Return Byte SDC_status.
pause 1
return
stop_read:
SSPEN = 0
stop
Response is as follows...........
869 <----- [just an I2C sensor]
sdc timeout: 1
sdc timeout: 2
sdc timeout: 3
sdc timeout: 4
sdc timeout: 5
sdc timeout: 6
sdc timeout: 7
sdc timeout: 8
sdc timeout: 9
sdc timeout: 10
Go idle
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 1
Op cond
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 1
Op cond
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 1
Op cond
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 0
CRC On/Off
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 0
Set Block Length
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 0
Sector write
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 0
Accepted!
506
Got a write response at 32
SDC data in = 3
SDC sector address: 10
Entering SectorRead loop
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Countdown timeout: 6
Got a response at: 6
SDC_response: 0
SectorRead error: 0
Passed initial read command and address send
Data token received!
HELLOGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
SDC sector address: 11
Entering SectorRead loop
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 193
SectorRead error: 11000001
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 240
Not accepted!
SectorRead error: 11110000
################################################## #######################
I'm having trouble with a PIC18LF45K22 and a 1GB SD card.
I've been looking at the SDFS file and tried to write directly to the SD card which has already been formatted FAT16. I've managed to have it initialise the card, set the block length etc and send out 512 bytes of data to a sector, it then reads that sector and displays the ASCII (sends data/response via RS232 to RealTerm).
2 issues:
1. When I write to the card, and it reads the same sector back, if I then place this card in my laptop and use a hexeditor, I cannot find the string ANYWHERE!!! But I know it's on the card as I've written to different sectors and stuff from previous hours remains!
2. If I issue a second readsector command (say for instance I wanted to read consecutive sectors, or even re-read the same sector) I get a non-zero SDC_response value and the routine fails!
I feel I've done pretty well here but my head is getting sore!
If I post the code here, is there any chance someone could have a look please?
Many thanks in advance
Jimbo
define OSC 16
DEFINE HSER_BAUD 19200
DEFINE HSER_CLROERR 1 ' Auto clear over-run errors
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 20h
OSCCON = OSCCON | %01110000 ' set internal clock to 16 MHz incase of switchover
SDI Var PORTC.4 ' SPI data in
SDI_TRIS Var TRISC.4 ' SPI data in direction
SCL Var PORTC.3 ' SPI clock
SCL_TRIS Var TRISC.3 ' SPI clock direction
SD_CS Var PORTA.5 ' SD card chip select
SD_CS_TRIS Var TRISA.5 ' SD card chip select direction
SD_CD Var PORTB.4 ' SD card detect
SD_CD_TRIS Var TRISB.4 ' SD card detect direction
SDO Var PORTC.5 ' SPI data out
SDO_TRIS Var TRISC.5 ' SPI data out direction
i2cSDA VAR PORTD.1
i2cSCL VAR PORTD.0
SSPEN Var SSPCON1.5 ' SSP enable
WCOL Var SSPCON1.7 ' SSP write collision
BF Var SSPSTAT.0 ' SSP buffer full
SSPIF Var PIR1.3 ' SSP interrupt flag
accx var byte
accx2 var byte
accx_axis var word
fail var byte
read_loop var byte
NODATA Con 0
MOREDATA Con 1
MEDIA_SECTOR_SIZE Con 512
FAT_BUFFER_SIZE Con MEDIA_SECTOR_SIZE
' Indexes into command table
GO_IDLE_STATE Con 0
SEND_OP_COND Con 1
SET_BLOCKLEN Con 2
READ_SINGLE_BLOCK Con 3
WRITE_SINGLE_BLOCK Con 4
CRC_ON_OFF Con 5
sdcCardDataRejected Con 8
SDC_address Var Long
SDC_buffer Var Byte[MEDIA_SECTOR_SIZE]
SDC_cmd Var Byte
SDC_CmdCode Var Byte
SDC_CRC Var Byte
SDC_data_in Var Byte
SDC_data_out Var Byte
SDC_index Var Word
SDC_moredataexpected Var Byte
SDC_response Var Byte
SDC_sector_addr Var Long
SDC_status Var Byte
SDC_timeout Var Long
SDC_timeout1 Var Word
sdcValid Con 0
sdcCardInitCommFailure Con 1
sdcCardNotInitFailure Con 2
sdcCardInitTimeout Con 3
FAT_error Var Byte
FAT_error = 0
DATA_START_TOKEN Con $fe
DATA_ACCEPTED Con $05
SDC_FLOATING_BUS Con $ff
SDC_BAD_RESPONSE Con SDC_FLOATING_BUS
FALSE Con 0
TRUE Con 1
'SDC_UseHardSPI Var Byte
'Include "SDFS.PBP"
trisa = %00000000
trisd = %00000000
trisc = %00000000
adcon0.0 = 0
ANSELA = 0
ANSELB = 0
ANSELC = 0
ANSELD = 0
ANSELE = 0
ADCON1 = 15 ' All I/O pins digital
pause 1000
I2CWRITE i2cSDA,i2cSCL, $a6, $2d, [0]
pauseus 5
I2CWRITE i2cSDA,i2cSCL, $a6, $2d, [16]
pauseus 5
I2CWRITE i2cSDA,i2cSCL, $a6, $2d, [8]
pauseus 5
I2CWRITE i2cSDA,i2cSCL, $a6, $31, [8]
pause 1000
i2cread i2cSDA,i2cSCL,$a7,50,[accx,accx2],error
accx_axis = accx+(accx2 &03)*256
hserout [$d,$a,#accx_axis,$d,$d]
fail = 0
'while (fail <5 & FAT_error != 0)
fail = fail+1
SD_CS = 1 ' SD card not selected.
SD_CS_TRIS = 0 ' Output SD card chip select.
SD_CD_TRIS = 1 ' Input card detect.
'SD_WE_TRIS = 1 ' Input write protect.
SDO = 1 ' Start SPI data out high.
SDO_TRIS = 0 ' Output SPI data out.
SDI_TRIS = 1 ' Input SPI data in.
SCL = 1 ' SPI clock idles high.
SCL_TRIS = 0 ' Output SPI clock.
pause 1
SSPSTAT = %00000000 ' Sample at middle of data output time, Mode 1, 1: Transmit on idle to active clock transition.
SSPCON1 = %00010010 ' SPI master mode, clock = Fosc/64, Mode 1, 1: Clock idle high.
SSPEN = 1 ' Enable hardware SPI port.
pause 1
For SDC_timeout1 = 1 To 10
hserout [$d,$a,"sdc timeout: ",#SDC_timeout1]
SDC_data_out = $ff ' Data pin must be high.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = SDC_data_out' Send the byte.
If (WCOL) Then Return' Check for write collision.
While !SSPIF ' Wait for send to complete.
Wend
Next SDC_timeout1
pause 1
hserout [$d,$a,"Go idle"]
SDC_cmd = GO_IDLE_STATE
SDC_address = 0
gosub send_receive_SD_loop
SDC_data_out = $ff ' Data pin must be high.
gosub write_byte
If (!SDC_moredataexpected) Then
SD_CS = 1
Endif
If (SDC_response = SDC_BAD_RESPONSE) Then
SDC_status = sdcCardInitCommFailure
Goto InitError
Endif
If ((SDC_response & $F7) != $01) Then
SDC_status = sdcCardNotInitFailure
Goto InitError
Endif
For SDC_timeout1 = $fff To 0 Step -1
hserout [$d,$a,"Op cond"]
SDC_cmd = SEND_OP_COND
SDC_address = 0
gosub send_receive_SD_loop
' Generate 8 clock cycles.
SDC_data_out = $ff ' Data pin must be high.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = SDC_data_out ' Send the byte.
If (WCOL) Then Return ' Check for write collision.
While !SSPIF ' Wait for send to complete.
Wend
If (!SDC_moredataexpected) Then
SD_CS = 1
Endif
If (SDC_response = $00) Then SDC_timeout1 = 0 ' Got a response, end the loop.
Next SDC_timeout1
If (SDC_response != $00) Then
SDC_status = sdcCardInitTimeout
Goto InitError
Endif
Pause 1
SSPSTAT = %00000000 ' Sample at middle of data output time, Mode 1, 1: Transmit on idle to active clock transition.
SSPCON1 = %00010000 ' SPI master mode, clock = Fosc/64, Mode 1, 1: Clock idle high.
SSPEN = 1
hserout [$d,$a,"CRC On/Off"]
SDC_cmd = CRC_ON_OFF
SDC_address = 0
gosub send_receive_SD_loop
SDC_data_out = $ff
gosub write_byte
If (!SDC_moredataexpected) Then
SD_CS = 1
Endif
hserout [$d,$a,"Set Block Length"]
SDC_cmd = SET_BLOCKLEN
SDC_address = MEDIA_SECTOR_SIZE
gosub send_receive_SD_loop
SDC_data_out = $ff
gosub write_byte
pause 1
'################################################# #############
'SectorWrite:
hserout[$d,$a,"Sector write"]
SDC_sector_addr = 200
SDC_cmd = WRITE_SINGLE_BLOCK
SDC_address = SDC_sector_addr << 9
gosub send_receive_SD_loop
If (SDC_response != 0) Then
hserout[$d,$a,"Not accepted!",$d,$a]
gosub stop_read
else
hserout[$d,$a,"Accepted!",$d,$a]
endif
SDC_data_out = DATA_START_TOKEN
Gosub write_byte
SDC_data_out = 72 'store 'HELLO'
Gosub write_byte
SDC_data_out = 69
Gosub write_byte
SDC_data_out = 76
Gosub write_byte
SDC_data_out = 76
Gosub write_byte
SDC_data_out = 79
Gosub write_byte
For SDC_index = 0 To (MEDIA_SECTOR_SIZE - 6)
hserout[$d,#SDC_index]
SDC_data_out = $47
Gosub write_byte
Next SDC_index
' Send the CRC bytes.
SDC_data_out = $ff
gosub write_byte ' Just sends 16 1s.
gosub write_byte
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Get the byte.
If ((SDC_data_in & $0f) != DATA_ACCEPTED) Then
SDC_status = sdcCardDataRejected
hserout[$d,$a,"Rejected!"]
gosub stop_read
Else
' The card is writing data into the storage media.
' Wait for the card to return non-zero (not busy) or a timeout.
For SDC_timeout = 0 To 10000
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Get the byte.
If (SDC_data_in != 0) Then
hserout[$d,$a,"Got a write response at ",#SDC_timeout]
SDC_timeout = 10000 ' Got a response, end the loop.
endif
Next SDC_timeout
hserout[$d,$a,"SDC data in = ",#SDC_data_in]
If (SDC_data_in = 0) Then
hserout[$d,$a,"SDC Card timeout"]
gosub stop_read
endif
Endif
SDC_data_out = $ff ' Data pin must be high.
gosub write_byte
SD_CS = 1
'################################################# #################
pause 1
for read_loop = 10 to 12
hserout[$d,$a,"SDC sector address: ",#read_loop]
gosub SectorRead
next read_loop
End
error:
HSEROUT["Error"]
RETURN
InitError:
HSEROUT [$d,$a,"Error unknown", $d, $a]
return
write_byte:
' Write Byte SDC_data_out.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = SDC_data_out ' Send the byte.
If (WCOL) Then
HSEROUT [$d,$a,"Error: collision", $d, $a]
Return ' Check for write collision.
endif
While !SSPIF ' Wait for send to complete.
Wend
return
write_SPI:
SD_CS = 0
Lookup SDC_cmd, [$40, $41, $50, $51, $58, $7b], SDC_CmdCode
Lookup SDC_cmd, [$95, $f9, $ff, $ff, $ff, $25], SDC_CRC
Lookup SDC_cmd, [NODATA, NODATA, NODATA, MOREDATA, MOREDATA, NODATA], SDC_moredataexpected
SDC_data_out = SDC_CmdCode
gosub write_byte
SDC_data_out = SDC_address.Byte3
gosub write_byte
SDC_data_out = SDC_address.Byte2
gosub write_byte
SDC_data_out = SDC_address.Byte1
gosub write_byte
SDC_data_out = SDC_address.Byte0
gosub write_byte
SDC_data_out = SDC_CRC
gosub write_byte
return
send_receive_SD_loop:
SD_CS = 0
pause 1
gosub write_SPI
hserout [$d,$a,"Test card for response: ",$d,$a]
For SDC_timeout = 8 To 0 Step -1
' Read Byte SDC_data_in from SPI bus. Returns SDC_data_in.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Get the byte.
hserout ["Countdown timeout: ",#SDC_timeout,$d,$a]
SDC_response = SDC_data_in
If (SDC_response != SDC_FLOATING_BUS) Then
hserout ["Got a response at: ",#SDC_timeout]
SDC_timeout = 0 ' Got a response, end the loop.
endif
Next SDC_timeout
hserout[$d,$a,"SDC_response: ",#SDC_response]
return
SectorRead:
hserout[$d,$a,$a,"Entering SectorRead loop"]
SDC_sector_addr = 200
SDC_status = sdcValid ' Set default error code.
SDC_cmd = READ_SINGLE_BLOCK
SDC_address = SDC_sector_addr << 9
Gosub send_receive_SD_loop ' Send Byte SDC_cmd to Long SDC_address, Returns Word SDC_response.
hserout[$d,$a,"SectorRead error: ",bin SDC_response,8]
If (SDC_response != 0) Then
Gosub send_receive_SD_loop ' Try once more to send Byte SDC_cmd to Long SDC_address, Returns Word SDC_response.
If (SDC_response != 0) Then
hserout[$d,$a,"Not accepted!"]
hserout[$d,$a,"SectorRead error: ",bin SDC_response,8]
gosub stop_read 'stops the algorithm totally
else
hserout[$d,$a,"Accepted on 2nd attempt!",$d,$a]
Endif
Endif
hserout[$d,$a,"Passed initial read command and address send",$d,$a]
Pauseus 40 ' Timing delay- at least 8 clock cycles.
For SDC_timeout = $2ff To 0 Step -1
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Read Byte SDC_data_in from SPI bus. Returns SDC_data_in.
Pauseus 40 ' Timing delay- at least 8 clock cycles.
If (SDC_data_in != SDC_FLOATING_BUS) Then SDC_timeout = 0 ' Got a response, end the loop.
Next SDC_timeout
If (SDC_data_in != DATA_START_TOKEN) Then
hserout["Timeout!!!!"]
gosub stop_read 'stops the algorithm totally
else
hserout["Data token received!",$d,$a]
endif
For SDC_index = 0 To (MEDIA_SECTOR_SIZE - 1)
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Read Byte SDC_data_in from SPI bus. Returns SDC_data_in.
hserout[SDC_data_in]
Next SDC_index
SDC_data_out = $ff ' Data pin must be high.
Gosub write_byte ' Just sends 16 clocks.
gosub write_byte
SD_CS = 1 ' Return Byte SDC_status.
pause 1
return
stop_read:
SSPEN = 0
stop
Response is as follows...........
869 <----- [just an I2C sensor]
sdc timeout: 1
sdc timeout: 2
sdc timeout: 3
sdc timeout: 4
sdc timeout: 5
sdc timeout: 6
sdc timeout: 7
sdc timeout: 8
sdc timeout: 9
sdc timeout: 10
Go idle
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 1
Op cond
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 1
Op cond
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 1
Op cond
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 0
CRC On/Off
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 0
Set Block Length
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 0
Sector write
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 0
Accepted!
506
Got a write response at 32
SDC data in = 3
SDC sector address: 10
Entering SectorRead loop
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Countdown timeout: 6
Got a response at: 6
SDC_response: 0
SectorRead error: 0
Passed initial read command and address send
Data token received!
HELLOGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
SDC sector address: 11
Entering SectorRead loop
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 193
SectorRead error: 11000001
Test card for response:
Countdown timeout: 8
Countdown timeout: 7
Got a response at: 7
SDC_response: 240
Not accepted!
SectorRead error: 11110000
################################################## #######################