[菜农助学交流] 菜农M0助学板之读SD卡块内容小练(库操作方式)

[复制链接]
 楼主| tear086 发表于 2011-4-19 20:49 | 显示全部楼层 |阅读模式
本帖最后由 tear086 于 2011-4-19 20:59 编辑

之前是移植到Nios II上,而且是用得IO模拟的,现在使用nuc1xx的spi核做的,不过还是参考了新唐的例程。关于sd的一些笔记,我贴在博客了。今天在此就不赘述了。http://www.cnblogs.com/yuphone/category/272287.html

上代码先。
main.h
  1. #ifndef __MAIN_H__
  2. #define __MAIN_H__

  3. #include <stdio.h>

  4. /*********************************************************
  5. * 系统寄存器映射及库头文件
  6. *********************************************************/
  7. #include "NUC1xx.h" // 系统寄存器映射
  8. #include "DrvSYS.h"
  9. #include "DrvGPIO.h"
  10. #include "DrvUART.h"
  11. #include "DrvSPI.h"
  12. #include "sd_card.h"
  13. /**********************************************************
  14. * 自定义宏
  15. **********************************************************/
  16. #define APP_DEBUG

  17. #ifdef APP_DEBUG
  18.     #define DEBUG printf
  19. #else
  20.     #define DEBUG(...)
  21. #endif

  22. typedef enum{NO=0, YES=!NO}bool;

  23. #endif /* __MAIN_H__ */



