|
发表于 2007-7-17 21:32:25
|
显示全部楼层
elefan:
你好,我看完SD卡的数据手册和参考网站里的一些sd卡原程序,因为我的编译系统是CVAVR,所以我用你的程序来初始化我的mmc卡,按照你的方法连接电路,不过我是按照硬件SPI的端口连接的(实际上还是软件SPI),以便以后用硬件SPI,在运行过程,我发觉CM0都写不进去,恳请大家帮帮忙,看是否程序问题。
* 编译软件:CodeVision AVR C 版本:1.24.48d 以上
* MCU : Atmega32-16PU 晶振: 7.37286MHz
**********************************************************************/
#include <mega32.h>
#include <delay.h> //延时函数的头文件
#define uint8 unsigned char
#define int8 signed char
#define uint16 unsigned int
#define int16 signed int
#define uint32 unsigned long
#define int32 signed long
/*----------------------MCU and MMC pins define------------------------*/
//SPI pins define
#define MMC_Write PORTB //SPI port register
#define MMC_Read PINB //Data PIN
#define MMC_Direction_REG DDRB //Direction register
#define SPI_DI 6 //-->MMC_DO_PIN
#define SPI_DO 5 //-->MMC_DI_PIN
#define SPI_Clock 7 //-->MMC_CLK_PIN
#define MMC_Chip_Select 4 //-->MMC_CS_PIN
#define MMC_DO_PIN MMC_Read.SPI_DI
#define MMC_DI_PIN MMC_Write.SPI_DO
#define MMC_CLK_PIN MMC_Write.SPI_Clock
#define MMC_CS_PIN MMC_Write.MMC_Chip_Select
//LED pins define
#define CMD_LED PORTA //LED LIGHT
#define CMD_LED_Direction DDRA //Direction register
#define CMD0_OK 0 //CMD 0 complete light
#define CMD1_OK 1 //CMD 1 complete light
#define CMD17_OK 2 //CMD 17 complete light
#define CMD24_OK 3 //CMD 24 complete light
#define SPI_BUSY 7 //busy led
#define CMD0_OK_LED CMD_LED.CMD0_OK
#define CMD1_OK_LED CMD_LED.CMD1_OK
#define CMD17_OK_LED CMD_LED.CMD17_OK
#define CMD24_OK_LED CMD_LED.CMD24_OK
#define MMC_BUSY_LED CMD_LED.SPI_BUSY //busy led for spi port
/*--------------------------Error define-----------------------------*/
#define INIT_CMD0_ERROR 0x01
#define INIT_CMD1_ERROR 0x02
#define WRITE_BLOCK_ERROR 0x03
#define READ_BLOCK_ERROR 0x04
/*--------------------------MMC_CS_select define-----------------------------*/
//set MMC_Chip_Select to high (MMC/SD-Card Invalid)
#define MMC_Disable() MMC_Write.MMC_Chip_Select=1;
//set MMC_Chip_Select to low (MMC/SD-Card Active)
#define MMC_Enable() MMC_Write.MMC_Chip_Select=0;
#define nop() #asm("nop"); //asm nop defined in CVAVR
//---------------------------------------------------------------
// Prototypes
//---------------------------------------------------------------
// usart initialize
void usart_init(void);
// port initialize
void MMC_Port_Init(void);
//read a byte from MMC
uint8 Read_Byte_MMC(void);
//write a byte to MMC
void Write_Byte_MMC(uint8 value);
//read a block from MMC
uint8 MMC_Read_Block(uint8 *CMD,uint8 *Buffer,uint16 Bytes);
//MMC initialize
uint8 MMC_Init(void);
//write data sector to MMC
uint8 MMC_write_sector(uint32 addr,uint8 *Buffer);
//write a command to MMC
uint8 Write_Command_MMC(uint8 *CMD);
//read MMC CSD
uint8 Read_CSD_MMC(uint8 *Buffer);
//read MMC CID
uint8 Read_CID_MMC(uint8 *Buffer);
//---------------------------------------------------------------------
static uint8 Init_Flag; //Set it to 1 when Init is processing.
/*---------------------------------------------------------------------
函数功能: 本函数用于串行口的初始化操作。
备注: 本函数仅在主函数中调用一次即可。
----------------------------------------------------------------------*/
void usart_init(void)
{ /*设置波特率*/
UBRRL=0x03; //波特率=115200
/*接收、发送器使能*/
UCSRB=0x18;
/*设置帧格式: 8个数据位, 1个停止位*/
UCSRC=0x86;
}
/*---------------------------------------------------------------------
函数功能 :port initialize
函数入口参数:NO
函数出口参数:NO
说明 :
----------------------------------------------------------------------*/
void MMC_Port_Init(void)
{
//Config ports
MMC_Direction_REG.SPI_DI = 0; //Set Pin MMC_DI as Input
MMC_Direction_REG.SPI_Clock = 1; //Set Pin MMC_Clock as Output
MMC_Direction_REG.SPI_DO = 1; //Set Pin MMC_DO as Output
MMC_Direction_REG.MMC_Chip_Select = 1; //Set Pin MMC_Chip_Select as Output
//busy led port init
CMD_LED_Direction.CMD0_OK = 1; //set pin CMD0_LED as output
CMD_LED_Direction.CMD1_OK = 1; //set pin CMD0_LED as output
CMD_LED_Direction.CMD17_OK = 1; //set pin CMD0_LED as output
CMD_LED_Direction.CMD24_OK = 1; //set pin CMD0_LED as output
CMD_LED_Direction.SPI_BUSY = 1; //Set spi busy led port output
MMC_BUSY_LED = 1; //busy led off
CMD0_OK_LED = 1; //cmd0_ok_led off
CMD1_OK_LED = 1; //cmd0_ok_led off
CMD17_OK_LED = 1; //cmd0_ok_led off
CMD24_OK_LED = 1; //cmd0_ok_led off
MMC_CS_PIN = 1; //Set MMC_Chip_Select to High,MMC/SD Invalid.
}
//****************************************************************************
//Routine for Init MMC/SD card(SPI-MODE)
//****************************************************************************
uint8 MMC_Init(void)
{
uint8 retry,temp;
uint8 i;
uint8 CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
//MMC_Port_Init(); //Init SPI port
for(i=0;i<200;i++) //Wait MMC/SD ready...
{
#asm("nop");
}
Init_Flag=1; //Set the init flag
for (i=0;i<0x0f;i++)
{
Write_Byte_MMC(0xff); //send 74 clock at least!!!
}
//Send Command CMD0 to MMC/SD Card
retry=0;
do
{ //retry 200 times to send CMD0 command
temp=Write_Command_MMC(CMD);
retry++;
if(retry==200)
{ //time out
UDR = INIT_CMD0_ERROR;
while (!(UCSRA&0x20));
return(INIT_CMD0_ERROR);//CMD0 Error!
}
}
while(temp!=1);
UDR = ~INIT_CMD0_ERROR;
while (!(UCSRA&0x20));
CMD0_OK_LED = 0; //CMD 0 sent to MMC sucessful
//Send Command CMD1 to MMC/SD-Card
CMD[0] = 0x41; //Command 1
CMD[5] = 0xFF;
retry=0;
do
{ //retry 100 times to send CMD1 command
temp=Write_Command_MMC(CMD);
retry++;
if(retry==100)
{ //time out
UDR = INIT_CMD1_ERROR;
while (!(UCSRA&0x20));
return(INIT_CMD1_ERROR);//CMD1 Error!
}
}
while(temp!=0);
CMD1_OK_LED = 0; //CMD 1 sent to MMC sucessful
Init_Flag=0; //Init is completed,clear the flag
MMC_Disable(); //set MMC_Chip_Select to high
return(0); //All commands have been taken.
}
//****************************************************************************
//Send a Command to MMC/SD-Card
//Return: the second byte of response register of MMC/SD-Card
//****************************************************************************
uint8 Write_Command_MMC(uint8 *CMD)
{
uint8 tmp;
uint8 retry=0;
uint8 i;
//set MMC_Chip_Select to high (MMC/SD-Card disable)
MMC_Disable();
//send 8 Clock Impulse
Write_Byte_MMC(0xFF);
//set MMC_Chip_Select to low (MMC/SD-Card active)
MMC_Enable();
//send 6 Byte Command to MMC/SD-Card
for (i=0;i<0x06;i++)
{
Write_Byte_MMC(*CMD++);
}
//get 16 bit response
Read_Byte_MMC(); //read the first byte,ignore it.
do
{ //Only last 8 bit is used here.Read it out.
tmp = Read_Byte_MMC();
retry++;
}
while((tmp==0xff)&&(retry<100));
return(tmp);
}
//****************************************************************************
//Routine for reading a byte from MMC/SD-Card
//****************************************************************************
uint8 Read_Byte_MMC(void)
{
uint8 temp=0;
uint8 i;
MMC_BUSY_LED=0;
//Software SPI
for (i=0; i<8; i++) //MSB First
{
MMC_CLK_PIN=0; //Clock Impuls (Low)
if(Init_Flag) delay_us(10);
temp = (temp << 1) + MMC_DO_PIN; //read mmc data out pin
MMC_CLK_PIN=1; //set Clock Impuls High
if(Init_Flag) delay_us(10);
}
MMC_BUSY_LED=1;
return (temp);
}
//****************************************************************************
//Routine for sending a byte to MMC/SD-Card
//****************************************************************************
void Write_Byte_MMC(uint8 value)
{
uint8 i;
MMC_BUSY_LED=0;
//Software SPI
for (i=0; i<8; i++)
{ //write a byte
if (((value >> (7-i)) & 0x01)==0x01) MMC_DI_PIN=1; //Send bit by bit(MSB First)
else MMC_DI_PIN=0;
MMC_CLK_PIN=0; //set Clock Impuls low
if(Init_Flag) delay_us(10);
MMC_CLK_PIN=1; //set Clock Impuls High
if(Init_Flag) delay_us(10);
}//write a byte
MMC_DI_PIN=1; //set Output High
MMC_BUSY_LED=1;
}
//****************************************************************************
//Routine for writing a Block(512Byte) to MMC/SD-Card
//Return 0 if sector writing is completed.
//****************************************************************************
uint8 MMC_write_sector(uint32 addr,uint8 *Buffer)
{
uint8 tmp,retry;
uint16 i;
//Command 24 is a writing blocks command for MMC/SD-Card.
uint8 CMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
#asm("cli"); //clear all interrupt.
addr = addr << 9; //addr = addr * 512
CMD[1] = ((addr & 0xFF000000) >>24 );
CMD[2] = ((addr & 0x00FF0000) >>16 );
CMD[3] = ((addr & 0x0000FF00) >>8 );
//Send Command CMD24 to MMC/SD-Card (Write 1 Block/512 Bytes)
retry=0;
do
{ //Retry 100 times to send command.
tmp=Write_Command_MMC(CMD);
retry++;
if(retry==100)
{
return(tmp); //send commamd Error!
}
}
while(tmp!=0);
//Before writing,send 100 clock to MMC/SD-Card
for (i=0;i<100;i++)
{
Read_Byte_MMC();
}
//Send Start Byte to MMC/SD-Card
Write_Byte_MMC(0xFE);
//Now send real data Bolck (512Bytes) to MMC/SD-Card
for (i=0;i<512;i++)
{
Write_Byte_MMC(*Buffer++); //send 512 bytes to Card
}
//CRC-Byte
Write_Byte_MMC(0xFF); //Dummy CRC
Write_Byte_MMC(0xFF); //CRC Code
tmp=Read_Byte_MMC(); // read response
if((tmp & 0x1F)!=0x05) // data block accepted ?
{
MMC_Disable();
return(WRITE_BLOCK_ERROR); //Error!
}
//Wait till MMC/SD-Card is not busy
while (Read_Byte_MMC()!=0xff){};
//set MMC_Chip_Select to high (MMC/SD-Card Invalid)
MMC_Disable();
return(0);
}
//****************************************************************************
//Routine for reading data Registers of MMC/SD-Card
//Return 0 if no Error.
//****************************************************************************
uint8 MMC_Read_Block(uint8 *CMD,uint8 *Buffer,uint16 Bytes)
{
uint16 i; uint8 retry,temp;
//Send Command CMD to MMC/SD-Card
retry=0;
do
{ //Retry 100 times to send command.
temp=Write_Command_MMC(CMD);
retry++;
if(retry==100)
{
return(READ_BLOCK_ERROR); //block write Error!
}
}
while(temp!=0);
//Read Start Byte form MMC/SD-Card (FEh/Start Byte)
while (Read_Byte_MMC() != 0xfe){};
//Write blocks(normal 512Bytes) to MMC/SD-Card
for (i=0;i<Bytes;i++)
{
*Buffer++ = Read_Byte_MMC();
}
//CRC-Byte
Read_Byte_MMC();//CRC - Byte
Read_Byte_MMC();//CRC - Byte
//set MMC_Chip_Select to high (MMC/SD-Card invalid)
MMC_Disable();
return(0);
}
//***************************************************************************
//Routine for reading CID Registers from MMC/SD-Card (16Bytes)
//Return 0 if no Error.
//***************************************************************************
uint8 Read_CID_MMC(uint8 *Buffer)
{
//Command for reading CID Registers
uint8 CMD[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
uint8 temp;
temp=MMC_Read_Block(CMD,Buffer,16); //read 16 bytes
return(temp);
}
//***************************************************************************
//Routine for reading CSD Registers from MMC/SD-Card (16Bytes)
//Return 0 if no Error.
//***************************************************************************
uint8 Read_CSD_MMC(uint8 *Buffer)
{
//Command for reading CSD Registers
uint8 CMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
uint8 temp;
temp=MMC_Read_Block(CMD,Buffer,16); //read 16 bytes
return(temp);
}
void main(void)
{
usart_init();
MMC_Port_Init();
MMC_Init();
while (1)
{
MMC_Init();
};
} |
|