sddriver.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. #include "sddriver.h"
  2. /* Private variables ---------------------------------------------------------*/
  3. u8 SD_Type=0;
  4. void SPI_Configuration(void)
  5. {
  6. GPIO_InitTypeDef GPIO_InitStructure;
  7. SPI_InitTypeDef SPI_InitStructure;
  8. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
  9. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
  10. /*----------------------SPI端口配置---------------------------------*/
  11. /*SPI_SCK SPI_MOSI 复用推挽输出*/
  12. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
  13. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  14. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  15. GPIO_Init(GPIOA, &GPIO_InitStructure);
  16. /*SPI_MISO 上拉输入模式*/
  17. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  18. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  19. GPIO_Init(GPIOA, &GPIO_InitStructure);
  20. /*SD_CS 推挽输出*/
  21. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  22. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  23. GPIO_Init(GPIOA, &GPIO_InitStructure);
  24. /*失能SD卡*/
  25. SD_CS_DISABLE();
  26. /*----------------------SPI1配置-----------------------------------*/
  27. /* 初始化 */
  28. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  29. SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  30. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  31. SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /*串行时钟稳定状态是高电平*/
  32. SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;/* 时钟活跃边沿???*/
  33. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  34. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; /*SPI波特率预分频*/
  35. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; /*高位在前*/
  36. SPI_InitStructure.SPI_CRCPolynomial = 7; /*the polynomial used for the CRC calculation*/
  37. SPI_Init(SPI1, &SPI_InitStructure);
  38. /* SPI1使能 */
  39. SPI_Cmd(SPI1, ENABLE);
  40. }
  41. void SPI_SetSpeed(u8 SpeedSet)
  42. {
  43. SPI_InitTypeDef SPI_InitStructure;
  44. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  45. SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  46. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  47. SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /*串行时钟稳定状态是高电平*/
  48. SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;/* 时钟活跃边沿???*/
  49. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  50. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; /*高位在前*/
  51. SPI_InitStructure.SPI_CRCPolynomial = 7; /*the polynomial used for the CRC calculation*/
  52. /*如果速度设置输入0,则低速模式,非0则高速模式*/
  53. if(SpeedSet==SPI_SPEED_LOW)
  54. {
  55. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  56. }
  57. else
  58. {
  59. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
  60. }
  61. SPI_Init(SPI1, &SPI_InitStructure);
  62. }
  63. /*******************************************************************************
  64. * Function Name : SPI_ReadWriteByte
  65. * Description : SPI读写一个字节(发送完成后返回本次通讯读取的数据)
  66. * Input : u8 TxData 待发送的数
  67. * Output : None
  68. * Return : u8 RxData 收到的数
  69. *******************************************************************************/
  70. u8 SPI_ReadWriteByte(u8 TxData)
  71. {
  72. u8 RxData = 0;
  73. while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); /*等待发送缓冲区空 */
  74. SPI_I2S_SendData(SPI1, TxData); /*发一个字节*/
  75. while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); /*等待数据接收 */
  76. RxData = SPI_I2S_ReceiveData(SPI1); /*返回接收到的数据*/
  77. return (u8)RxData;
  78. }
  79. /*******************************************************************************
  80. * Function Name : SD_SendCommand
  81. * Description : 向SD卡发送一个命令
  82. * Input : u8 cmd 命令
  83. * u32 arg 命令参数
  84. * u8 crc crc校验值
  85. * Output : None
  86. * Return : u8 r1 SD卡返回的响应
  87. *******************************************************************************/
  88. u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc)
  89. {
  90. unsigned char r1;
  91. unsigned char Retry = 0;
  92. SPI_ReadWriteByte(0xff);
  93. //片选端置低,选中SD卡
  94. SD_CS_ENABLE();
  95. //发送
  96. SPI_ReadWriteByte(cmd | 0x40); //分别写入命令
  97. SPI_ReadWriteByte(arg >> 24);
  98. SPI_ReadWriteByte(arg >> 16);
  99. SPI_ReadWriteByte(arg >> 8);
  100. SPI_ReadWriteByte(arg);
  101. SPI_ReadWriteByte(crc);
  102. //等待响应,或超时退出
  103. while((r1 = SPI_ReadWriteByte(0xFF))==0xFF)
  104. {
  105. Retry++;
  106. if(Retry > 200)
  107. {
  108. break;
  109. }
  110. }
  111. //关闭片选
  112. SD_CS_DISABLE();
  113. //在总线上额外增加8个时钟,让SD卡完成剩下的工作
  114. SPI_ReadWriteByte(0xFF);
  115. //返回状态值
  116. return r1;
  117. }
  118. /*******************************************************************************
  119. * Function Name : SD_SendCommand_NoDeassert
  120. * Description : 向SD卡发送一个命令(结束是不失能片选,还有后续数据传来)
  121. * Input : u8 cmd 命令
  122. * u32 arg 命令参数
  123. * u8 crc crc校验值
  124. * Output : None
  125. * Return : u8 r1 SD卡返回的响应
  126. *******************************************************************************/
  127. u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc)
  128. {
  129. unsigned char r1;
  130. unsigned char Retry = 0;
  131. //????????
  132. SPI_ReadWriteByte(0xff);
  133. //片选端置低,选中SD卡
  134. SD_CS_ENABLE();
  135. //发送
  136. SPI_ReadWriteByte(cmd | 0x40); //分别写入命令
  137. SPI_ReadWriteByte(arg >> 24);
  138. SPI_ReadWriteByte(arg >> 16);
  139. SPI_ReadWriteByte(arg >> 8);
  140. SPI_ReadWriteByte(arg);
  141. SPI_ReadWriteByte(crc);
  142. //等待响应,或超时退出
  143. while((r1 = SPI_ReadWriteByte(0xFF))==0xFF)
  144. {
  145. Retry++;
  146. if(Retry > 200)
  147. {
  148. break;
  149. }
  150. }
  151. //返回响应值
  152. return r1;
  153. }
  154. uint8_t SD_Init(void)
  155. {
  156. uint16_t i; /* 用来循环计数 */
  157. uint8_t r1; /* 存放SD卡的返回值 */
  158. uint16_t retry; /* 用来进行超时计数 */
  159. uint8_t buff[6];
  160. uint16_t temp;
  161. SPI_Configuration(); /* SD卡硬件初始化 */
  162. /*初始化设置为低速模式
  163. 因为SPI初始化时是低速的,SD卡初始化完成后设置为高速,
  164. 有的卡只要初始化一次就行,程序就ok;
  165. 但有的卡需要多次复位
  166. */
  167. SPI_SetSpeed(SPI_SPEED_LOW);
  168. /*先产生>74个脉冲,让SD卡自己初始化完成 */
  169. for(i=0;i<50;i++)
  170. {
  171. temp = SPI_ReadWriteByte(0xFF);
  172. }
  173. /*-----------------SD卡复位到idle开始-----------------*/
  174. /*
  175. 循环连续发送CMD0,直到SD卡返回0x01,进入IDLE状态
  176. 超时则直接退出
  177. */
  178. retry = 0;
  179. do
  180. {
  181. r1 = SD_SendCommand(CMD0, 0, 0x95); /*发送CMD0,让SD卡进入IDLE状态 */
  182. retry++;
  183. }while((r1 != 0x01) && (retry<200));
  184. /*跳出循环后,检查原因:初始化成功?or 重试超时?*/
  185. if(retry==200)
  186. {
  187. printf("\r\n 超时返回 \r\n");
  188. return 1; /* 超时返回1 */
  189. }
  190. printf("\r\n SD卡已复位到idle \r\n", temp);
  191. /*------------获取卡片的SD版本信息,并进行相应的初始化----------------*/
  192. r1 = SD_SendCommand_NoDeassert(8, 0x1aa, 0x87);
  193. printf("\r\n 卡片的SD版本信息:0x%x \r\n", r1);
  194. /*----------下面是v1.0版版本的初始化-----------*/
  195. if(r1 == 0x05)
  196. {
  197. //设置卡类型为SDV1.0,如果后面检测到为MMC卡,再修改为MMC
  198. SD_Type = SD_TYPE_V1;
  199. //如果是V1.0卡,CMD8指令后没有后续数据
  200. //片选置高,结束本次命令
  201. SD_CS_DISABLE();
  202. //多发8个CLK,让SD结束后续操作
  203. SPI_ReadWriteByte(0xFF);
  204. //-----------------SD卡、MMC卡初始化开始-----------------
  205. //发卡初始化指令CMD55+ACMD41
  206. // 如果有应答,说明是SD卡,且初始化完成
  207. // 没有回应,说明是MMC卡,额外进行相应初始化
  208. retry = 0;
  209. do
  210. {
  211. //先发CMD55,应返回0x01;否则出错
  212. r1 = SD_SendCommand(CMD55, 0, 0);
  213. if(r1 != 0x01)
  214. {
  215. return r1;
  216. }
  217. //得到正确响应后,发ACMD41,应得到返回值0x00,否则重试200次
  218. r1 = SD_SendCommand(ACMD41, 0, 0);
  219. retry++;
  220. }while((r1!=0x00) && (retry<400));
  221. // 判断是超时还是得到正确回应
  222. // 若有回应:是SD卡;没有回应:是MMC卡
  223. //----------MMC卡额外初始化操作开始------------
  224. if(retry==400)
  225. {
  226. retry = 0;
  227. //发送MMC卡初始化命令(没有测试)
  228. do
  229. {
  230. r1 = SD_SendCommand(1, 0, 0);
  231. retry++;
  232. }while((r1!=0x00)&& (retry<400));
  233. if(retry==400)
  234. {
  235. return 1; //MMC卡初始化超时
  236. }
  237. //写入卡类型
  238. SD_Type = SD_TYPE_MMC;
  239. }
  240. //----------MMC卡额外初始化操作结束------------
  241. //设置SPI为高速模式
  242. SPI_SetSpeed(1);
  243. SPI_ReadWriteByte(0xFF);
  244. //禁止CRC校验
  245. /*
  246. r1 = SD_SendCommand(CMD59, 0, 0x01);
  247. if(r1 != 0x00)
  248. {
  249. return r1; //命令错误,返回r1
  250. }
  251. */
  252. //设置Sector Size
  253. r1 = SD_SendCommand(CMD16, 512, 0xff);
  254. if(r1 != 0x00)
  255. {
  256. return r1; //命令错误,返回r1
  257. }
  258. }
  259. /*-------------------下面是V2.0卡的初始化--------------------------*/
  260. /*其中需要读取OCR数据,判断是SD2.0还是SD2.0HC卡*/
  261. else if(r1 == 0x01)
  262. {
  263. printf("\r\n 这是V2.0的卡 \r\n");
  264. //V2.0的卡,CMD8命令后会传回4字节的数据,要跳过再结束本命令
  265. buff[0] = SPI_ReadWriteByte(0xFF); //should be 0x00
  266. buff[1] = SPI_ReadWriteByte(0xFF); //should be 0x00
  267. buff[2] = SPI_ReadWriteByte(0xFF); //should be 0x01
  268. buff[3] = SPI_ReadWriteByte(0xFF); //should be 0xAA
  269. SD_CS_DISABLE();
  270. //the next 8 clocks
  271. SPI_ReadWriteByte(0xFF);
  272. //判断该卡是否支持2.7V-3.6V的电压范围
  273. if(buff[2]==0x01 && buff[3]==0xAA)
  274. {
  275. //支持电压范围,可以操作
  276. printf("\r\n 支持电压范围,可以操作 \r\n");
  277. retry = 0;
  278. //发卡初始化指令CMD55+ACMD41
  279. do
  280. {
  281. r1 = SD_SendCommand(CMD55, 0, 0);
  282. if(r1!=0x01)
  283. {
  284. return r1;
  285. }
  286. r1 = SD_SendCommand(ACMD41, 0x40000000, 0);
  287. if(retry>200)
  288. {
  289. return r1; //超时则返回r1状态
  290. }
  291. }while(r1!=0);
  292. printf("\r\n 初始化指令发送完成 \r\n");
  293. //初始化指令发送完成,接下来获取OCR信息
  294. //-----------鉴别SD2.0卡版本开始-----------
  295. r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);
  296. if(r1!=0x00)
  297. {
  298. return r1; //如果命令没有返回正确应答,直接退出,返回应答
  299. }
  300. printf("\r\n SD2.0卡版本鉴别结束 r1 = 0x%x \r\n", r1);
  301. //读OCR指令发出后,紧接着是4字节的OCR信息
  302. buff[0] = SPI_ReadWriteByte(0xFF);
  303. buff[1] = SPI_ReadWriteByte(0xFF);
  304. buff[2] = SPI_ReadWriteByte(0xFF);
  305. buff[3] = SPI_ReadWriteByte(0xFF);
  306. //OCR接收完成,片选置高
  307. SD_CS_DISABLE();
  308. SPI_ReadWriteByte(0xFF);
  309. //检查接收到的OCR中的bit30位(CCS),确定其为SD2.0还是SDHC
  310. //如果CCS=1:SDHC CCS=0:SD2.0
  311. if(buff[0]&0x40) //检查CCS
  312. {
  313. SD_Type = SD_TYPE_V2HC;
  314. }
  315. else
  316. {
  317. SD_Type = SD_TYPE_V2;
  318. }
  319. //设置SPI为高速模式
  320. SPI_SetSpeed(SPI_SPEED_HIGH);
  321. }
  322. }
  323. printf("\r\n 初始化结束,返回的r1 = 0x%x",r1);
  324. return r1;
  325. }
  326. /*******************************************************************************
  327. * Function Name : SD_ReadSingleBlock
  328. * Description : 读SD卡的一个block
  329. * Input : u32 sector 取地址(sector值,非物理地址)
  330. * u8 *buffer 数据存储地址(大小至少512byte)
  331. * Output : None
  332. * Return : u8 r1
  333. * 0: 成功
  334. * other:失败
  335. *******************************************************************************/
  336. u8 SD_ReadSingleBlock(u32 sector, u8 *buffer)
  337. {
  338. u8 r1;
  339. //设置为高速模式
  340. SPI_SetSpeed(SPI_SPEED_HIGH);
  341. if(SD_Type==SD_TYPE_V2HC)
  342. {
  343. sector = sector>>9;
  344. }
  345. r1 = SD_SendCommand(CMD17, sector, 0);//读命令
  346. if(r1 != 0x00)
  347. {
  348. return r1;
  349. }
  350. r1 = SD_ReceiveData(buffer, 512, RELEASE);
  351. if(r1 != 0)
  352. {
  353. return r1; //读数据出错!
  354. }
  355. else
  356. {
  357. return 0;
  358. }
  359. }
  360. /*******************************************************************************
  361. * Function Name : SD_ReadMultiBlock
  362. * Description : 读SD卡的多个block
  363. * Input : u32 sector 取地址(sector值,非物理地址)
  364. * u8 *buffer 数据存储地址(大小至少512byte)
  365. * u8 count 连续读count个block
  366. * Output : None
  367. * Return : u8 r1
  368. * 0: 成功
  369. * other:失败
  370. *******************************************************************************/
  371. u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count)
  372. {
  373. u8 r1;
  374. //设置为高速模式
  375. SPI_SetSpeed(SPI_SPEED_HIGH);
  376. if(SD_Type==SD_TYPE_V2HC)
  377. {
  378. sector = sector>>9;
  379. }
  380. //SD_WaitReady();
  381. //发读多块命令
  382. r1 = SD_SendCommand(CMD18, sector, 0);//读命令
  383. if(r1 != 0x00)
  384. {
  385. return r1;
  386. }
  387. //开始接收数据
  388. do
  389. {
  390. if(SD_ReceiveData(buffer, 512, NO_RELEASE) != 0x00)
  391. {
  392. break;
  393. }
  394. buffer += 512;
  395. } while(--count);
  396. //全部传输完毕,发送停止命令
  397. SD_SendCommand(CMD12, 0, 0);
  398. //释放总线
  399. SD_CS_DISABLE();
  400. SPI_ReadWriteByte(0xFF);
  401. if(count != 0)
  402. {
  403. return count; //如果没有传完,返回剩余个数
  404. }
  405. else
  406. {
  407. return 0;
  408. }
  409. }
  410. /*******************************************************************************
  411. * Function Name : SD_WriteSingleBlock
  412. * Description : 写入SD卡的一个block
  413. * Input : u32 sector 扇区地址(sector值,非物理地址)
  414. * u8 *buffer 数据存储地址(大小至少512byte)
  415. * Output : None
  416. * Return : u8 r1
  417. * 0: 成功
  418. * other:失败
  419. *******************************************************************************/
  420. u8 SD_WriteSingleBlock(u32 sector, const u8 *data)
  421. {
  422. u8 r1;
  423. u16 i;
  424. u16 retry;
  425. //设置为高速模式
  426. SPI_SetSpeed(SPI_SPEED_HIGH);
  427. //如果不是SDHC,给定的是sector地址,将其转换成byte地址
  428. if(SD_Type==SD_TYPE_V2HC)
  429. {
  430. sector = sector>>9;
  431. }
  432. r1 = SD_SendCommand(CMD24, sector, 0x00);
  433. if(r1 != 0x00)
  434. {
  435. return r1; //应答不正确,直接返回
  436. }
  437. //开始准备数据传输
  438. SD_CS_ENABLE();
  439. //先放3个空数据,等待SD卡准备好
  440. SPI_ReadWriteByte(0xff);
  441. SPI_ReadWriteByte(0xff);
  442. SPI_ReadWriteByte(0xff);
  443. //放起始令牌0xFE
  444. SPI_ReadWriteByte(0xFE);
  445. //放一个sector的数据
  446. for(i=0;i<512;i++)
  447. {
  448. SPI_ReadWriteByte(*data++);
  449. }
  450. //发2个Byte的dummy CRC
  451. SPI_ReadWriteByte(0xff);
  452. SPI_ReadWriteByte(0xff);
  453. //等待SD卡应答
  454. r1 = SPI_ReadWriteByte(0xff);
  455. if((r1&0x1F)!=0x05)
  456. {
  457. SD_CS_DISABLE();
  458. return r1;
  459. }
  460. //等待操作完成
  461. retry = 0;
  462. while(!SPI_ReadWriteByte(0xff))
  463. {
  464. retry++;
  465. if(retry>0xfffe) //如果长时间写入没有完成,报错退出
  466. {
  467. SD_CS_DISABLE();
  468. return 1; //写入超时返回1
  469. }
  470. }
  471. //写入完成,片选置1
  472. SD_CS_DISABLE();
  473. SPI_ReadWriteByte(0xff);
  474. return 0;
  475. }
  476. /*******************************************************************************
  477. * Function Name : SD_WaitReady
  478. * Description : 等待SD卡Ready
  479. * Input : None
  480. * Output : None
  481. * Return : u8
  482. * 0: 成功
  483. * other:失败
  484. *******************************************************************************/
  485. u8 SD_WaitReady(void)
  486. {
  487. u8 r1;
  488. u16 retry;
  489. retry = 0;
  490. do
  491. {
  492. r1 = SPI_ReadWriteByte(0xFF);
  493. if(retry==0xfffe)
  494. {
  495. return 1;
  496. }
  497. }while(r1!=0xFF);
  498. return 0;
  499. }
  500. /*******************************************************************************
  501. * Function Name : SD_GetCapacity
  502. * Description : 获取SD卡的容量
  503. * Input : None
  504. * Output : None
  505. * Return : u32 capacity
  506. * 0: 取容量出错
  507. *******************************************************************************/
  508. u32 SD_GetCapacity(void)
  509. {
  510. u8 csd[16];
  511. u32 Capacity;
  512. u8 r1;
  513. u16 i;
  514. u16 temp;
  515. //取CSD信息,如果期间出错,返回0
  516. if(SD_GetCSD(csd)!=0)
  517. {
  518. return 0;
  519. }
  520. //如果为SDHC卡,按照下面方式计算
  521. if((csd[0]&0xC0)==0x40)
  522. {
  523. Capacity = ((((u32)csd[8])<<8) + (u32)csd[9] +1)*(u32)1024;
  524. }
  525. else
  526. {
  527. /**
  528. 下面代码为网上版本 容量计算
  529. * formula of the capacity
  530. * memory capacity = BLOCKNR * BLOCK_LEN
  531. * BLOCKNR = (C_SIZE + 1)* MULT
  532. * C_SIZE_MULT+2
  533. * MULT = 2
  534. * READ_BL_LEN
  535. * BLOCK_LEN = 2
  536. **/
  537. //C_SIZE
  538. i = csd[6]&0x03;
  539. i<<=8;
  540. i += csd[7];
  541. i<<=2;
  542. i += ((csd[8]&0xc0)>>6);
  543. //C_SIZE_MULT
  544. r1 = csd[9]&0x03;
  545. r1<<=1;
  546. r1 += ((csd[10]&0x80)>>7);
  547. //BLOCKNR
  548. r1+=2;
  549. temp = 1;
  550. while(r1)
  551. {
  552. temp*=2;
  553. r1--;
  554. }
  555. Capacity = ((u32)(i+1))*((u32)temp);
  556. // READ_BL_LEN
  557. i = csd[5]&0x0f;
  558. //BLOCK_LEN
  559. temp = 1;
  560. while(i)
  561. {
  562. temp*=2;
  563. i--;
  564. }
  565. //The final result
  566. Capacity *= (u32)temp;
  567. //Capacity /= 512;
  568. }
  569. return (u32)Capacity;
  570. }
  571. /*******************************************************************************
  572. * Function Name : SD_GetCSD
  573. * Description : 获取SD卡的CSD信息,包括容量和速度信息
  574. * Input : u8 *cid_data(存放CID的内存,至少16Byte)
  575. * Output : None
  576. * Return : u8
  577. * 0:NO_ERR
  578. * 1:TIME_OUT
  579. * other:错误信息
  580. *******************************************************************************/
  581. u8 SD_GetCSD(u8 *csd_data)
  582. {
  583. u8 r1;
  584. //发CMD9命令,读CSD
  585. r1 = SD_SendCommand(CMD9, 0, 0xFF);
  586. if(r1 != 0x00)
  587. {
  588. return r1; //没返回正确应答,则退出,报错
  589. }
  590. //接收16个字节的数据
  591. SD_ReceiveData(csd_data, 16, RELEASE);
  592. return 0;
  593. }
  594. /*******************************************************************************
  595. * Function Name : SD_ReceiveData
  596. * Description : 从SD卡中读回指定长度的数据,放置在给定位置
  597. * Input : u8 *data(存放读回数据的内存>len)
  598. * u16 len(数据长度)
  599. * u8 release(传输完成后是否释放总线CS置高 0:不释放 1:释放)
  600. * Output : None
  601. * Return : u8
  602. * 0:NO_ERR
  603. * other:错误信息
  604. *******************************************************************************/
  605. u8 SD_ReceiveData(u8 *data, u16 len, u8 release)
  606. {
  607. u16 retry;
  608. u8 r1;
  609. // 启动一次传输
  610. SD_CS_ENABLE();
  611. //等待SD卡发回数据起始令牌0xFE
  612. retry = 0;
  613. do
  614. {
  615. r1 = SPI_ReadWriteByte(0xFF);
  616. retry++;
  617. if(retry>2000) //2000次等待后没有应答,退出报错
  618. {
  619. SD_CS_DISABLE();
  620. return 1;
  621. }
  622. }while(r1 != 0xFE);
  623. //开始接收数据
  624. while(len--)
  625. {
  626. *data = SPI_ReadWriteByte(0xFF);
  627. data++;
  628. }
  629. //下面是2个伪CRC(dummy CRC)
  630. SPI_ReadWriteByte(0xFF);
  631. SPI_ReadWriteByte(0xFF);
  632. //按需释放总线,将CS置高
  633. if(release == RELEASE)
  634. {
  635. //传输结束
  636. SD_CS_DISABLE();
  637. SPI_ReadWriteByte(0xFF);
  638. }
  639. return 0;
  640. }
  641. /*******************************************************************************
  642. * Function Name : SD_WriteMultiBlock
  643. * Description : 写入SD卡的N个block
  644. * Input : u32 sector 扇区地址(sector值,非物理地址)
  645. * u8 *buffer 数据存储地址(大小至少512byte)
  646. * u8 count 写入的block数目
  647. * Output : None
  648. * Return : u8 r1
  649. * 0: 成功
  650. * other:失败
  651. *******************************************************************************/
  652. u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count)
  653. {
  654. u8 r1;
  655. u16 i;
  656. //设置为高速模式
  657. SPI_SetSpeed(SPI_SPEED_HIGH);
  658. //如果不是SDHC,给定的是sector地址,将其转换成byte地址
  659. if(SD_Type == SD_TYPE_V2HC)
  660. {
  661. sector = sector>>9;
  662. }
  663. //如果目标卡不是MMC卡,启用ACMD23指令使能预擦除
  664. if(SD_Type != SD_TYPE_MMC)
  665. {
  666. r1 = SD_SendCommand(ACMD23, count, 0x00);
  667. }
  668. //发多块写入指令
  669. r1 = SD_SendCommand(CMD25, sector, 0x00);
  670. if(r1 != 0x00)
  671. {
  672. return r1; //应答不正确,直接返回
  673. }
  674. //开始准备数据传输
  675. SD_CS_ENABLE();
  676. //先放3个空数据,等待SD卡准备好
  677. SPI_ReadWriteByte(0xff);
  678. SPI_ReadWriteByte(0xff);
  679. //--------下面是N个sector写入的循环部分
  680. do
  681. {
  682. //放起始令牌0xFC 表明是多块写入
  683. SPI_ReadWriteByte(0xFC);
  684. //放一个sector的数据
  685. for(i=0;i<512;i++)
  686. {
  687. SPI_ReadWriteByte(*data++);
  688. }
  689. //发2个Byte的dummy CRC
  690. SPI_ReadWriteByte(0xff);
  691. SPI_ReadWriteByte(0xff);
  692. //等待SD卡应答
  693. r1 = SPI_ReadWriteByte(0xff);
  694. if((r1&0x1F)!=0x05)
  695. {
  696. SD_CS_DISABLE(); //如果应答为报错,则带错误代码直接退出
  697. return r1;
  698. }
  699. //等待SD卡写入完成
  700. if(SD_WaitReady()==1)
  701. {
  702. SD_CS_DISABLE(); //等待SD卡写入完成超时,直接退出报错
  703. return 1;
  704. }
  705. //本sector数据传输完成
  706. }while(--count);
  707. //发结束传输令牌0xFD
  708. r1 = SPI_ReadWriteByte(0xFD);
  709. if(r1==0x00)
  710. {
  711. count = 0xfe;
  712. }
  713. if(SD_WaitReady())
  714. {
  715. while(1)
  716. {
  717. }
  718. }
  719. //写入完成,片选置1
  720. SD_CS_DISABLE();
  721. SPI_ReadWriteByte(0xff);
  722. return count; //返回count值,如果写完则count=0,否则count=1
  723. }