Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

speeding up the SPI CLOCK

Status
Not open for further replies.

irilias

New Member
Hi, i hope you're all doing well .
i'm trying to implement an interface between a PIC16f877a (8Mhz xtal) and an MMC, and i have a bit of a problem with CCS, now i understand that MMC requires a clock lower than 400khz for initialization and that's what i did, the code is running with SPI_CLK_DIV_64 (125khz).

my question is, what code should i add to speed up the SPI connection? i mean should i just redefine the SPI setup: Setup_spi(SPI_CLK_DIV_4) ?!

my second question concerns the bus interface circuitry, what Transistors do you recommend using ?

Code:
#include<16f877a.h> 
#fuses hs,nowdt, noprotect, nolvp 
#use delay(clock=10000000) 
#include<math.h> 
#include<string.h> 
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) 
int mmc_init(); 
int mmc_response(unsigned char response); 
int mmc_write_block(unsigned long block_number); 

/************************** 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_64); 
*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 
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 Write Block  *******************************/ 
int mmc_write_block(unsigned long block_number) 
{ 
unsigned long i; 
unsigned long varh,varl; 
char p,f,n; 
set_adc_channel(0); 
delay_us(10); 
f=read_adc(); 
n=(f*5)/256; 
p=(n*9375)/206; 
varl=((block_number&0x003F)<<9); 
varh=((block_number&0xFFC0)>>7); 
puts("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(varh); 
SPI_WRITE(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; 
puts("Got response to write block\n\r"); 
SPI_WRITE(0xFE);   // send data token 
for(i=0;i<512;i++) 
{ 
SPI_WRITE(p);   // send data 
} 
SPI_WRITE(0xFF);   // dummy CRC 
SPI_WRITE(0xFF); 
if((SPI_READ(0xFF)&0x0F)!=0x05) return 1; 
puts("Got data response to write block\n\r"); 
OUTPUT_HIGH(PIN_C2);  // set SS = 1 (off) 
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 
} 
/**************************************************************************/

MMC_PIC_interface.JPG

Thank you
 
you can use any small NPNs like 2N3904 etc.
 
i have some 2N2222 lying around and they seem comparable to the one you mentioned, thanks for your answer i really appreciate it :)
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top