Discussion in "8051 Discussion Forum" started by    Help    Dec 8, 2008.
Sat Jan 31 2009, 12:58 AM
#71
I'll try:

Firstly, Chan has written two different versions of his FAT file system: FF.C and TFF.C - I chose to port the TFF.C version.

The only files you need to concern yourself with are the DISKIO.C file and the TFF.H file, which has conditional compiler options in it...

Before you begin the port, I recommend you have working the basic SPI functions you need to communicate with the card. This is very important, so you don't waste time trying to debug something within Chan's stuff, when really it's your routine that doesn't work...

My basic routines are as follows:

   enum SPI_FREQUENCIES { kHz400, MHz1, MHz5, MHz10 };

   extern void SPI_EnableCS      ( );
   extern void SPI_DisableCS     ( );
   extern void SPI_Init          ( enum SPI_FREQUENCIES ThisFrequency );
   extern BYTE SPI_Byte          ( BYTE ThisByte );
   extern void SPI_SetChannel    ( BYTE ThisChannel );

   extern BYTE SD_Init           ( );
   extern BYTE SD_Command        ( BYTE ThisCommand, ULONG ThisArgument );
   extern BYTE SD_CRC_7          ( BYTE *List, BYTE Length );
   extern BYTE SD_GetR1          ( );
   extern WORD SD_GetR2          ( );
   extern BYTE SD_ReadSector     ( ULONG SectorNumber, BYTE *Buffer );
   extern BYTE SD_WriteSector    ( ULONG SectorNumber, BYTE *Buffer );
   extern BYTE SD_WaitForReady   ( );


When you feel each of the above routines works perfectly, begin the port by rewriting the 5 simple functions in DISKIO.C, namely:
DSTATUS disk_initialize( BYTE drv )
DSTATUS disk_status( BYTE drv	)
DRESULT disk_read ( BYTE drv, BYTE *buff, DWORD sector, BYTE count )
DRESULT disk_write( BYTE drv, const BYTE *buff, DWORD sector, BYTE count )
DRESULT disk_ioctl ( BYTE drv, BYTE ctrl, void *buff )


Here is an example of how I wrote the disk_read(...) function above:
/*-----------------------------------------------------------------------*/
/* Read Sector...                                                        */
/*-----------------------------------------------------------------------*/
DRESULT disk_read ( BYTE drv, BYTE *buff, DWORD sector, BYTE count )
   {
   /* Supports only single drive and must have a size of 1 sector */
   if( drv || !count || (count>
1) ) 
      return( RES_PARERR );

   /* if we haven't initialized the card yet... */
   if( Stat & STA_NOINIT ) 
      return RES_NOTRDY;
   
   /* Single block read */
   if( SD_ReadSector( sector, buff ) )
      return( RES_ERROR );
   
   return( RES_OK );
   }


The same must be done for each of the 5 functions listed...
Also, the compiler options within TFF.C must be set correctly. Here is how I have mine set:
#define _MCU_ENDIAN	2
#define _FS_READONLY	0
#define _FS_MINIMIZE	0
#define	_USE_STRFUNC	1
#define	_USE_FORWARD	1
#define _FAT32	        0
#define _USE_FSINFO	1
#define	_USE_SJIS	1
#define	_USE_NTFLAG	1


Once you have written each of the 5 functions listed, and everything compiles, you will need one final function:
DWORD get_fattime()
   {
   RTC_CURRENT rtc;
   
   
   RTC_read( &rtc );
   
   return	  ((DWORD)((WORD)(rtc.Year) + 2000 - 1980) << 25)
                  | ((DWORD)rtc.Month << 21)
                  | ((DWORD)rtc.Date << 16)
                  | ((DWORD)rtc.Hours << 11)
                  | ((DWORD)rtc.Minutes << 5)
                  | ((DWORD)rtc.Seconds >
>
 1);
   }


