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

I Need Help With The Pic and MMC Comunication

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



Joined: 04 Oct 2006
Posts: 8

View user's profile Send private message

I Need Help With The Pic and MMC Comunication
PostPosted: Thu Oct 05, 2006 9:40 am     Reply with quote

Hi I'm using this software, but I have problems with the response, I don't always get the response of the MMC card. I'm using PIC18F4520 with a 4MHz oscillator.

I'm using the spi.h of the microchip C18 compiler. I think that it works fine.

I need help, maybe someone can help me. Thanks.

This is my code, I check the hardware and it's correct.

thanks

ana


Code:

#include <p18cxxx.h> 

#include "spi.h"
unsigned char data[64];

unsigned char WriteSPI( PARAM_SCLASS unsigned char data_out );
unsigned char ReadSPI( void );


/************************** MMC get response **************************************/
/**** Repeatedly reads the MMC until we get the response we want or timeout ****/

int mmc_respuesta(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(ReadSPI() != response && --count > 0);

        if(count==0) return 1;                  // loop was exited due to timeout
        else return 0;                          // loop was exited before timeout
}


/************************** MMC Init **************************************/
/* Initialises the MMC into SPI mode and sets block size, returns 0 on success */

#define SS LATCbits.LATC6  //chip selector
int mmc_init(void){
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
  TRISC = 0x10;
  SSPSTAT=0x40;
  SSPCON1 = 0x22;
 
  SS = 1;

for(i=0;i<10;i++)                       // initialise the MMC card into SPI mode by sending clks on
{
        WriteSPI(0x55);
}

to spi mode when it receives reset
SS=0;
WriteSPI(0x40);                        // send reset command
WriteSPI(0x00);                        // all the arguments are 0x00 for the reset command
WriteSPI(0x00);
WriteSPI(0x00);
WriteSPI(0x00);
WriteSPI(0x95);                        // precalculated checksum as we are still in MMC mode

//putsSPI("Sent go to SPI\n\r");
if(mmc_respuesta(0x01)==1) return 1;     // if = 1 then there was a timeout waiting for 0x01 from the mmc


//putsSPI("Got response from MMC\n\r");

i = 0;

while((i <255>= 254) return 1;                   // if >= 254 then there was a timeout waiting for 0x00 from the mmc


//putsSPI("Got out of idle response from MMC\n\r");


SS=1;
WriteSPI(0xFF);                        // extra clocks to allow mmc to finish off what it is doing


SS=0;
        WriteSPI(0x50);                // send mmc command one to bring out of idle state
        WriteSPI(0x00);
        WriteSPI(0x00);
        WriteSPI(0x02);                // high block length bits - 512 bytes
        WriteSPI(0x00);                // low block length bits
        WriteSPI(0xFF);                // checksum is no longer required but we always send 0xFF

if((mmc_respuesta(0x00))==1) return 1;

SS=1;
//putsSPI("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(void){

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

        WriteSPI(0x58);                // send mmc command one to bring out of idle state
        WriteSPI(0x00);
        WriteSPI(0x00);
        WriteSPI(0x00);                //
        WriteSPI(0x00);                // always zero as mulitples of 512
        WriteSPI(0xFF);                // checksum is no longer required but we always send 0xFF

//OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)
SS=1;
return 0;
}

/************************** MMC Write Block **************************************/

int mmc_write(unsigned long block_number){
unsigned long i;
unsigned char dir3,dir2,dir1,dir0;

dir0 = ((block_number&0x03)<<6>>2);
dir2 =((block_number&0x03FC00)>>10);
dir3 = (block_number >>18);

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

//OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)
SS=0;
        WriteSPI(0x58);                // send mmc write block
        WriteSPI(dir3);
        WriteSPI(dir2);
        WriteSPI(dir1);
        WriteSPI(dir0);                // always zero as mulitples of 512
        WriteSPI(0xFF);                // checksum is no longer required but we always send 0xFF

if((mmc_respuesta(0x00))==1) return 1;
//putsSPI("Got response to write block\n\r");
/*
WriteSPI(0xFE);                        // send data token

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

WriteSPI(i2c_eeprom_read(varh[i],varlow[i]));     // send data

}*/

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

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

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

//OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)
SS=1;
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 int i;
unsigned char dir3,dir2,dir1,dir0;

dir0 = ((block_number&0x03)<<6>>2);
dir2 =((block_number&0x03FC00)>>10);
dir3 = (block_number >>18);
//OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)
SS=0;

        WriteSPI(0x51);                // send mmc read single block command
        WriteSPI(dir3);      // arguments are address
        WriteSPI(dir2);
        WriteSPI(dir1);
        WriteSPI(dir0);
        WriteSPI(0xFF);                // checksum is no longer required but we always send 0xFF

if((mmc_respuesta(0x00))==1) return 1;   // if mmc_respuesta returns 1 then we failed to get a 0x00 response (affirmative)

//putsSPI("Got response to read block command\n\r");

if((mmc_respuesta(0xFE))==1) return 1;   // wait for data token

//putsSPI("Got data token\n\r");

        for(i=0;i<64;i++)
        {
              data[i] =(ReadSPI());               // we should now receive 512 bytes
        }

ReadSPI();                 // CRC bytes that are not needed
ReadSPI();

//OUTPUT_HIGH(PIN_C2);            // set SS = 1 (off)
SS=1;
WriteSPI(0xFF);                // give mmc the clocks it needs to finish off

//putsSPI("\n\rEnd of read block\n\r");

return 0;
}


Last edited by ANITA on Tue Oct 10, 2006 8:15 am; edited 3 times in total
ckielstra



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

View user's profile Send private message

PostPosted: Thu Oct 05, 2006 11:39 am     Reply with quote

Please edit your post by posting again but now:
- Use the 'code' buttons when posting to preserve the formatting, this makes reading much easier to us.
- Select the 'Disable HTML in this post' check box. Now a lot of your program code has disappeared.

Why did you change the code to use another SPI include file? What is wrong with the CCS supplied version?
ANITA



Joined: 04 Oct 2006
Posts: 8

View user's profile Send private message

PostPosted: Thu Oct 05, 2006 12:05 pm     Reply with quote

Hi
I edit the post but i don't know if i doing well.

i'm using anothe compiletor because is the one i download but if the other its better i tried that one

i can use the ccs with the PIC18f4520??

thank
ana
ANITA



Joined: 04 Oct 2006
Posts: 8

View user's profile Send private message

PostPosted: Thu Oct 05, 2006 12:31 pm     Reply with quote

hi

I read the CCS Compile, i can used because i use microchip mplab icd 2 to program miy pic.

because of that i using another compile and the spi.h of that compile

thanks

ana
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 05, 2006 4:15 pm     Reply with quote

Quote:

i'm using anothe compiletor because is the one i download but if the
other its better i tried that one. i can use the ccs with the PIC18f4520 ?

You can't use the CCS demo with the 18F4520.
Here is the demo page:
http://www.ccsinfo.com/content.php?page=compdemo
It says the demo only works with the 16F877, 16C544, and 18F458.
Also, it says there is a 2K program size limit.
ckielstra



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

View user's profile Send private message

PostPosted: Fri Oct 06, 2006 8:40 am     Reply with quote

As I understand it you are using the Microchip C18 compiler. You know this is a website for the CCS compiler which is a different company? We are here willing to help everybody with PIC related questions, but as we have none to little knowledge of your compiler we might not be able to solve your problem.

Quote:
I edit the post but i don't know if i doing well.
I can see you used the 'code' button several times but it didn't work. You can see the keywords [ code][ /code] are inserted before and after your program code twice. The correct way is to only have [ code] before and then [ /code] after your program code.

Also your program code is still messed up. Are you sure you reposted all text and selected the 'Disable HTML' checkbox?
For example a line like
Code:
while((i <255>= 254) return 1; // if >= 254 then there was a timeout waiting for 0x00 from the mmc
makes no sense.

Also post your code for initializing the SPI port.
ANITA



Joined: 04 Oct 2006
Posts: 8

View user's profile Send private message

PostPosted: Mon Oct 09, 2006 10:07 am     Reply with quote

i can inicializate my mmc but i can read the boot.

i read something but i don't think that it's correct.

i'm usign this code to read, i'm not sure about adrresing.


Code:


unsigned char Command(char befF,int AdrH,int AdrL,char befH ){            

    SPI(0xFF);
    SPI(befF);
    SPI(AdrH>>8);
    SPI(AdrH);
    SPI(AdrL>>8);
    SPI(AdrL);
    SPI(befH);
    SPI(0xFF);
    return (SPI(0xFF));      
}

unsigned char MMC_Read (unsigned long block_number){
unsigned int dir1;
unsigned int dir2;
unsigned int i,j;
extern unsigned  char  data1[64];

  dir1=(block_number>>16);
  dir2=(block_number);
  CS=0;
  if (Command(0x51,dir1,dir2,0xFF) !=0) return 1;
  while(SPI(0xFF) != 0xFE);

  i=0;
  for (i=0;i<64;i++){
        data1[i]=SPI(0xFF);
  }
   SPI(0xFF);
  SPI(0xFF);
  CS=1;
  return 0;
ckielstra



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

View user's profile Send private message

PostPosted: Mon Oct 09, 2006 11:24 am     Reply with quote

Hi Anita,

I see you have learned how to use the 'Code' button. Too bad your first posted program code is still corrupted because you didn't replace all code and then select the 'Disable HTML in this post' checkbox.

My guess is that part of your problem is that you are reading 64 bytes. This suggests to me that you are also writing 64 bytes (you didn't post that code). You have to know that MMC cards can only be written with data blocks of 512 bytes, writing less bytes will make the card to not accept the data. A simple workaround to test this is to write your 64 bytes and then write 512-64=448 bytes of all '0'.

If you want to read data you can read a single byte, but writing is always in blocks of 512 bytes. So if you want to change a single byte in the MMC card you first have to read the block of 512 bytes, change the single byte in memory and then write the whole block to the MMC card again.
ANITA



Joined: 04 Oct 2006
Posts: 8

View user's profile Send private message

PostPosted: Tue Oct 10, 2006 8:15 am     Reply with quote

Thanks for the help ckielstra.

i saw the problem with the size of data that i want to read, i write 512 bytes then i read 64 bytes.

i can't read the boot sector, the first block, the sector where the fat table is.

i can write and read what i wrote but i can read that sector i don't know why.

when i try to read that sector using read command the response give me error, response=0x01; idle error.

thanks
ana
ANITA



Joined: 04 Oct 2006
Posts: 8

View user's profile Send private message

PostPosted: Tue Oct 10, 2006 12:29 pm     Reply with quote

Hi

i have another question
can i read a single byte inside the block that i wrote?can i read a single adress?
ckielstra



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

View user's profile Send private message

PostPosted: Tue Oct 10, 2006 2:27 pm     Reply with quote

ANITA wrote:
can i read a single byte inside the block that i wrote?can i read a single adress?
Yes you can, but then first you have to tell the MMC card how many bytes you want to read by using the SET_BLOCKLEN command. This same block length is used for writing, so don't forget to set it back to 512 before writing new data.

I converted some of my code to use your functions and changed data types to the C18 compiler (16 bit integer by default). The (untested) code looks like:
Code:

#define SET_BLOCKLEN      MMC_CMD(0x50) // Set block length
#define READ_SINGLE_BLOCK MMC_CMD(0x51) // Reads a block of the size selected with SET_BLOCKLEN

#define MMC_START_BLOCK_TOKEN   0xFE    // Token signalling the start of a data block

//-----------------------------------------------------------------------------
// Selects a block length (in bytes) for all following block
// commands (read and write).
// Returns 0 when OK, 1 on error.
//-----------------------------------------------------------------------------
unsigned char MMC_SetBlockLen(unsigned short block_len)
{
  char Result;

  CS=0;
  Result = Command(SET_BLOCKLEN, 0, block_len, 0xFF);
  CS=1;

  return Result;
}

//-----------------------------------------------------------------------------
// Read multiple data bytes from Flash memory.
// Because of MMC limitations with block sizes of 512 bytes, the maximum number
// of bytes to read is limited to 512 bytes and is not allowed to cross a
// 512 byte sector border.
// Address: 32-bit linear address for reading from flash.
// Data:    Pointer to buffer for storing the read data.
// Len:     Number of bytes to read (0 - 512).
// Returns: 0 when OK, 1 on error.
//-----------------------------------------------------------------------------
unsigned char MMC_ReadDataBuf(unsigned long Address, char *Data, unsigned short Len)
{
  unsigned char Result;
  unsigned short i;
  unsgined short AddrH, AddrL
 
 
  Result = MMC_SetBlockLen(Len);
  if (Result != 0)
    return Result;

  CS=0;
  AddrH = (Address>>16);
  AddrL = (Address) & 0x00FF;
  Result = Command(READ_SINGLE_BLOCK, AddrH, AddrL, 0xFF);

  if (Result == 0)
  {
    // Wait for Start Byte (0xFE)
    while ( SPI(0xFF) != MMC_START_BLOCK_TOKEN)
    {
      // Do nothing (or add a time-out mechanism).
    }

    // Read the data
    for (i=0; i<Len; i++)
    {
      Data[i] = SPI(0xFF);
    }
   
    // Skip the CRC
    SPI(0xFF);
    SPI(0xFF);
     
    Result = 0;
  }

  CS=1;

  return Result;
}


Example to read 10 bytes from address 0x123456:
Code:
char Buf[10];
char Result;
Result = MMC_ReadDataBuf(0x123456, Buf, 10);
ANITA



Joined: 04 Oct 2006
Posts: 8

View user's profile Send private message

PostPosted: Tue Oct 17, 2006 1:14 pm     Reply with quote

Thanks for the help ckielstra.

my program its working very well, the only problem that i have its the 512 buffer, i'm using a PIC18 and the c18 compiler use diferente syntasys, but i solved with the strings but its not perfect yet.

really thank you

my big problem was the SPI macro of the compiler, they have an big error, but i can saw it and fixed.

thankx

ana
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