main.c
  1. #include "main.h"
  2. /**********************************************************
  3. * 变量申明
  4. **********************************************************/
  5. volatile bool g_tmr0_5ms = NO;
  6. /**********************************************************
  7. * 函数申明
  8. **********************************************************/
  9. extern char GetChar(void);
  10. extern void PFN_UART_CALLBACK(void);
  11. /**********************************************************
  12. * 系统上电初始化
  13. **********************************************************/
  14. void MAIN_INIT(void)
  15. {
  16.     UNLOCKREG();
  17.     {   /* 配置系统时钟 */
  18.         SYSCLK->PWRCON.XTL12M_EN = 1; //  设定12M外部晶振
  19.         DrvSYS_Delay(5000); // 等待时钟就绪
  20.         DrvSYS_SelectPLLSource(E_SYS_EXTERNAL_12M); // 选择12MHz为PLL输入
  21.         DrvSYS_Open(50000000); // 打开50MHz
  22.     }      
  23.     {   /* 配置串口 */
  24.         STR_UART_T param;
  25.         
  26.         DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC, 0); //使能UART时钟
  27.         DrvGPIO_InitFunction(E_FUNC_UART0);    // 复用功能引脚设置
  28.                                                          
  29.         param.u32BaudRate        = 115200;    // 波特率
  30.         param.u8cDataBits        = DRVUART_DATABITS_8;  // 数据位
  31.         param.u8cStopBits        = DRVUART_STOPBITS_1;  // 停止位
  32.         param.u8cParity          = DRVUART_PARITY_NONE;    // 校验位
  33.         param.u8cRxTriggerLevel  = DRVUART_FIFO_1BYTES;    // FIFO存储深度1字节
  34.         param.u8TimeOut             = 0; // FIFO超时设定
  35.         DrvUART_Open(UART_PORT0, ¶m); // 串口开启、结构体整体赋值
  36.                
  37.         // 串口的中断类型比较丰富,此处仅打开接收中断
  38.         DrvUART_EnableInt(UART_PORT0, DRVUART_RDAINT, (PFN_DRVUART_CALLBACK*)PFN_UART_CALLBACK);
  39.         DrvUART_ClearIntFlag(UART_PORT0, DRVUART_RDAINT);
  40.     }
  41.     {   /* 配置GPIO */
  42.         NVIC_DisableIRQ(GPAB_IRQn);
  43.         NVIC_DisableIRQ(GPCDE_IRQn);
  44.         DrvGPIO_Open(E_GPB, 10, E_IO_OUTPUT); // 蜂鸣器
  45.         DrvGPIO_ClrBit(E_GPB, 10); // 关蜂鸣器
  46.     }
  47.     {   /* 配置TMR0 */
  48.         NVIC_DisableIRQ(TMR0_IRQn);
  49.         // 第一步 使能和选择定时器时钟源及使能定时器模块         
  50.         SYSCLK->CLKSEL1.TMR0_S = 0; // 选择12Mhz作为定时器时钟源
  51.         SYSCLK->APBCLK.TMR0_EN =1;  // 使能定时器0
  52.         TIMER0->TCSR.CEN = 1;       // 使能定时器模块
  53.         // 第二步 选择操作模式   
  54.         TIMER0->TCSR.MODE = 1; // 选择周期模式
  55.         TIMER0->TCSR.CRST = 1; // 清加1计数器   
  56.         // 第三步 输出时钟周期 = 定时器时钟源周期*(8位预分频因子 + 1) * (24位比较因子TCMP)
  57.         TIMER0->TCSR.PRESCALE = 11; // 12分频
  58.         TIMER0->TCMPR = 5000; // 12M/12/5000=200Hz, 5ms
  59.         // 第四步 使能中断
  60.         TIMER0->TISR.TIF = 1; // 清中断  
  61.         TIMER0->TCSR.IE = 1; // 使能中断
  62.         NVIC_EnableIRQ(TMR0_IRQn);  // 使能TMR0中断
  63.         // 第五步 使能定时器模块
  64.         TIMER0->TCSR.CRST = 1; // 复位向上计数器
  65.             TIMER0->TCSR.CEN = 1; // 使能TMR0
  66.         //TIMER0->TCSR.TDR_EN=1; // 无需读取加1计数器值
  67.     }
  68. //    {   /* 配置SPI0主机模式 */
  69. //        NVIC_DisableIRQ(SPI0_IRQn);
  70. //        // 第一步 使能SPI0核
  71. //        SYSCLK->APBCLK.SPI0_EN        =1;
  72. //                SYS->IPRSTC2.SPI0_RST         =1;
  73. //                SYS->IPRSTC2.SPI0_RST         =0;
  74. //        // 第二步 设置除GPIO外的第一功能
  75. //        SYS->GPCMFP.SPI0_SS0_I2SLRCLK =1;
  76. //                SYS->GPCMFP.SPI0_CLK_I2SBCLK  =1;               
  77. //                SYS->GPCMFP.SPI0_MISO0_I2SDI  =1;       
  78. //                SYS->GPCMFP.SPI0_MOSI0_I2SDO  =1;
  79. //        SYS->GPBMFP.TM2_SS01          =1;
  80. //        // 第三步 设置除GPIO外的第二功能
  81. //        SYS->ALTMFP.PC0_I2SLRCLK      =0;
  82. //        SYS->ALTMFP.PC1_I2SBCLK       =0;
  83. //        SYS->ALTMFP.PC2_I2SDI         =0;
  84. //        SYS->ALTMFP.PC3_I2SDO         =0;
  85. //        SYS->ALTMFP.PB10_S01          =1;
  86. //        // 第四步 配置SPI0模式
  87. //        SPI0->CNTRL.SLAVE = 0; // 0 主机模式;1 从机模式
  88. //        SPI0->CNTRL.CLKP = 0; // 0 SCLK低电平闲置;1 SCLK高电平闲置
  89. //        SPI0->CNTRL.TX_NEG = 0; // 0 上升沿传输;1 下降沿传输
  90. //        SPI0->CNTRL.TX_BIT_LEN = 8; // [0 31] 一次传输8位
  91. //        SPI0->CNTRL.TX_NUM = 0; // 0 每次传输完成一次收/发;1 每次传输完成两次收/发
  92. //        SPI0->CNTRL.LSB = 0; // 0 优先发送MSB;1 优先发送LSB
  93. //        // 第六步 配置从机选择
  94. //        SPI0->SSR.AUTOSS = 1; // 0 设置或清除SSR.SSR来决定是否产生从机选择信号
  95. //                              // 1 CNTRL.GO_BUSY设置后,SSR.SSR会由SPI核自动产生,只要一次收/发完成后结束
  96. //        SPI0->SSR.SS_LVL = 0; // 0 高电平/上升沿有效;1 低电平/下降沿有效
  97. //        // 第五步 设置时钟输出频率
  98. //        // 设置SPI0的时钟分频器
  99. //        SPI0->DIVIDER.DIVIDER = (uint16_t)((((DrvSYS_GetHCLKFreq()/2000000) + 1) >> 1) - 1); // 2MHz
  100. //                // 设置SPI0的第二个时钟分频器
  101. //        // SPI0->DIVIDER.DIVIDER2 = (uint16_t)((((DrvSYS_GetHCLKFreq()/10000) + 1) >> 1) - 1); // 10kHz
  102. //        SPI0->DIVIDER.DIVIDER2 = 0;
  103. //        // 第六步
  104. //        SPI0->TX[0] = 0; // 清TX[0]
  105. //        // SPI0->TX[1] = 0; // 清TX[1]
  106. //        SPI0->CNTRL.GO_BUSY = 1; // 触发一次SPI传输
  107. //        // 第七步 设置中断
  108. //        //SPI0->CNTRL.IE = 0; // 0 失能中断;1 使能中断
  109. //        //SPI0->CNTRL.IE = 1; // 写1清中断标志
  110. //        //NVIC_EnableIRQ(SPI0_IRQn);
  111. //        
  112. //    }
  113.     LOCKREG();
  114. }
  115. /**********************************************************
  116. * TMR0 ISR
  117. **********************************************************/
  118. void TMR0_IRQHandler(void) __irq
  119. {   // 注意:ISR内必须清中断
  120.     TIMER0->TISR.TIF = 1; // 清中断  

  121.     g_tmr0_5ms = YES;   
  122. }
  123. /**********************************************************
  124. * UART0 回调函数
  125. **********************************************************/
  126. void PFN_UART_CALLBACK(void)
  127. {   // 注意:回调函数内无须清中断
  128.     switch(GetChar()) {        
  129.         default:
  130.             DEBUG("test");
  131.             break;        
  132.     }                   
  133. }
  134. /**********************************************************
  135. * 主函数
  136. **********************************************************/
  137. int main(void)
  138. {
  139.     MAIN_INIT(); // 上电初始化系统
  140.     SD_CARD_Open();
  141.     SD_CARD_DEMO();  
  142.    
  143.     while(1) {
  144.         if(g_tmr0_5ms != NO) {
  145.             g_tmr0_5ms = NO;
  146.         }

  147.         if(0) break; // 跳出大循环
  148.     }
  149.    
  150.     SD_CARD_Close();
  151.     DrvUART_Close(UART_PORT0);
  152.     return 0;
  153. }
 楼主| tear086 发表于 2011-4-19 20:50 | 显示全部楼层