This particular function reads the time from my on-board real-time clock and formats the data for Chan's routines...

Hope this helps - my system is working perfectly...

Mon Feb 02 2009, 05:10 AM
#72
I have been private-messaged by the Original Poster to start from the beginning... :-s

I'm not sure exactly what specific points you need help with. Perhaps you can explain your question in detail here.

i just re-read the entire thread on this subject, and Ajay has been very specific, including example code for the low-level drivers that interface with the SPI bus. I too have been very specific, with code examples and suggestions.

If you have a specific question, I would be happy to try and answer...

By the way, do you have a name, or is your real name "Help"

-dave
Mon Feb 02 2009, 08:15 AM
#73
Dear Dave,

I'm using AT89C52 uC. This uC don't have build in SPI function but Ajay have taught me how to write the SPI routine for MMC.
1) If for my case the uC have not SPI function. Do i still need SPI frequencies initial?
2) SPI_SetChannel() function, may i know how it work? Please can you guide me how to write the function routine.
3) SD_CRC_7(), SD_GetR1(), SD_GetR2(), and SD_WaitForReady() function, please can you share with us how you to write coding?

Dear Dave,..Sure i have a name. You can call me Tang Nice to meet you.

Thank you,.


[ Edited Mon Feb 02 2009, 08:20 AM ]
Mon Feb 02 2009, 11:03 AM
#74
Hello Tang,

To answer your questions:

1. Do i still need SPI frequencies initial? Yes. When communicating with the SD card over the SPI interface, the initial SPI clock frequency cannot exceed 400Khz, and must be faster than 100Khz. This can be found in the SanDisk Secure Digital Card Product Manual Version 1.9, section 4.5. under "Clock Control"

2. SPI_SetChannel() function SPI_SetChannel() is a function I wrote to select between several SPI devices that are all connected to the MOSI and MISO lines from my microcontroller. Recall that each SPI device has 4 basic connections: SPICLK, MISO, MOSI, and CS. These connections are the SPI clock signal, the input line to the microcontroller, the output line from the microcontroller, and a chip select (respectively). A very good description of this bus can be found at:

http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus

If you only have the SD card, you can connect the CS signal to any available output pin on your microcontroller (provided the voltage is 3.3v) and not use this function. If you have more than one device connected to this bus, then you must provide a way of selecting only one device at a time. For instance, say P3.0 is connected to the SD memory card CS pin, and P3.1 is connected to some other device (like a temperature sensor). Your routine might look like this:
enum DeviceChannel = { SD_CARD, TEMP_CHIP };

void SPI_SetChannel( enum DeviceChannel ThisChannel )
   {
   switch( ThisChannel )
      {
      case SD_CARD :
         P3 = (P3 & 0xFC) | 0x01;
         break;
      case TEMP_CHIP :
         P3 = (P3 & 0xFC) | 0x02;
         break;
      default :
         P3 = (P3 & 0xFC);
         break;
      }
   }


Please understand that your routine will be specifically designed for YOUR hardware configuration...
3. SD_CRC_7(), SD_GetR1(), SD_GetR2(), and SD_WaitForReady() function The SD_CRC_7() function is optional, actually. I wrote it so that I could calculate a 7-bit CRC value for a string of bytes. If you do not understand CRC, you can read about it here:

http://en.wikipedia.org/wiki/Cyclic_redundancy_check

Since you don't really need the CRC values for commands when communicating with the SD card, you can just ignore this function.

The SD_GetR1() function is for retrieving the response byte from the card when it is in the R1 format, as described in the SanDisk Secure Digital Card Product Manual Version 1.9, section 5.2.3.1. "Format R1"

My function is as follows:
BYTE SD_GetR1()
   {
   BYTE i, j;

   for( i=0; i<8; i++ )
      {              /* response will be after 1-8 0xffs.. */
      j = SPI_Byte( 0xff );
      if(j != 0xff)  /* if it isn't 0xff, it is a response */
         return(j);
     }
   return(j);
   }


