18 SERVO 09.2011
if ( (res &0x0F) ==
0x05 ) {
cmd = INIT;
}
else {
cmd = SEND_APP_OP;
}
if (!res) {
break;
}
}
if (res != 0) {
return(LOG_FAIL);
// failed to reset.
}
// 7. Check for
// capacity of the card
res = SD_SendCmd
(READ_OCR,0);
if (res != 0) {
return(LOG_FAIL);
// error, bad thing.
}
for (n=0; n<4; n++) {
db[n] = SD_Read();
}
SD_Disable();
// check CCS bit (bit 30),
// PoweredUp (bit 31) set
// if ready.
if ( ((db[0] & 0x40)
== 0x40) && (db[0] !=
0xFF) ) {
sdcard.cardCap = 1;
// card is high capacity
}
else{
sdcard.cardCap = 0;
// card is low capacity
}
}
sdcard.cardInit = 1;
// successfully initialized
// Get the CSD register to
// find the size of the card
res = SD_SendCmd(SEND_CSD,0);
if (res != 0) {
return(LOG_FAIL);
}
timer = t_1ms + 300;
// wait for a response
while(timer > t_1ms) {
res = SD_Read();
if (res == DATA_START) {
break;
}
}
if (res == DATA_START) {
// no timeout, read data
for (n=0; n< 16; n++) {
db[n] = SD_Read();
// read the received value
}
// ignore CRC (for now)
don’t like “magic numbers” in my
code, so I use defined constants. This
procedure will identify both SD and
SDHC cards. I have not tested it with
SDXC cards, however, since I don’t
have any of them.
Whew! Another Mr. Roboto has
come to an end. There were many
SD_Read();
SD_Read();
SD_Disable();
}
else {
return(LOG_FAIL);
}
if (sdcard.cardCap == 1) {
// Uses SDHC capacity
// calculation
sdcard.cardSize =
db[9] + 1;
sdcard.cardSize +=
(uint32_t)(db[8] << 8);
sdcard.cardSize +=
(uint32_t)(db[7] &
0x0F)<<12;
sdcard.cardSize *=
524288;
// multiply by 512KB
// (C_SIZE + 1)
// 512 1024
sdcard.cardNumBlocks =
sdcard.cardSize/sdcard
.cardBlock;
}
else {
// Uses SD capacity
// calculation
sdcard.cardSize =
(uint16_t)((db[6] &
0x03)<<10) | (uint16_t)
(db[7]<<2) | (uint16_t)
((db[8] & 0xC0)>>6)) + 1;
sdcard.cardSize =
sdcard.cardSize <<((
(uint16_t)((db[9] &
0x03)<<1) | (uint16_t)
((db[10] & 0x80)>>7)) +2);
sdcard.cardSize =
sdcard.cardSize <<(
(uint16_t)(db[5] & 0x0F));
// (C_SIZE +1) <<(C_SIZE_
// MULT + 2) <<(READ_BL_LEN)
sdcard.cardNumBlocks =
sdcard.cardSize/
sdcard.cardBlock;
// Set block size to 512 bytes
res = SD_SendCmd(
SET_WBLEN,0x00000200);
SD_Disable();
}
// Now kick to full speed
// 8MHz mode. disable SPI for
// configuration
SPI1STATbits.SPIEN = 0;
// Master, CKE=0; CKP=1,
// sample end, prescale 1:2
// (8MHz) all works
SPI1CON1 = 0x027b;
// re-enable SPI after
// configuration
SPI1STATbits.SPIEN = 1;
return(res);
}
obstacles that got in my way to get
here, but “where there is a will ...” If
you have any questions for Mr. Roboto,
please send them to roboto@servo
magazine.com. I love to hear from
you and will do my best to answer
your questions. Until then, keep on
working on those robots! SV