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

Need help with the MMC code
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
tranjimmysd



Joined: 05 May 2005
Posts: 9

View user's profile Send private message

Need help with the MMC code
PostPosted: Tue May 10, 2005 8:54 pm     Reply with quote

Hi,
I have the CCS 16F877A Proto-board. I connect it with 256 MB MMC card( brand new one, I got it from Fry's Electronic). I use SPI.
RC5 to MOSI(MMC pin2)
RC4 to MISO(MMC pin7)
RC3 to CLK (MMC pin 5)
RC1 to CS (MMC pin1)

the MMC is powered by 3.3 volt. The PIC is powered by 5.0 volt. Since the voltage level for RC1, RC4 and RC3 is 5.0 volt. So I use voltage divider 3.3 K and 1.8 K Ohm in MOSI, CS, CLK to make sure that those MMC pins will have 3.3 volt level.

I use this code from the internet to test it. Based on the debug output to rs232, i can tell that I got some responses from MMC when I write to it. But when it comes to the read function. I get nothing when trying to read back the test pattern ( a bunch of number 7). Here is the code. Can anyone tell me if I am missing anything:

*******************************************
#include <16f877a.h>
#device ICD=TRUE
#fuses HS, NOPROTECT, PUT, NOWDT, BROWNOUT, NOLVP, NOCPD
#use delay(clock=20000000)
#use rs232 (baud=9600, xmit=PIN_C6,rcv=PIN_C7)
#include <stdlib.h>
#include <input.c>

#define LOW(var) (var & 0xFF)
#define HIGH(var) (var>>8)

int mmc_init();
int mmc_response(unsigned char response);
int mmc_read_block(unsigned long block_number);
int mmc_write_block(unsigned long block_number);
int mmc_get_status();


/************************** 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 | SPI_SS_DISABLED);

*0x94 |= 0x40; // set CKE = 1 - clock idle low
*0x14 &= 0xEF; // set CKP = 0 - data valid on rising edge

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

printf("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

printf("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

printf("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)
printf("Got set block length response from MMC\n\r");
return 0;
}

/************************** MMC Get Status **************************************/
/* Get the status register of the MMC, for debugging purposes */

int mmc_get_status()
{

OUTPUT_LOW(PIN_C2); // set SS = 0 (on)

SPI_WRITE(0x58); // send mmc command one to bring out of idle state
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00); //
SPI_WRITE(0x00); // always zero as mulitples of 512
SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF
OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)
return 0;
}

/************************** MMC Write Block **************************************/
int mmc_write_block(unsigned long block_number)
{
unsigned long i;
unsigned long varh,varl;

varl=((block_number&0x003F)<<9);
varh=((block_number&0xFFC0)>>7);

printf("Write block\n\r"); // block size has been set in mmc_init()

OUTPUT_LOW(PIN_C2); // set SS = 0 (on)

SPI_WRITE(0x58); // send mmc write block
SPI_WRITE(HIGH(varh));
SPI_WRITE(LOW(varh));
SPI_WRITE(HIGH(varl));
SPI_WRITE(0x00); // always zero as mulitples of 512
SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF

if((mmc_response(0x00))==1) return 1;
printf("Got response to write block\n\r");

SPI_WRITE(0xFE); // send data token

for(i=0;i<512;i++)
{

SPI_WRITE(7 + '0'); // send data

}

SPI_WRITE(0xFF); // dummy CRC
SPI_WRITE(0xFF);

if((SPI_READ(0xFF)&0x0F)!=0x05) return 1;

printf("Got data response to write block\n\r");

OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)
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
}



void main(void)
{
printf("testing for MMC");
mmc_init();
mmc_write_block(0);

if (mmc_read_block(0) == 1)
{
printf("MMC not response for reading \r\n");
}

while(1)
{

}
}
icefield



Joined: 09 May 2005
Posts: 20
Location: Canada

View user's profile Send private message

Re: Need help with the MMC code
PostPosted: Wed May 11, 2005 4:07 am     Reply with quote

tranjimmysd wrote:
Hi,
the MMC is powered by 3.3 volt. The PIC is powered by 5.0 volt. Since the voltage level for RC1, RC4 and RC3 is 5.0 volt. So I use voltage divider 3.3 K and 1.8 K Ohm in MOSI, CS, CLK to make sure that those MMC pins will have 3.3 volt level.


The trouble might be that MISO is only getting 3.3V signals. Check the electrical specs of the PIC. MISO is probably a Schmitt trigger input (see the Port Spec), in which case minimum logic high is usually 0.7 or 0.8Vdd (i.e., 3.5-4V). So, you need a proper level converting chip or some MML to complement that resistor network.

For newbies: MML is Mickey Mouse Logic - usually a transitor or MOSFET with some resistors hanging off. As opposed to TTL or CMOS.

Cheers,
Erik
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Wed May 11, 2005 9:18 am     Reply with quote

See this thread:

http://www.ccsinfo.com/forum/viewtopic.php?t=22777

The last post has a link to a philips semiconductor application note on level shifting. It may be of help.
tranjimmysd



Joined: 05 May 2005
Posts: 9

View user's profile Send private message

PostPosted: Wed May 11, 2005 10:44 am     Reply with quote

Many thanks Icefield and Newguy. Good suggestions. I will give it a try and let you guys know how it goes.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed May 11, 2005 1:39 pm     Reply with quote

There are some serious problems with your level translation,
and with the MMC specification's requirement for pull-ups, etc.

But before considering that, the code that you posted uses
Pin C2 for the CS (or slave select). But in your pin list,
you're using pin C1.

You must either change your hardware to use Pin C2,
or you must modify the driver so it uses pin C1.
tranjimmysd



Joined: 05 May 2005
Posts: 9

View user's profile Send private message

PostPosted: Wed May 11, 2005 7:26 pm     Reply with quote

Hi,
Sorry for the typo. I did use C2 for the chip select.

I put this circuit( the first part) in between MISO and RC4 to make sure that the RC4/SDI pin on the pic will receive proper 5 volt level.

http://www.circuitcellar.com/pastissues/articles/Tom99/figure1.htm

with that circuit, I can go little further in the read function until where the function asks for the data token(if((mmc_response(0xFE))==1) return 1; // wait for data token). Asking for 0xFE, the MMC returns 0xFF.

I stuck. Any suggestion will be appreciated.

Jim
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed May 11, 2005 8:58 pm     Reply with quote

What is your version of the compiler ?
tranjimmysd



Joined: 05 May 2005
Posts: 9

View user's profile Send private message

PostPosted: Wed May 11, 2005 9:35 pm     Reply with quote

Hi,
The compiler version 3.224

PCWH compiler
IDE version 3.224
PCB Version 3.224
PCM version 3.224
PCH version 3.224

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 12, 2005 12:51 am     Reply with quote

His SPI setup has got some problems. I can see at least two problems.
I don't have time to finish writing it all up tonight. I'll do it tomorrow
morning and then post it.


Also, I'm curious as the manufacturer and part number of your MMC card.
I'd like to download the data sheet for it.
tranjimmysd



Joined: 05 May 2005
Posts: 9

View user's profile Send private message

PostPosted: Thu May 12, 2005 1:17 am     Reply with quote

Hi,
The MMC card made by Power Quotient International Co., Ltd
www.pqi.com.tw

It called Reduced Size MMC

Thank you very much for all your helps

Jim
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 12, 2005 3:31 pm     Reply with quote

Actually, I thought I had found two bugs, but I've only found one so far.

This line of code has a bug.
Code:
SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 | SPI_SS_DISABLED);

The SPI_SS_DISABLED parameter is only supposed to be used with
the SPI_SLAVE parameter. If it's used with SPI_MASTER, then it
affects the SPI clock frequency. In this case, it changes the divisor
from 1/4 to 1/16. So the SCLK is running not at 5 MHz as he intends,
but actually at 1.25 MHz.

So the correct code should look like this:
Code:
SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4);


I don't know if this is going to affect your problem. I'll keep looking
at it on Friday and over the weekend. If I see anything else, I'll post it.
Of course, anyone else who sees a problem should post it as well.
tranjimmysd



Joined: 05 May 2005
Posts: 9

View user's profile Send private message

PostPosted: Thu May 12, 2005 10:24 pm     Reply with quote

Hi,
I tried that but it did not work. :-(
I made my circuit based on this
http://www.captain.at/electronics/pic-mmc/
I aslo added in the volt level shifter in between the MMC output pin to the PIC SPI input .

I made my volt level shifter by using some of the resistors and transitors( I got them from Radioshack, the NPN high speed switching transistors).


Jim
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 12, 2005 11:00 pm     Reply with quote

CCS has a driver. It's called MMC_SPI.C, and it's in this folder:
c:\Program Files\Picc\Drivers

Have you tried that one ?
tranjimmysd



Joined: 05 May 2005
Posts: 9

View user's profile Send private message

PostPosted: Fri May 13, 2005 12:42 am     Reply with quote

Hi,
I tried the CCS driver, but it did not work too.

Have anyone in this forum ever tried this MMC code? http://www.microchipc.com/sourcecode/#mmc

if the code is working on for others, then there must be something wrong with my hardware connection.


Do you know any simple MMC/PIC development platform( PIC on 5 volts and MMC on 3.3 volts and support CCS ICD-U40) out there that I can purchase?

I like to test that MMC code with the surely-working-hardware.

Many thanks for all your helps
Jim
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Fri May 13, 2005 1:03 am     Reply with quote

I could be wrong, but I was under the impression that the ICD-U40 could program the low-voltage (LF) pics. Why don't you try to get an LF pic, run/program it at 3.3V, and then you can directly connect it to the 3.3V MMC card?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
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