View previous topic :: View next topic |
Author |
Message |
Sone_br
Joined: 05 Jul 2005 Posts: 2 Location: Brazil-Curitiba-PR
|
Starting to read a MMC (using SPI) |
Posted: Wed Jul 13, 2005 1:59 pm |
|
|
Hi eveybody,
I´m using MPLAB 6.61 with CCS-C Compiler 3.150. I´m trying to initialize and to read a MMC Card using PIC18F258. But i m not have any success. :/
My eletrical schematics is like this : http://www.cc5x.de/MMC/
My problem is basic : after i send command [0x40, 0x00, 0x00, 0x00, 0x00, 0x95] the mmc card not response me with the 0x01.
What´s wrong? Can anybody send me an example?
Thanks a lot.
The code i got from web:
Code: |
// pic mmc
// ---- ----
// RC2 1 (cs)
// RC3 5 (ckl)
// RC4 7 (dataOut)
// RC5 2 (dataIn)
//
// mmc pin 1,2,5:
// mmc
// |
// |
// --- |3,3kohm|--|--|1,8kohm|--- PIC
// |
// GND
//
// Testing to Start and Read a MMC
//
#include <18f258.h>
#use delay(clock=4000000)
#fuses XT,NOWDT,NOBROWNOUT,NOOSCSEN,NOPROTECT,NOPUT
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#use fast_io(C)
#byte SSPBUF = 0xFC9
#byte SSPCON = 0xFC6
#byte SSPSTAT = 0xFC7
#bit BF = SSPSTAT.0
#bit SMP = SSPSTAT.7
#bit CKE = SSPSTAT.6
#bit CKP = SSPCON.4
#bit SSPM1 = SSPCON.1
#bit SSPEN = SSPCON.5
#define LOW(var) (var & 0xFF)
#define HIGH(var) (var>>8)
// Prototypes:
int mmc_init();
int mmc_response(unsigned char response);
int mmc_read_block(unsigned long block_number);
int mmc_read_block(unsigned long block_number);
char SPI(char d);
void main(void)
{
puts("STARTING...\n\r");
if(MMC_Init())
puts("MMC ON\n\r"); // MMC Init OK
if (mmc_read_block(0) == 1)
{
printf("MMC not response for reading \r\n");
}
}
/************************** MMC Init ************************/
/* Initialises the MMC into SPI mode and sets block size, returns 0 on success */
int mmc_init()
{
int i;
SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 );
*0xFC7 |= 0x40; // set CKE = 1 - clock idle low (for PIC18F258)
*0xFC6 &= 0xEF; // set CKP = 0 - data valid on rising edge (for PIC18F258)
SSPEN=1; // set SSPEN = 1 - Enables serial port and configures SCK,...
// ...SDO, SDI and SS as serial port pins(for PIC18F258)
SMP=0;
CKE=0;
CKP=1;
SSPM1=1;
OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)
for(i=0;i<10;i++) // initialise the MMC card into SPI mode by sending clks on
{
SPI_WRITE(0xFF);
}
OUTPUT_LOW(PIN_C2); // set SS = 0 (on) tells card to go to spi mode when it receives reset
SPI_WRITE(0x40); // send reset command
SPI_WRITE(0x00); // all the arguments are 0x00 for the reset command
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x95); // precalculated checksum as we are still in MMC mode
puts("Sent go to SPI\n\r");
if(mmc_response(0x01)==1) return 1; // if = 1 then there was a timeout waiting for 0x01 from the mmc
puts("Got response from MMC\n\r");
i = 0;
while((i < 255) && (mmc_response(0x00)==1)) // must keep sending command if response
{
SPI_WRITE(0x41); // send mmc command one to bring out of idle state
SPI_WRITE(0x00); // all the arguments are 0x00 for command one
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF
i++;
}
if(i >= 254) return 1; // if >= 254 then there was a timeout waiting for 0x00 from the mmc
puts("Got out of idle response from MMC\n\r");
OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)
SPI_WRITE(0xFF); // extra clocks to allow mmc to finish off what it is doing
OUTPUT_LOW(PIN_C2); // set SS = 0 (on)
SPI_WRITE(0x50); // send mmc command one to bring out of idle state
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x02); // high block length bits - 512 bytes
SPI_WRITE(0x00); // low block length bits
SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1) return 1;
OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)
puts("Got set block length response from MMC\n\r");
return 0;
}
/************************** MMC Read Block **************************************/
/**** Reads a 512 Byte block from the MMC and outputs each byte to RS232 ****/
int mmc_read_block(unsigned long block_number)
{
unsigned long i;
unsigned long varh,varl;
varl=((block_number&0x003F)<<9);
varh=((block_number&0xFFC0)>>7);
OUTPUT_LOW(PIN_C2); // set SS = 0 (on)
SPI_WRITE(0x51); // send mmc read single block command
SPI_WRITE(HIGH(varh)); // arguments are address
SPI_WRITE(LOW(varh));
SPI_WRITE(HIGH(varl));
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1) return 1; // if mmc_response returns 1 then we failed to get a 0x00 response (affirmative)
printf("Got response to read block command\n\r");
if((mmc_response(0xFE))==1) return 1; // wait for data token
printf("Got data token\n\r");
for(i=0;i<512;i++)
{
putc(SPI_READ(0xFF)); // we should now receive 512 bytes
}
SPI_READ(0xFF); // CRC bytes that are not needed
SPI_READ(0xFF);
OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)
SPI_WRITE(0xFF); // give mmc the clocks it needs to finish off
printf("\n\rEnd of read block\n\r");
return 0;
}
/************************** MMC get response **************************************/
/**** Repeatedly reads the MMC until we get the response we want or timeout *******/
/**********************************************************************************/
int mmc_response(unsigned char response)
{
unsigned long count = 0xFFFF; // 16bit repeat, it may be possible to shrink this to 8 bit but there is not much point
while(SPI_READ(0xFF) != response && --count > 0);
if(count==0) return 1; // loop was exited due to timeout
else return 0; // loop was exited before timeout
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Thu Jul 14, 2005 9:39 am |
|
|
Couple of things I remember from doing this a while back is that you need to activate the chip select pin then get a command 0 (aka reset) to take then immediately follow with a command 1 (aka idle) command
It might help to look at my MMC_init routine in
FAT 16 file system for MMC using SPI mode
( The code is mostly about FAT16 but it has the low level MMC calls like MMC_init set block len etc.)
http://www.ccsinfo.com/forum/viewtopic.php?t=21721 |
|
|
Sone_br
Joined: 05 Jul 2005 Posts: 2 Location: Brazil-Curitiba-PR
|
|
Posted: Thu Jul 14, 2005 10:17 am |
|
|
PCM programmer,
Great, It works!
I just removed the 1k8ohm resistor. i connected mmc direct to the pic, then mmc response me. Any problem doing it?
Tks! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 14, 2005 11:07 am |
|
|
On their schematic, http://www.cc5x.de/MMC/ ther PIC runs at +5v
while the MMC runs at +3.3v. So they need to reduce the 5v CMOS
levels coming from the PIC down to the 3.3v CMOS levels used by
the MMC. That's why they have the 1.8K / 3.3K voltage dividers.
If your PIC is running at +3.3v, then you don't need the voltage
dividers. You should remove them in that case. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Jul 14, 2005 11:53 am |
|
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Jul 14, 2005 12:34 pm |
|
|
That's what I said, 'it might work'. And it might not....
I just gave a few suggestions for improvement. |
|
|
Guest
|
|
Posted: Tue Mar 21, 2006 7:12 am |
|
|
[quote="ckielstra"]In combination with a PIC18F458 I strongly recommend to make some changes to the schematic as given in [url]http://www.cc5x.de/MMC/ [/url]. This schematic is a mixture of 3.3 and 5V components and it is working outside of the specifications. For example, your PIC18F458 is specified on the RC4 input (SDI) with a minimum high voltage of 0.7VDD, running at 5V that is a minimum of 3,5V. The 3.3V MMC is never going to comply to this.
Another design mistake is the absence of 100kOhm pull-up resistors on all 3 SPI lines. this will cause start-up problems because the MMC is starting up in an open-collector mode.
You might be lucky to get the circuit to work, but why would you? Replacing your PIC18F458 by an PIC18LF458 allows you to reduce the supply voltage for the whole circuit to 3.3V. Then you can get rid of the resistor networks and CS5203A-3 as well, compensating for the higher costs of the LF-version PIC. For 3.3V operation you'll have to replace the MAX232 by a 3.3V compatible version with the extra benefit that the newer drivers are way more power efficient.[/quote] |
|
|
|