|
发表于 2010-3-12 17:28:42
|
显示全部楼层
C51 COMPILER V8.01 SD 06/02/2009 19:20:11 PAGE 1
C51 COMPILER V8.01, COMPILATION OF MODULE SD
OBJECT MODULE PLACED IN SD.OBJ
COMPILER INVOKED BY: F:\安装重地\KEIL\C51\BIN\C51.EXE SD.c LARGE BROWSE DEBUG OBJECTEXTEND
line level source
1 #include<reg52.h>
2 #include"SD.h"
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 //变量定义
7 unsigned char is_init; //在初始化的时候设置此变量为1
8 uchar xdata FAT32_Buffer[512];//扇区数据读写缓冲区
9
10 sbit CS = P3^7; //SD卡片选
11 sbit SI = P3^5; //同步数据输入
12 sbit SCL = P3^3; //同步时钟输入
13 sbit SO = P3^1; //同步数据输出
14
15 //函数区
16 void delay(unsigned int time)
17 {
18 1 while(time--);
19 1 }
20
21 void Longdelay(unsigned int time)
22 {
23 1 while(time--)
24 1 delay(50000);
25 1 }
26
27 void spi_write(unsigned char x) //SPI写一个字节
28 {
29 1 unsigned char i;
30 1 for(i=0;i<8;i++)
31 1 {
32 2 SI=((x<<i)&0x80); //SI为一个IO口,只可能为0和1(大于0的时候)
33 2 SCL=0;
34 2 if(is_init) delay(8); //初始化SD卡的时候,数据通信的数度要放慢
35 2 SCL=1;
36 2 if(is_init) delay(8);
37 2 }
38 1 }
39
40 unsigned char spi_read() //SPI读一个字节
41 {
42 1 unsigned char temp=0,i;
43 1 SO=1;
44 1 for(i=0;i<8;i++)
45 1 {
46 2 SCL=0;
47 2 if(is_init) delay(8);
48 2 if(SO) temp|=(0x80>>i);
49 2 SCL=1;
50 2 if(is_init) delay(8);
51 2 }
52 1 return(temp);
53 1 }
54
55 unsigned char Write_Cmd(unsigned char *pcnd) //向SD卡写命令
C51 COMPILER V8.01 SD 06/02/2009 19:20:11 PAGE 2
56 {
57 1 unsigned char temp,time=0,i;
58 1 for(i=0;i<6;i++) //发送6字节的命令字节序列(每个命令都有6个字节)
59 1 {
60 2 spi_write(pcnd);
61 2 }
62 1 do
63 1 {
64 2 temp= spi_read();
65 2 //一直读,直到读到的不是0xff或超时(为0xff的时候,说明命令还没有被SD卡接受)
66 2 time++;
67 2
68 2 } while((temp==0xff)&&(time<50));
69 1
70 1 return(temp);
71 1 }
72
73 unsigned char SD_Reset()
74 //SD卡复位,进入SPI模式,使用CMD0(0号命令),即向SD卡中写入0号命令将使SD卡复位
75 {
76 1 unsigned char time,temp,i;
77 1 unsigned char pcnd[]={0x40,0x00,0x00,0x00,0x00,0x95}; //0号命令的序列
78 1
79 1 is_init=0; //使通信速率下降
80 1 CS=1;
81 1 for(i=0;i<0x0f;i++) //初始化时,首先要发送至少74个时钟脉冲,此处为120个时钟信号
82 1 {
83 2 spi_write(0xff);
84 2 }
85 1
86 1 CS=0;
87 1 time=0; //记录写入0号命令的次数
88 1 do
89 1 {
90 2 temp=Write_Cmd(pcnd); //写入CMD0,如果命令0写入成功,则temp的值是0x01
91 2 time++;
92 2 if(time==200)
93 2 {
94 3 return(INIT_CMD0_ERROR);//CMD0写入失败
95 3 }
96 2 } while(temp!=0x01);
97 1
98 1 CS=1;
99 1 spi_write(0xff); //按照SD卡的操作时序在这里补8个时钟
100 1 return 0; //返回0,说明复位操作成功
101 1 }
102
103 unsigned char SD_Init() //初始化,使用CMD1(1号命令)
104 {
105 1 unsigned char time,temp;
106 1 unsigned char pcnd[] = {0x41,0x00,0x00,0x00,0x00,0xff};
107 1 CS=0;
108 1 time=0;
109 1 do
110 1 {
111 2 temp=Write_Cmd(pcnd);
112 2 time++;
113 2 if(time==100)
114 2 {
115 3 return(INIT_CMD1_ERROR); //CMD1写入失败
116 3 }
117 2 } while(temp!=0);
C51 COMPILER V8.01 SD 06/02/2009 19:20:11 PAGE 3
118 1
119 1 is_init=0; //初始化完毕,将is_init设置为0, 为了以后提高数据通信的速度
120 1 CS=1; //关闭SD卡的片选
121 1 spi_write(0xff); //按照SD卡的操作时序在这里补8个时钟
122 1 return 0; //返回0,说明初始化成功
123 1 }
124
125 unsigned char SD_write_sector(unsigned long addr ,unsigned char *Buffer)
126 //向SD卡中的指定地址的扇区地址内写入512个字节,使用24号命令
127 {
128 1 unsigned char temp,time;
129 1 unsigned int i;
130 1 unsigned char pcnd[]={0x58,0x00,0x00,0x00,0x00,0xff}; //24号命令的序列
131 1 //向SD卡中单个块(一个扇区有512个字节)写入数据,用CMD24.
132 1 //中间的32个位是用来记录字节的地址,由此可知,SD卡最大容量是2^32个字节,为4G
133 1
134 1 addr<<=9;
135 1 //addr=addr * 512(左移9次,即2^9=512) 将模块地址(扇区地址)转换为字节地址
136 1 pcnd[1]=((addr&0xff000000)>>24); //将字节的地址写入到CMD24字节序列中
137 1 pcnd[2]=((addr&0x00ff0000)>>16);
138 1 pcnd[3]=((addr&0x0000ff00)>>8);
139 1
140 1 CS=0; //打开SD卡片选
141 1 time=0;
142 1 do
143 1 {
144 2 temp=Write_Cmd(pcnd);
145 2 time++;
146 2 if(time==100)
147 2 {
148 3 return(temp); //命令写入失败
149 3 }
150 2 } while(temp!=0);
151 1
152 1 for(i=0;i<100;i++) //这里要插入若干时钟信号
153 1 {
154 2 spi_read();
155 2 }
156 1
157 1 spi_write(0xfe); //开始写入字节0xfe,后面就是要写入的512个字节
158 1
159 1 for(i=0;i<512;i++) //将缓冲区中要写入的512个字节写入SD卡中
160 1 {
161 2 spi_write(*Buffer++);
162 2 }
163 1 spi_write(0xff);
164 1 spi_write(0xff); //两个字节的CRC校验码,不用关心
165 1
166 1 temp=spi_read(); //读取返回值
167 1 if((temp&0x1f)!=0x05) //如果返回值是xxx00101(temp的低五位) 说明数据应经被SD卡接受
168 1 {
169 2 CS=1;
170 2 return(WRITE_BLOCK_ERROR); //写块数据失败
171 2 }
172 1
173 1 while(spi_read()!=0xff);
174 1 //等到SD卡不忙(数据被接受以后,SD卡要将这些数据写入到自身的Flash中,需要一定时间)
175 1 //忙时,读回来的值为0x00(此时SD正在向Flash中写入数据),不忙时,为0xff
176 1 CS=1; //关闭片选
177 1
178 1 spi_write(0xff); //按照SD卡的操作时序在这里补8个时钟
179 1 return(0); //返回0,写入扇区操作成功
C51 COMPILER V8.01 SD 06/02/2009 19:20:11 PAGE 4
180 1 }
181
182 unsigned char SD_read_sector(unsigned long addr,unsigned char *buffer)
183 //从SD卡中的指定地址的扇区地址内读出512个字节,使用17号命令
184 {
185 1 unsigned int j;
186 1 unsigned char time,temp;
187 1 unsigned char pcnd[]={0x51,0x00,0x00,0x00,0x00,0xff};
188 1 //从SD卡中单个块读取数据,用CMD17。中间的32个位是用来记录字节的地址,
189 1
190 1 addr<<=9; //addr=addr * 512 将模块地址(扇区地址) 转换为字节地址
191 1 pcnd[1]=((addr&0xff000000)>>24); //将字节的地址写入到CMD24字节序列中
192 1 pcnd[2]=((addr&0x00ff0000)>>16);
193 1 pcnd[3]=((addr&0x0000ff00)>>8);
194 1
195 1 CS=0; //打开片选
196 1 time=0;
197 1 do
198 1 {
199 2 temp=Write_Cmd(pcnd); //写入CMD17
200 2 temp=0;
201 2 time++;
202 2 if(time==100)
203 2 { // while(1);
204 3 return(READ_BLOCK_ERROR); //读块失败
205 3 }
206 2 } while(temp!=0);
207 1
208 1 while(spi_read()!=0xfe); //一直读,当读到0xfe时,说明后面的是512字节的数据了
209 1
210 1 for(j=0;j<512;j++) //将数据写入到数据缓冲区中
211 1 {
212 2 buffer[j]=spi_read();
213 2 }
214 1
215 1 spi_read();
216 1 spi_read(); //读取两个字节的CRC校验码,不用关心
217 1
218 1 CS=1; //关闭片选
219 1 spi_write(0xff); //按照SD卡的操作时序在这里补8个时钟
220 1 return 0; //读取成功
221 1 }
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 900 ----
CONSTANT SIZE = 24 ----
XDATA SIZE = 513 52
PDATA SIZE = ---- ----
DATA SIZE = ---- ----
IDATA SIZE = ---- ----
BIT SIZE = ---- ----
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S) |
|