I believe you can get the idea from this example, and write your own code for the R2 response. If you read section 5.2.3.3. from the product manual, it fully describes the format...

And finally, the SD_WaitForReady() function was just something to maintain compatibility with Chan's stuff. It is a simple routine that sends nothing but clock pulses to the SD card, and insures the card isn't in the middle of something.

My rendition of it looks like this:
BYTE SD_WaitForReady()
   {
   BYTE i;
   WORD j;

   SPI_Byte( 0xFF );
   
	j = 500;
   do
      {
		i = SPI_Byte( 0xFF );
      Delay( 1 );
      } while ((i != 0xFF) && j);
   
   return( i );
   }


Undoubtedly, you are wondering what the SPI_Byte() function does, as well as the Delay() function...
The SPI_Byte function sends a byte to the currently selected SPI device, and returns any response from that device. The Delay function waits for the number of milliseconds. In this example, the delay is 1 millisecond.

I hope this helps you...

By the way, if you don't already have a copy of the product manual, you can find it here:

http://www.cs.ucr.edu/~amitra/sdcard/ProdManualSDCardv1.9.pdf

-dave
Tue Feb 03 2009, 07:46 AM
#75
Dave, me and Help working on a controller with no SPI, i mean its just gonna be slow nothing else that that. everything else is going to remain same.

Well i cannot believe i made this mistake in downloading files

i just downloaded the new files.
so as i checked we only have to bother about diskio.c right? and define our own functions with name
MMC_disk_initialize();
MMC_disk_status();
MMC_disk_read(buff, sector, count);
MMC_disk_write(buff, sector, count);
MMC_disk_ioctl(ctrl, buff);

how much amount of minimum RAM needed for this?
Tue Feb 03 2009, 08:08 AM
#76
Dear Daves,



1. Please can you guide me how to write the SPI clock in 100kHz-400kHz? Is it correct the Clock Timing diagram? If correct, how can we write an efficiency code on this part? I'm worry if i put a while-loop/for-loop for delay 400kHz/100kHz then it will take the processor load usage, somemore SD have 512 byte's to send/receive, am i rite?

2. SPI_SetChannel() function i think i know how to do already. Thank for your advice.

3. I have ready CRC7 function. Please can you compare your result with mine? I would like to confirm the CRC7 function do correct not. Let say,
Ex1:
List[0]=0x40
List[1]=0x00
List[2]=0x00
List[3]=0x00
List[4]=0x00
Length = 5
CRC = 0x4A

Ex2:
List[0]=0x40
List[1]=0x00
List[2]=0x00
List[3]=0x00
List[4]=0x31
Length = 5
CRC = 0x68

The SD_GetR2(), and SD_WaitForReady() function i think should not be the problem, i can understand it. I think this two function have to complete all the basic routines then only can test. Hopefully after the basic routines finished tested is ok.

Thank you,.
Tue Feb 03 2009, 07:10 PM
#77
Tang,

Actually, when they say 100-400kHz, they're talking about frequency, which is defined here:

http://en.wikipedia.org/wiki/Frequency

so actually, your picture should look like this:




That means that from rising edge to rising edge, the time should be 2.5 - 10 usecs, which means you will need an interrupt for the rising edge, and then an interrupt for the falling edge. In other words, your interrupt must happen every 1.25 usecs, but not slower than every 5 usecs. Also, when the interrupt occurs, you must shift 1 bit of information out over your designated MOSI pin, and shift 1 bit of information in from your designated MISO pin, every OTHER interrupt...
Tue Feb 03 2009, 07:43 PM
#78
Ajay,

You are correct. :-) These, along with the compiler options located in either FF.H or TFF.H are the only things that need to be modified...

Regarding the memory, you need a buffer of 512 bytes for the read/write buffer and probably another 512 bytes for static variables, stack variables, and local buffers...

