本文包含原理图、PCB、源代码、封装库、中英文PDF等资源
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
#include <reg51.h>
#include "huixian.h"
#define uchar unsigned char
#define ulong unsigned long
#define ushort unsigned short
sbit clk = P2^5; //时钟线
//define master out slave in pin 数据输chu
sbit miso = P2^4;
//define master in slave out pin 数据输ru
sbit mosi = P2^6;
//define chip selection(挑选) pin
sbit cs = P2^7;
sbit led = P3^7;
void Write_Byte_SD(uchar dat)
{
uchar i;
for (i = 0; i < 8; i++)
{
clk = 0;
dat <<= 1;
mosi = CY;
// miso = CY;
clk = 1;
}
mosi = 1;
}
uchar Read_Byte_SD()
{
uchar i, dat;
for (i = 0; i < 8; i++)
{
clk = 0;
dat <<= 1;
dat |= miso;
// *dat |= mosi;
clk = 1; //循环结束 clk == 1
}
return dat;
}
unsigned char Write_Command_SD(unsigned char *CMD)
{
unsigned char tmp;
unsigned char retry=0;
unsigned char i;
//禁止SD卡片选
cs=1;
//发送8个时钟信号
Write_Byte_SD(0xFF);
//使能SD卡片选
cs=0;
//向SD卡发送6字节命令
for (i=0;i<0x06;i++)
{
Write_Byte_SD(*CMD++);
}
//获得16位的回应
Read_Byte_SD(); //read the first byte,ignore it.
do
{ //读取后8位
tmp = Read_Byte_SD();
retry++;
} while((tmp==0xff)&&(retry<50));
return(tmp);
}
// 初始化例程:
//--------------------------------------------------------------------------
// 初始化SD卡到SPI模式
//--------------------------------------------------------------------------
unsigned char SD_Init()
{
unsigned char retry,temp;
unsigned char i;
unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
//SD_Port_Init(); //初始化驱动端口//////////////////
// Init_Flag=1; //将初始化标志置1
uart_puts("init1");
cs = 1;
for (i=0;i<0x0f;i++)
{
Write_Byte_SD(0xff); //发送至少74个时钟信号
}
//向SD卡发送CMD0
retry=0;
cs = 0;
uart_puts("init2");
do
{ //为了能够成功写入CMD0,在这里写200次
temp=Write_Command_SD(CMD);
retry++;
if(retry==200)
{ //超过200次
uart_puts("init cmd0 over200");
if (temp == 0xff)
{
sendone('f');
}
// return(0);//CMD0 Error!
break;
}
// sendone(retry);
}
while(temp!=1); //回应01h,停止写入
uart_puts("init3");
//发送CMD1到SD卡
CMD[0] = 0x41; //CMD1
CMD[5] = 0xFF;
retry=0;
do
{ //为了能成功写入CMD1,写100次
temp=Write_Command_SD(CMD);
retry++;
if(retry==100)
{ //超过100次
// return(0);//CMD1 Error!
uart_puts("init cmd1 over100");
if (temp == 0xff)
{
sendone('f');
}
break;
}
}
while(temp!=0);//回应00h停止写入
// Init_Flag=0; //初始化完毕,初始化标志清零
cs=1; //片选无效
return(0); //初始化成功
}
void SD_get_data(unsigned int Bytes,unsigned char *buffer)
{
unsigned int j;
unsigned char ch;
for (j=0;j<Bytes;j++)
{
*buffer++ = Read_Byte_SD();
}
*buffer = '\0';
for (j; j < 512; j++)
{
ch = Read_Byte_SD();
}
cs = 1;
}
void delay_spi(uchar a)
{
uchar b;
for (b=100; b; b--)
for (a; a; a--);
}
// 扇区读的程序例程:
unsigned char SD_Read_Sector(unsigned long sector,unsigned char *buffer)
{
unsigned char retry;
//命令16
unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
unsigned char temp;
//地址变换 由逻辑块地址转为字节地址
sector = sector << 9; //sector = sector * 512
CMD[1] = ((sector & 0xFF000000) >>24 );
CMD[2] = ((sector & 0x00FF0000) >>16 );
CMD[3] = ((sector & 0x0000FF00) >>8 );
//将命令16写入SD卡
retry=0;
cs = 0;
do
{ //为了保证写入命令 一共写100次
temp=Write_Command_SD(CMD);
retry++;
// sendone(temp);
if(retry==100)
{
uart_puts("read cmd16 over 100");
if (temp == 0xff)
{
sendone('f');
}
// return(0); //block write Error!
break;
}
}
while(temp!=0);
cs = 1;
retry = 0;
//Read Start Byte form MMC/SD-Card (FEh/Start Byte)
//Now data is ready,you can read it out.
uart_puts("waiting....");
cs = 0;
while ( temp != 0xfe)
{
temp = Read_Byte_SD();
retry++;
delay_spi(200);
delay_spi(200);
if (retry == 200)
{
retry = 0;
if (temp == 0xff)
{
sendone('f');
}
else
{
sendone('a');
}
delay_spi(200);
delay_spi(200);
}
}
// readPos=0;
uart_puts("get ");
if (temp == 0xff)
{
sendone('f');
}
SD_get_data(7,buffer);
//512字节被读出到buffer中
return 0;
}
//其中SD_get_data函数如下:
//----------------------------------------------------------------------------
// 获取数据到buffer中
//----------------------------------------------------------------------------
//扇区写的程序例程:
//--------------------------------------------------------------------------------------------
// 写512个字节到SD卡的某一个扇区中去 返回0说明写入成功
//--------------------------------------------------------------------------------------------
unsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer)
{
unsigned char tmp,retry;
unsigned int i = 0;
//命令24
unsigned char CMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
addr = addr << 9; //addr = addr * 512
CMD[1] = ((addr & 0xFF000000) >>24 );
CMD[2] = ((addr & 0x00FF0000) >>16 );
CMD[3] = ((addr & 0x0000FF00) >>8 );
//写命令24到SD卡中去
cs = 0;
retry=0;
do
{ //为了可靠写入,写100次
tmp=Write_Command_SD(CMD);
retry++;
if(retry==100)
{
// return(tmp); //send commamd Error!
break;
}
// uart_puts(aa);
}
while(tmp!=0);
//在写之前先产生100个时钟信号
for (i=0;i<100;i++)
{
Read_Byte_SD();
}
//写入开始字节
Write_Byte_SD(0xFE);
Write_Byte_SD(0xFE);
//现在可以写入512个字节
while (*Buffer != '\0')
{
Write_Byte_SD(*Buffer++);
i++;
}
for (i;i<512;i++)
{
Write_Byte_SD(0xff);
}
//CRC-Byte
Write_Byte_SD(0xFF); //Dummy CRC
Write_Byte_SD(0xFF); //CRC Code
tmp=Read_Byte_SD(); // read response
if((tmp & 0x1F)!=0x05) // 写入的512个字节是未被接受
{
cs=1;
// return(0); //Error!
// break;
}
//等到SD卡不忙为止
//因为数据被接受后,SD卡在向储存阵列中编程数据
while (Read_Byte_SD()!=0xff){;}
//禁止SD卡
cs=1;
return(0);//写入成功
}
void delay1s(uchar d) //误差 0us
{
unsigned char a,b,c;
while(d--)
{
for(c=167;c>0;c--)
for(b=171;b>0;b--)
for(a=16;a>0;a--);
} //if Keil,require use intrins.h
}
void main()
{
uchar str[]="0123456";
uchar str1[]="ABCDEFGHI";
init_uart();
delay1s(30);
SD_Init();
SD_write_sector(0x00ffff,str);
delay_spi(300);
uart_puts(str);
SD_Read_Sector(0x00ffff,str1);
uart_puts("du chu");
uart_puts(str1);
while (1)
{
;
}
}
串口输出
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
//void init_uart();
//void sendone(uchar ch);
//void uart_puts(uchar *str);
//void delay_uart(uchar ms);
uchar str[16], con = 0;
//void main()
//{
// uchar i = 0; // buf[16],
// init_uart();
// while (1)
// {
// if (con != 0)
// {
// for (i = 0; i < con; i++)
// {
// sendone(str[i]);
// str[i] = str[i + 1];
// }
// con--;
// }
// }
//
//}
void init_uart()
{
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xf3;
TL1 = 0xf3;
EA = 1;
ES = 1;
TR1 = 1;
}
void ISR_UART() interrupt 4
{
if (RI)
{
RI = 0;
str[con] = SBUF; //接收
con++;
str[con] = '\0';
}
}
void sendone(uchar ch)
{
SBUF = ch; //发送后 TI = 1, 进入中断
while (!TI);
TI = 0;
}
void uart_puts(uchar *str)
{
while (*str)
{
sendone(*str);
str++;
// if (*str == ';')
// {
// break;
// }
}
}
void delay_uart(uchar ms)
{
uchar x, y;
for (;ms > 0; ms--)
for (x = 100; x > 0; x--)
for (y = 100; y > 0; y--);
} |