CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Starting to read a MMC (using SPI)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Sone_br



Joined: 05 Jul 2005
Posts: 2
Location: Brazil-Curitiba-PR

View user's profile Send private message Send e-mail

Starting to read a MMC (using SPI)
PostPosted: Wed Jul 13, 2005 1:59 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jul 13, 2005 2:04 pm     Reply with quote

Go to the following thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=23183&start=15
It has code from that website, already translated to CCS and it works.
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Thu Jul 14, 2005 9:39 am     Reply with quote

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

View user's profile Send private message Send e-mail

PostPosted: Thu Jul 14, 2005 10:17 am     Reply with quote

PCM programmer,

Great, It works! Very Happy

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

View user's profile Send private message

PostPosted: Thu Jul 14, 2005 11:07 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jul 14, 2005 11:53 am     Reply with quote

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 14, 2005 12:20 pm     Reply with quote

Though, the input levels for the PIC's SDI pin might work in a hobbyist
situation, as discussed in my first post in this thread.
http://www.ccsinfo.com/forum/viewtopic.php?t=23183&start=1
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Jul 14, 2005 12:34 pm     Reply with quote

PCM programmer wrote:
Though, the input levels for the PIC's SDI pin might work in a hobbyist
situation, as discussed in my first post in this thread.
http://www.ccsinfo.com/forum/viewtopic.php?t=23183&start=1
That's what I said, 'it might work'. And it might not....
I just gave a few suggestions for improvement.
Guest








PostPosted: Tue Mar 21, 2006 7:12 am     Reply with quote

[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]
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group