Interfacing SD Card to ATMega

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All,

I am trying to interface a ATMega168 running at 8MHz with an SD card using Chan's PetitFs software. I am using the PetitFs that has been converted to use SPI rather than USI. I downloaded this from a thread on this forum.

The AVR is powered at 5V and the signals are translated by the 74LVC and 74ACHT logic buffers. I have checked the signals to verify the bus activity. The SCK line shows pulse trains, and the SS, MISO, and MOSI lines show pulses around every 1000us. I have attached a schematic of how the AVR interfaces to the logic buffers.

Below is the main code that I am using to test the functionality of the SD card. I am displaying the exit code returned by disk_initialize() to an LCD display for debugging. I have wrote a function with exit codes corresponding to the value returned from the disk_initialize() function. My problem is that the code keeps returning "˜SD = 5', which in my code indicates the value that was returned is not either of the function flags returned from disk_initialize().

I have tried changed the SPI bus speed from fosc/2 to fosc/64 and fosc/128 with no change in the exit function code.

Any insight into why I cannot initialize the SD Card?


// AVR to SD Card Test Code

#include  
#include  
#include  
#include  
#include "lcd.h" 
#include "i2cmaster.h" 

#define	SYSCLK		8000000UL

//------SD Card Library Includes
#include "SDCardFiles/diskio.h"
#include "SDCardFiles/pff.h"
//#include "SDCardFiles/xitoa.h"
//#include "SDCardFiles/suart.h"


// Flags
uint8_t WriteLCDFlag = 0, FunctionFlag;

// SD Card Variables
uint8_t res_str[10];	
BYTE res = 0;

//Function Prototypes 
void WriteLCD(void);
void TriggerFunctions(void);	// Sets flags within function
void SDCardInit(void);			// Initialize SD Card and prepare for write


/**************************************************************************************/
/**************************************************************************************/
/*********************           main function          *******************************/
/**************************************************************************************/
/**************************************************************************************/

int main(void) 
{ 
	
	// Init LCD 
   lcd_init(LCD_DISP_ON); 
   i2c_init();

   // Set Data Direction Register
   DDRB |= 0x2C;	// SS, SCK, and MOSI set HIGH (0b00101100)
   PORTB |= 0x04;	// SS pulled up (0b0000100)
   
   sei();	// Enable Interrupts  
    
   for(;;)  // run forever
   { 
	
		WriteLCDFlag = 1;
		
		// Write to LCD Display
		WriteLCD();
	
		if (!(res == 0))
		{
			SDCardInit();
		}
   } 
    
} 



/******************* ISR's ***********************************/
/*************************************************************/

ISR(TIMER0_COMPA_vect)       // Continually Interrupt program to update time to LCD display 
{ 

	FunctionFlag = 1;		// Set flag for TriggerFunctions() function
	
} 

ISR(PCINT2_vect)			
{

//	AnemDebounceFlag = 1;	// Set flag for AnemDebounce() function
	
}


/*------------------ End ISR's ----------------------------*/
/*-----------------------------------------------------------*/