I am using XDATA for my variables, since I have NOVRAM attached to my microcontroller. My memory chip is an ST M48T37Y-70MH1E, which is an expensive part, but works nicely in my system. It also has an embedded real-time clock in it, which satisfies the need for date/time stamping on files I create on my SD card.

-dave
Tue Feb 03 2009, 08:46 PM
#79
Tang,

Regarding the CRC calculations, I get a different answer than you do:

Ex1:
List[0]=0x40
List[1]=0x00
List[2]=0x00
List[3]=0x00
List[4]=0x00
Length = 5
CRC = 0x95

Ex2:
List[0]=0x40
List[1]=0x00
List[2]=0x00
List[3]=0x00
List[4]=0x31
Length = 5
CRC = 0xD1

Here's a link to everything you ever wanted to know about CRC calculations:
http://www.geocities.com/SiliconValley/Pines/8659/crc.htm

I got help from here:

http://www.edaboard.com/ftopic102279.html

Here is how I calculate the proper 7-bit CRC:
// _____________________________________________________________________________________________
//                                                                                              
// Function: SD_CRC_7()                                                                         
//                                                                                              
// Description:                                                                                 
// ------------                                                                                 
// calulates the 7-bit CRC for a list of bytes...                                               
//                                                                                              
// Design Notes:                                                                                
// -------------                                                                                
// In the case of CRC-7, the remainder can be calculated using a 7-bit shift register in        
// software. This shift register is initialized to all zeros at the start of the calculation. As
// each bit (MSB first) of the protected data is shifted into the LSB of the shift register,    
// the MSB of the shift register is shifted out and examined. If the bit just shifted out is    
// one, the contents of the shift register are modified by XORing with the CRC-7 polynomial     
// value 0x09. If the bit shifted out of the shift register is zero, no XOR is performed. Once  
// the last bit of protected data is shifted in and the conditional XOR completed, six more     
// zeros must be shifted through in a similar manner. This process is referred to as            
// augmentation, and completes the polynomial division. At this point, the CRC-7 value can be   
// read directly from the shift register.                                                       
// _____________________________________________________________________________________________
//                                                                                              
BYTE SD_CRC_7( BYTE *List, BYTE Length )
   {
   idata BYTE crc = 0x00;
   idata BYTE i, j, mask;

   for( i=0; i<Length; i++ )
      {
      mask = List[ i ];
      for( j=0; j<8; j++)
         {
         crc <<= 1;
         if(( mask & 0x80 ) ^ ( crc & 0x80 ) )
            crc ^= 0x09;
         mask <<= 1; 
         }
      }
   crc = (crc << 1) | 1;
   return( crc );
   }
Wed Feb 04 2009, 11:32 AM
#80
Dear Daves,

Thank for your usefull information and thank for your CRC7 coding. Previously my code is
crc = crc << 1 | 1;
now i change it to
crc = (crc << 1) | 1;
then work fine already..Thank again.

Please guide me how to write the 1.25uSec interrupt? The frequency is too high. I'm using this fomula
F = 11059200
t = 2us
S = 65535 - (F*t)/12
S = 65533.1568
S = 0xFFFD
So, i define TL0=0xFD and TH0=0xFF.
Is it correct?

I have write a simple Timer0 interrupt code, not sure correct not? Please can you check for me?
void init_timer0(void)
{
	TMOD &= 0xF0;
	TMOD |= 1;

	TL0 = TL;
	TH0 = TH;

	ET0 = 1;
	EA  = 1;
	TR0 = 1;
}

void ticks(void)
{
	char i;
	i++;
                     // SPI coding start
                     // ....
                     // ..   
}

void clk_tick() interrupt 1
{
	TR0 = 0;
	ET0 = 0;

	ticks(); 

	TL0 = TL;
	TH0 = TH;

	ET0 = 1;
	TR0 = 1;
}


Please advice...

Thank you,.