本帖最后由 tear086 于 2011-5-9 10:56 编辑

sd_card.h
  1. #ifndef SD_CARD_H_
  2. #define SD_CARD_H_

  3. #include "main.h"

  4. #define ENABLE_SD_CARD_DEBUG // 打开调试信息
  5. // debug switch
  6. #ifdef ENABLE_SD_CARD_DEBUG
  7.     #define SD_CARD_DEBUG    DEBUG
  8. #else
  9.     #define SD_CARD_DEBUG(...)
  10. #endif


  11. uint8_t SD_CARD_SPI_Transfer(uint8_t byte);
  12. uint8_t SD_CARD_Init(void);
  13. //
  14. void SD_CARD_Open(void);
  15. void SD_CARD_Close(void);
  16. uint8_t SD_CARD_Write_Sector(uint32_t addr,uint8_t *buf);
  17. uint8_t SD_CARD_Read_Sector(uint8_t *CMD,uint8_t *buf,uint16_t n_bytes);
  18. uint8_t SD_CARD_Read_Sector_Start(uint32_t sector);
  19. static void SD_CARD_Read_Data(uint16_t n_bytes,uint8_t *buf);
  20. void SD_CARD_Read_Data_LBA(uint32_t LBA,uint16_t n_bytes,uint8_t *buf);
  21. void SD_CARD_Read_Sector_End(void);
  22. static uint8_t SD_CARD_Read_CSD(uint8_t *buf);
  23. static uint8_t SD_CARD_Read_CID(uint8_t *buf);
  24. void SD_CARD_Get_Info(void);
  25. void SD_CARD_DEMO(void);


  26. #endif /* SD_CARD_H_ */