/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/
/*--------------------   TriggerFunctions Function         ---------------------------*/
/*------------   Set Flags for polled function is main()   ---------------------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/

void TriggerFunctions(void)
{
	if (FunctionFlag == 1)
	{
		
		// Enable WriteLCD Function
		WriteLCDFlag = 1;
		
		FunctionFlag = 0;			// Reset FunctionFlag 

	}
	
}

/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/
/*---------------------          WriteLCD function          --------------------------*/
/*---------------------     Write values to LCD screen      --------------------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/


void WriteLCD(void)
{
	if (WriteLCDFlag == 1)
	{
		// Clear the screen
		lcd_clrscr();
		
		lcd_puts(" SD=");
		lcd_puts(res_str);
		
		// Reset Flag
		WriteLCDFlag = 0;
		
	}
}


/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/
/*---------------------       SDCardInit function         ----------------------------*/
/*--------   Initialize SD Card and prepare volume for write             -------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/

void SDCardInit(void)
{

	res = disk_initialize();
	
	
	if (res == STA_NOINIT)		// Disk drive has not been initialized
		res = 1;
	
	if (res == STA_NODISK)		// No medium in drive.  Always cleared on fixed disk drive
		res = 2;
	
	if (!(res == STA_NOINIT))	// If STA_NOINIT is cleared, function succeeded in initializing disk
		res = 0;
		
	else
		res = 5;
		
	utoa(res,res_str,10);

}

Attachment(s): 

Last Edited: Fri. Apr 6, 2012 - 07:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are at least two threads in the Tutorials forum on how to interface an SD card.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Koshchi. Actually that is where I found the code mentioned in my original post. I have read through the tutorials and applied the things mentioned to the code I am working with

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think you are going to diagnose this from a dry reading. On the outside what does a scope or LA show happening on the SPI lines to the SD/MMC? On the inside what does a JTAG/dW show happening as you step disk_initialize()?

BTW is the number of = signs in the following intentional? As far as I can see this is the only chance main() has of ever doing anything related to the SD:

      if (!(res = 0))
      {
         SDCardInit();
      }

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Clawson:

I will hook up my o-scope again and report back the results in more detail. Unfortunately I don't have deep enough pockets to buy a JTAG/dw capable programmer.

The equal sign was a typo when I posted on here, and I have corrected it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The disk_initialize() function takes a parameter and you're calling it as if it was void .

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

Last Edited: Sat. Apr 7, 2012 - 04:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After probing around with my o-scope I found the following:

SCK Line: pulse train width = 236 us
time between pulse train = 3.68ms
Bus was pulled LOW between pulses

MOSI Line: pulse train width = 12 us
time between pulse trains = 3.70ms
Bus pulled HIGH between pulses

SS Line: pulse train width = 36 us
time between pulse trains = 3.70ms
Bus pulled HIGH between pulses

MISO Line: pulse train width = 14 us
time between pulse trains = 7.36ms
Bus pulled HIGH between pulses

There is not any communication to decode going between the SD card and the AVR (on the MOSI and MISO lines) as the signals are signal pulses. I attempted to play around with the bus timing a little bit more with no luck.

My test circuit is setup on a breadboard....with this be causing any capacitive loading on the SPI bus? The wires running from the AVR to the second breadboard containing the SD card are probably around 3 inches in total length, would this be potentially causing problems?

I am using a SanDisk 2GB SD Card. I am thinking of trying a lower capacity card if I can find it, and/or a different brand of card.

I'm kind of stumped here at the moment.....

Thanks all.

EDIT: I updated the test code to make it extremely simple

#include  
#include  
#include  
#include  
#include "lcd.h" 
#include "i2cmaster.h" 

//------SD Card Library Includes
#include "SDCardFiles/diskio.h"
#include "SDCardFiles/pff.h"
//#include "SDCardFiles/xitoa.h"
//#include "SDCardFiles/suart.h"

// SD Card Variables
uint8_t res_str[10];	
BYTE res = 0;

//Function Prototypes 
void WriteLCD(void);

/**************************************************************************************/
/**************************************************************************************/
/*********************           main function          *******************************/
/**************************************************************************************/
/**************************************************************************************/

int main(void) 
{ 
	
	// Init LCD 
   lcd_init(LCD_DISP_ON); 
   i2c_init();

   // Set Data Direction Register
   DDRB |= 0x2C;	// SS, SCK, and MOSI set HIGH (0b00101100)
   PORTB |= 0x04;	// SS pulled up (0b0000100)
   
   sei();	// Enable Interrupts  
    
   for(;;)  // run forever
   { 
		
		// Write to LCD Display
		WriteLCD();
		
		
		res = disk_initialize();
		
		if (res == STA_NOINIT)		// Disk drive has not been initialized
			res = 1;
		
		if (res == STA_NODISK)		// No medium in drive.  Always cleared on fixed disk drive
			res = 2;
		
		if (!(res == STA_NOINIT))	// If STA_NOINIT is cleared, function succeeded in initializing disk
			res = 0;
			
		else
			res = 4;
			
		utoa(res,res_str,10);	

   } 
    
} 


/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/
/*---------------------          WriteLCD function          --------------------------*/
/*---------------------     Write values to LCD screen      --------------------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/


void WriteLCD(void)
{

		// Clear the screen
		//lcd_clrscr();
		
		lcd_puts(" SD=");
		lcd_puts(res_str);
		
}