[ Edited Wed Feb 04 2009, 02:33 PM ]

Get Social

Information

Powered by e107 Forum System

Conversation

Sat Nov 01 2014, 08:54 AM
1
-1'
Sat Nov 01 2014, 08:54 AM
1
1
ExperimenterUK
Thu Oct 30 2014, 06:02 PM
This is a chat box..create a thread if you need help...but we don't do homework
Tue Oct 28 2014, 07:33 PM
vinni
hi rickey...anyone got the pgm...pls gimme now
Tue Oct 28 2014, 06:35 PM
potla
hi vinni even i need that program. help me if you get it
Tue Oct 28 2014, 03:22 PM
vinni
1. Using a look-up table in Flash ROM and accumulator offset indexed addressing mode, write a program that acts as a timer. The timer should count from 0 to 59 seconds. After reaching 59, it should go back to 0 on the next second and continue to count up. The timer should use the seven-segment display. The look-up table should contain information on how to display the digits 0 – 9 on the seven-segment display
Tue Oct 28 2014, 03:22 PM
vinni
hello Rickey..i need this pgm very urgently
Tue Oct 28 2014, 01:42 AM
Boy Donald
Dear sir, thanks before. i have some project urgent for my school and my project need this digital countdown timer using 7 segmen display. but your project only show ten minutes countdown, i need your help, can you show me more to change the minute or set the time manually. thank you, sorry for disturbing you.
Tue Oct 28 2014, 01:32 AM
Boy Donald
dear sir
Tue Oct 28 2014, 01:19 AM
Boy Donald
Rickey you inspired me a lot but why i can not change the time ( minute

Downloads

Comments

sanospsa
Fri Oct 31 2014, 09:23 AM
prash5054
Thu Oct 30 2014, 06:34 AM
Max.otto
Mon Oct 27 2014, 01:23 PM
toypoy
Sun Oct 26 2014, 01:06 AM
hiswe
Thu Oct 23 2014, 04:18 PM
pddung93
Sun Oct 19 2014, 01:56 PM
msideal
Thu Oct 16 2014, 08:48 AM
robotgirl
Tue Oct 14 2014, 06:23 PM

Online

Guests: 66, Members: 0 ...

most ever online: 182184
(Members: , Guests: 182184) on 06 Aug 2010: 05:37 AM

Members: 37536
Newest member: sanospsa
Forum Activity
rkodaganur Avatar
Posted By rkodaganur
Fri Oct 31 2014, 01:44 AM
Hi Ajay, I wanted to know can we use transformer ...
Max.otto Avatar
Posted By Max.otto
Thu Oct 30 2014, 11:09 AM
Hello all, before generating i have to give PWM p...
prash5054 Avatar
Posted By prash5054
Thu Oct 30 2014, 06:40 AM
can u post the updated code for the above problem ...
ExperimenterUK Avatar
Posted By ExperimenterUK
Wed Oct 29 2014, 05:36 PM
Thank you for the feedback.It's good to hear when ...
msideal Avatar
Posted By msideal
Tue Oct 28 2014, 05:34 PM
ExperimenterUK: Thankyou so much for helping me......
msideal Avatar
Posted By msideal
Tue Oct 28 2014, 05:18 PM
thanks ExperimenterUK for your help.... I will try...
ExperimenterUK Avatar
Posted By ExperimenterUK
Mon Oct 27 2014, 10:29 PM
Your error seems to be the use of PINC, which is f...
msideal Avatar
Posted By msideal
Mon Oct 27 2014, 05:45 PM
i want to extend my i/o's by writing this code. i ...
Max.otto Avatar
Posted By Max.otto
Mon Oct 27 2014, 01:30 PM
Hi all , i am working with PSoC 5LP. I have contin...
gaurav7577 Avatar
Posted By gaurav7577
Mon Oct 27 2014, 09:53 AM
hello everyone i wanna interface blood pressure se...