sd_card.c
  1. #include "sd_card.h"

  2. // 错误宏定义
  3. #define INIT_CMD0_ERROR     0x01
  4. #define INIT_CMD1_ERROR     0x02
  5. #define WRITE_BLOCK_ERROR   0x03
  6. #define READ_BLOCK_ERROR    0x04

  7. #define Delay_Us DrvSYS_Delay // us级延时
  8. #define SD_CARD_Set_nCS DrvSPI_ClrSS(eDRVSPI_PORT1, eDRVSPI_SS0) // nCS = 1
  9. #define SD_CARD_Clr_nCS DrvSPI_SetSS(eDRVSPI_PORT1, eDRVSPI_SS0) // nCS = 0

  10. typedef union{
  11.     uint8_t data[16];
  12.     struct{
  13.         uint8_t MID;    // Manufacture ID; Binary
  14.         uint8_t OLD[2]; // OEM/Application ID; ASCII
  15.         uint8_t PNM[5]; // Product Name; ASCII
  16.         uint8_t PRV;    // Product Revision; BCD
  17.         uint8_t PSN[4]; // Serial Number; Binary
  18.         uint8_t MDT[2]; // Manufacture Data Code; BCD; upper 4 bits of first byte are reserved
  19.         uint8_t CRC;    // CRC7_checksum; Binary; LSB are reserved
  20.     }CID;
  21. }CID_Info_STR;

  22. typedef struct{
  23.     uint8_t data[16];
  24.     uint32_t capacity_MB;
  25.     uint8_t READ_BL_LEN;
  26.     uint16_t C_SIZE;
  27.     uint8_t C_SIZE_MULT;
  28. }CSD_Info_STR;

  29. uint16_t gByteOffset=0; // 某字节在扇区内的偏移地址
  30. uint16_t gSectorOffset=0; // 扇区在SD卡内的偏移地址
  31. uint8_t gSectorOpened = 0; // 0 关闭扇区;1 打开扇区

  32. // 打开SD卡
  33. void SD_CARD_Open(void)
  34. {
  35.     DrvSYS_SetIPClock(E_SYS_SPI1_CLK,1);
  36.     DrvGPIO_InitFunction(E_FUNC_SPI1); // enable SPI function and pin
  37.    
  38.         DrvSPI_Open(eDRVSPI_PORT1,eDRVSPI_MASTER,eDRVSPI_TYPE1,8, FALSE);
  39.         DrvSPI_DisableAutoSS(eDRVSPI_PORT1);
  40.         DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT1, eDRVSPI_ACTIVE_LOW_FALLING);
  41.         DrvSPI_SetEndian(eDRVSPI_PORT1, eDRVSPI_MSB_FIRST);
  42.         DrvSPI_SetClockFreq(eDRVSPI_PORT1,300000,0);
  43.    
  44.     while(SD_CARD_Init() != 0x55);
  45.     SD_CARD_DEBUG(("SD卡初始化完成\r"));
  46.    
  47.         DrvSPI_SetClockFreq(eDRVSPI_PORT1,10000000,0);
  48. }


  49. // 关闭SD卡
  50. void SD_CARD_Close(void)
  51. {
  52.         DrvSPI_Close(eDRVSPI_PORT1);
  53. }


  54. // 收发一个字节
  55. static uint8_t SD_CARD_SPI_Transfer(uint8_t byte)
  56. {
  57.         uint32_t SPIdata=(uint32_t)byte;
  58.         DrvSPI_BurstTransfer(eDRVSPI_PORT1,1,2);
  59.         DrvSPI_SingleWrite(eDRVSPI_PORT1,&SPIdata);
  60.     while (DrvSPI_IsBusy(eDRVSPI_PORT1));
  61.         DrvSPI_DumpRxRegister(eDRVSPI_PORT1,&SPIdata,1);
  62.         return (uint8_t)SPIdata;
  63. }


  64. // SD卡写命令
  65. static uint8_t SD_CARD_Write_CMD(uint8_t *CMD)
  66. {
  67.     uint8_t temp,retry;
  68.     uint8_t i;

  69.     SD_CARD_Set_nCS; // 失能SD卡
  70.     SD_CARD_SPI_Transfer(0xFF); // 发8个脉冲
  71.     SD_CARD_Clr_nCS; // 使能SD卡

  72.     // 写6个字节到SD卡
  73.     for(i=0;i<6;i++) SD_CARD_SPI_Transfer(*CMD++);

  74.     // 读取16位响应
  75.     SD_CARD_SPI_Transfer(0xFF); // 第一个字节无效
  76.     retry=0;
  77.     do{ // 只取最后一个字节
  78.         temp=SD_CARD_SPI_Transfer(0xFF);
  79.         retry++;
  80.     }while((temp==0xFF) && (retry<100));
  81.    
  82.     return temp;
  83. }


  84. // 初始化SD卡;SPI模式
  85. static uint8_t SD_CARD_Init(void)
  86. {
  87.     uint8_t retry,temp;
  88.     uint8_t i;
  89.     uint8_t CMD[]={0x40,0x00,0x00,0x00,0x00,0x95};

  90.     SD_CARD_Set_nCS;
  91.     Delay_Us(10*1000);   
  92.     for(i=0;i<10;i++) // 最少先发74个脉冲
  93.         SD_CARD_SPI_Transfer(0xFF);
  94.     SD_CARD_Clr_nCS;

  95.     retry=0;
  96.     do{
  97.         temp=SD_CARD_Write_CMD(CMD);
  98.         retry++;
  99.         if(retry==200)
  100.             return INIT_CMD0_ERROR;
  101.     }while(temp!=1);

  102.     CMD[0]=0x41;// CMD[1]
  103.     CMD[5]=0xFF;
  104.     retry=0;
  105.     do{
  106.         temp=SD_CARD_Write_CMD(CMD);
  107.         retry++;
  108.         if(retry==100)   
  109.             return INIT_CMD1_ERROR;
  110.     }while(temp!=0);

  111.     SD_CARD_Set_nCS; // 失能SD卡
  112.    
  113.     return 0x55; // 初始化完成
  114. }


  115. // 写入一个块(扇区)
  116. uint8_t SD_CARD_Write_Sector(uint32_t addr,uint8_t *buf)
  117. {
  118.     uint8_t temp,retry;
  119.     uint16_t i;
  120.     uint8_t CMD[]={0x58,0x00,0x00,0x00,0x00,0xFF}; // CMD24

  121.     // 地址转换:逻辑块(扇区)地址 --> 字节地址
  122.     addr=addr << 9;
  123.     CMD[1]=((addr & 0xFF000000) >>24 );
  124.     CMD[2]=((addr & 0x00FF0000) >>16 );
  125.     CMD[3]=((addr & 0x0000FF00) >>8 );


  126.     retry=0;
  127.     do{
  128.         temp=SD_CARD_Write_CMD(CMD);
  129.         retry++;
  130.         if(retry==100)
  131.             return temp;
  132.     } while(temp!=0);

  133.     // 写数据前,先发100个脉冲;100/8=13
  134.     for(i=0;i<13;i++) SD_CARD_SPI_Transfer(0xFF);

  135.     // 写入开始字节
  136.     SD_CARD_SPI_Transfer(0xFE);

  137.     // 写入512个字节
  138.     for(i=0;i<512;i++) SD_CARD_SPI_Transfer(*buf++);

  139.     SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC
  140.     SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC

  141.     // 读取响应
  142.     temp=SD_CARD_SPI_Transfer(0xFF);
  143.     if( (temp & 0x1F)!=0x05 ) {// 数据被接收否?   
  144.         SD_CARD_Set_nCS; // 失能SD卡        
  145.         return WRITE_BLOCK_ERROR;
  146.     }

  147.     // 等待,只到SD卡不忙
  148.     while(SD_CARD_SPI_Transfer(0xFF)!=0xFF);

  149.     SD_CARD_Set_nCS; // 失能SD卡
  150.    
  151.     return 0;
  152. }


  153. // 读取块(扇区)内的字节(一般情况下,1块对应512字节)
  154. uint8_t SD_CARD_Read_Sector(uint8_t *CMD,uint8_t *buf,uint16_t n_bytes)
  155. {
  156.     uint16_t i;
  157.     uint8_t retry,temp;

  158.     retry=0;
  159.     do{
  160.         temp=SD_CARD_Write_CMD(CMD);
  161.         retry++;
  162.         if(retry==100)
  163.             return READ_BLOCK_ERROR;
  164.     }while(temp!=0);

  165.     // 读开始字节(0xFEh)
  166.     while(SD_CARD_SPI_Transfer(0xFF)!=0xFE);
  167.    
  168.     // 读取n个字节
  169.     for(i=0;i<n_bytes;i++) *buf++=SD_CARD_SPI_Transfer(0xFF);

  170.     SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC
  171.     SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC

  172.     SD_CARD_Set_nCS; // 失能SD卡
  173.    
  174.     return 0;
  175. }


  176. // 开始读取某个扇区
  177. uint8_t SD_CARD_Read_Sector_Start(uint32_t sector)
  178. {
  179.     uint8_t retry;
  180.     uint8_t CMD[]={0x51,0x00,0x00,0x00,0x00,0xFF}; // CMD16
  181.     uint8_t temp;

  182.     // 地址转换:逻辑块(扇区)地址 --> 字节地址
  183.     sector=sector << 9;
  184.     CMD[1]=((sector & 0xFF000000) >>24 );
  185.     CMD[2]=((sector & 0x00FF0000) >>16 );
  186.     CMD[3]=((sector & 0x0000FF00) >>8 );

  187.     retry=0;
  188.     do{
  189.         temp=SD_CARD_Write_CMD(CMD);
  190.         retry++;
  191.         if(retry==100)
  192.             return READ_BLOCK_ERROR;
  193.     }while(temp!=0);

  194.     // 读开始字节(0xFEh)
  195.     while(SD_CARD_SPI_Transfer(0xFF) != 0xFE);

  196.     gSectorOpened = 1; // 将扇区打开标志置一
  197.    
  198.     return 0;
  199. }


  200. static void SD_CARD_Read_Data(uint16_t n_bytes, uint8_t *buf)
  201. {
  202.     uint16_t i;
  203.     for(i=0; ((i<n_bytes) && (gByteOffset<512)); i++) {
  204.         *buf++ = SD_CARD_SPI_Transfer(0xFF);
  205.         gByteOffset++; // 读完一个字节;将扇区内的字节偏移地址加一
  206.     }
  207.     if(gByteOffset == 512) {
  208.         gByteOffset=0; // 将扇区内的字节偏移地址清零
  209.         
  210.         SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC
  211.         SD_CARD_SPI_Transfer(0xFF); // 假读;读取CRC
  212.         
  213.         gSectorOffset++; // 读完一个扇区;将SD卡内的扇区偏移地址加一
  214.         
  215.         gSectorOpened = 0; // 读完一个扇区后,扇区打开标志清零
  216.         SD_CARD_Set_nCS; // 失能SD卡
  217.     }
  218. }


  219. // 读取指定逻辑块地址(扇区偏移地址)内的数据;logic block address,LBA
  220. void SD_CARD_Read_Data_LBA(uint32_t LBA,uint16_t n_bytes,uint8_t *buf)
  221. {   // 如果某扇区被读完,则打开下一个扇区
  222.     if(gByteOffset == 0) while(SD_CARD_Read_Sector_Start(LBA));
  223.     SD_CARD_Read_Data(n_bytes,buf);
  224. }


  225. // 假读;读完某扇区内剩余的字节
  226. void SD_CARD_Read_Sector_End(void)
  227. {
  228.     uint8_t temp[1];
  229.     while((gByteOffset!=0x00) | (gSectorOpened==1))
  230.         SD_CARD_Read_Data(1,temp); // 假读
  231. }


  232. // 读SD卡的CSD寄存器
  233. static uint8_t SD_CARD_Read_CSD(uint8_t *buf)
  234. {
  235.     uint8_t CMD[]={0x49,0x00,0x00,0x00,0x00,0xFF};
  236.     return SD_CARD_Read_Sector(CMD,buf,16); // 读取16个字节
  237. }


  238. // 读SD卡的CID寄存器
  239. static uint8_t SD_CARD_Read_CID(uint8_t *buf)
  240. {
  241.     uint8_t CMD[]={0x4A,0x00,0x00,0x00,0x00,0xFF};
  242.     return SD_CARD_Read_Sector(CMD,buf,16); // 读取16个字节
  243. }


  244. void SD_CARD_Get_Info(void)
  245. {
  246.     CID_Info_STR CID;
  247.     CSD_Info_STR CSD;

  248.     SD_CARD_Read_CID(CID.data);
  249.     SD_CARD_DEBUG("SD-CARD CID:\r");
  250.     SD_CARD_DEBUG("    Manufacturer ID(MID): 0x%.2X\r", CID.CID.MID);
  251.     SD_CARD_DEBUG("    OEM/Application ID(OLD): %c%c\r", CID.CID.OLD[0], CID.CID.OLD[1]);
  252.     SD_CARD_DEBUG("    Product Name(PNM): %c%c%c%c%c\r", CID.CID.PNM[0], CID.CID.PNM[1], CID.CID.PNM[2], CID.CID.PNM[3], CID.CID.PNM[4]);
  253.     SD_CARD_DEBUG("    Product Revision: 0x%.2X\r", CID.CID.PRV);
  254.     SD_CARD_DEBUG("    Serial Number(PSN): 0x%.2X%.2X%.2X%.2X\r", CID.CID.PSN[0], CID.CID.PSN[1], CID.CID.PSN[2], CID.CID.PSN[3]);
  255.     SD_CARD_DEBUG("    Manufacture Date Code(MDT): 0x%.1X%.2X\r", CID.CID.MDT[0] & 0x0F, CID.CID.MDT[1]);
  256.     SD_CARD_DEBUG("    CRC-7 Checksum(CRC7):0x%.2X\r", CID.CID.CRC >> 1);

  257.     SD_CARD_Read_CSD(CSD.data);
  258.     CSD.C_SIZE = ((CSD.data[6]&0x03) << 10) | (CSD.data[7] << 2) | ((CSD.data[8]&0xC0) >>6);
  259.     CSD.C_SIZE_MULT = ((CSD.data[9]&0x03) << 1) | ((CSD.data[10]&0x80) >> 7);
  260.     CSD.READ_BL_LEN = (CSD.data[5]&0x0F);
  261.     CSD.capacity_MB = (((CSD.C_SIZE)+1) << (((CSD.C_SIZE_MULT) +2) + (CSD.READ_BL_LEN))) >> 20;
  262.     SD_CARD_DEBUG("SD-CARD CSD:\r");
  263.     SD_CARD_DEBUG("    max.read data block length: %d\r", 1<<CSD.READ_BL_LEN);
  264.     SD_CARD_DEBUG("    device size: %d\r", CSD.C_SIZE);
  265.     SD_CARD_DEBUG("    device size multiplier: %d\r", CSD.C_SIZE_MULT);
  266.     SD_CARD_DEBUG("    device capacity: %d MB\r", CSD.capacity_MB);
  267. }


  268. void SD_CARD_DEMO(void)
  269. {
  270.     uint16_t i;
  271.     uint8_t buf[512];
  272.    
  273.     SD_CARD_DEBUG("\r");   
  274.     SD_CARD_DEBUG("开始读取SD卡信息\r");   
  275.     SD_CARD_Get_Info(); // 读取CID和CSD
  276.     SD_CARD_DEBUG("SD卡信息读取完毕\r");
  277.    
  278.     SD_CARD_DEBUG("\r");
  279.     SD_CARD_DEBUG("开始读取SD卡的第一个块(扇区)\r");
  280.     SD_CARD_Read_Data_LBA(0,512,buf); // 读取SD卡的第一个块(扇区)
  281.     for(i=0; i<512; i++) {
  282.         if(i%16 == 0) SD_CARD_DEBUG("0x%.3X ", i);
  283.         SD_CARD_DEBUG("%.2X ", buf[i]);
  284.         if((i+1) % 8 == 0) SD_CARD_DEBUG(" ");
  285.         if((i+1) % 16 == 0) SD_CARD_DEBUG("\r");
  286.     }
  287.     SD_CARD_DEBUG("读取SD卡的第一个块(扇区)完毕\r");
  288. }
 楼主| tear086 发表于 2011-4-19 20:52 | 显示全部楼层
本帖最后由 tear086 于 2011-4-19 20:56 编辑

关于为何读取的第一个块内容与winhex所查看的第一个逻辑块内容不同的问题,请参见我的笔记。
http://www.cnblogs.com/yuphone/archive/2011/04/18/2019456.html
BSP包不在其内。文件目录如下:
--NUC100SeriesBSP
--sd
----docs
----list
----obj
----src

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
hotpower 发表于 2011-4-19 22:46 | 显示全部楼层
看看能否在SPI上用PDMA,看看两种方法在速度上的差异
weshiluwei6 发表于 2011-4-19 22:48 | 显示全部楼层
支持下啊
Cube 发表于 2011-4-20 02:33 | 显示全部楼层
支持,建议下一步移植FATFS
Swallow_0322 发表于 2011-4-20 07:43 | 显示全部楼层
顶!
hotpower 发表于 2011-4-20 08:38 | 显示全部楼层
非常好!
建议再用上pdma
plc_avr 发表于 2011-4-20 15:21 | 显示全部楼层
mark!
dong_abc 发表于 2011-4-23 13:31 | 显示全部楼层
很好的笔记
王紫豪 发表于 2011-5-2 19:40 | 显示全部楼层
你是缺氧? :lol
engelbert 发表于 2011-5-2 19:41 | 显示全部楼层
估计是,呵呵!
 楼主| tear086 发表于 2011-5-5 07:53 | 显示全部楼层
本帖最后由 tear086 于 2011-5-5 09:17 编辑

to 11楼 L12楼

先谢小马哥、瑞哥关注,祝安祺。小弟.COM 缺氧是也。
hotpower 发表于 2011-5-5 17:36 | 显示全部楼层
记着改成pdma,看看速度差异到底如何。
 楼主| tear086 发表于 2011-5-5 18:18 | 显示全部楼层
14# hotpower
lixupengarm 发表于 2011-5-23 17:53 | 显示全部楼层
mark!!
xdp63 发表于 2011-6-12 23:29 | 显示全部楼层
正在了解SD中。。。学习:handshake
ichuangj 发表于 2011-7-28 16:48 | 显示全部楼层
学习一个
hotpower 发表于 2011-7-28 17:45 | 显示全部楼层
缺氧最近没时间。
cecwxf 发表于 2011-8-3 11:39 | 显示全部楼层
貌似曾买过LZ的板子 顶
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:個人博客:yuphone.cnblogs.com 聯絡方式:張亞峰 15013013265@qq.com

0

主题

120

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部