久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5815|回復: 3
打印 上一主題 下一主題
收起左側

關于stm32spi讀寫sd卡cmd41一直返回0x01的解決辦法

[復制鏈接]
跳轉到指定樓層
樓主
先說一下我的情況,我的代碼是原子哥的,首先執行到cmd0,返回01,進入到idle狀態,這是沒有問題的,然后cmd8判斷是否為sdv2.0,返回01,這也是沒有問題的。然后循環發送cmd41(r1=SD_SendCmd(CMD41,0x40000000,0X01))和cmd55,返回值一直為0x01,正常來說,返回指應該0x00(我的卡是sdhc)。解決辦法:更換電源,我買的這個模塊的是可以用5v的,之前用的3v。推測可能是電流不夠。店家給的例程實在arduino上跑,我試了沒問題,看到電源我才感覺有點東西,這里踩個坑,希望能幫助到大家(第一次在論壇發帖,緊張。。。。)我用的例程放到下邊


單片機源程序如下:
  1. #include "sys.h"
  2. #include "sd-spi.h"                           
  3. #include "spi2.h"
  4. #include "usart.h"        
  5. #include<oled.h>

  6. u8  SD_Type=0;//SD卡的類型

  7. u8 SD_SPI_ReadWriteByte(u8 data)
  8. {
  9.         return SPI2_ReadWriteByte(data);
  10. }         
  11. //SD卡初始化的時候,需要低速
  12. void SD_SPI_SpeedLow(void)
  13. {
  14.          SPI2_SetSpeed(SPI_BaudRatePrescaler_256);//設置到低速模式        
  15. }
  16. //SD卡正常工作的時候,可以高速了
  17. void SD_SPI_SpeedHigh(void)
  18. {
  19.          SPI2_SetSpeed(SPI_BaudRatePrescaler_2);//設置到高速模式        
  20. }

  21. void SD_DisSelect(void)
  22. {
  23.         SD_CS=1;
  24.          SD_SPI_ReadWriteByte(0xff);//提供額外的8個時鐘
  25. }
  26. //選擇sd卡,并且等待卡準備OK
  27. //返回值:0,成功;1,失敗;
  28. u8 SD_Select(void)
  29. {
  30.         SD_CS=0;
  31.         if(SD_WaitReady()==0)return 0;//等待成功
  32.         SD_DisSelect();
  33.         return 1;//等待失敗
  34. }
  35. //等待卡準備好
  36. //返回值:0,準備好了;其他,錯誤代碼
  37. u8 SD_WaitReady(void)
  38. {
  39.         u32 t=0;
  40.         do
  41.         {
  42.                 if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
  43.                 t++;                          
  44.         }while(t<0XFFFFFF);//等待
  45.         return 1;
  46. }
  47. //等待SD卡回應
  48. //Response:要得到的回應值
  49. //返回值:0,成功得到了該回應值
  50. //    其他,得到回應值失敗
  51. u8 SD_GetResponse(u8 Response)
  52. {
  53.         u16 Count=0xFFFF;//等待次數                                                            
  54.         while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到準確的回應            
  55.         if (Count==0)return MSD_RESPONSE_FAILURE;//得到回應失敗   
  56.         else return MSD_RESPONSE_NO_ERROR;//正確回應
  57. }
  58. //從sd卡讀取一個數據包的內容
  59. //buf:數據緩存區
  60. //len:要讀取的數據長度.
  61. //返回值:0,成功;其他,失敗;        
  62. u8 SD_RecvData(u8*buf,u16 len)
  63. {                                    
  64.         if(SD_GetResponse(0xFE))return 1;//等待SD卡發回數據起始令牌0xFE
  65.     while(len--)//開始接收數據
  66.     {
  67.         *buf=SPI2_ReadWriteByte(0xFF);
  68.         buf++;
  69.     }
  70.     //下面是2個偽CRC(dummy CRC)
  71.     SD_SPI_ReadWriteByte(0xFF);
  72.     SD_SPI_ReadWriteByte(0xFF);                                                                                                                     
  73.     return 0;//讀取成功
  74. }
  75. //向sd卡寫入一個數據包的內容 512字節
  76. //buf:數據緩存區
  77. //cmd:指令
  78. //返回值:0,成功;其他,失敗;        
  79. u8 SD_SendBlock(u8*buf,u8 cmd)
  80. {        
  81.         u16 t;                           
  82.         if(SD_WaitReady())return 1;//等待準備失效
  83.         SD_SPI_ReadWriteByte(cmd);
  84.         if(cmd!=0XFD)//不是結束指令
  85.         {
  86.                 for(t=0;t<512;t++)SPI2_ReadWriteByte(buf[t]);//提高速度,減少函數傳參時間
  87.             SD_SPI_ReadWriteByte(0xFF);//忽略crc
  88.             SD_SPI_ReadWriteByte(0xFF);
  89.                 t=SD_SPI_ReadWriteByte(0xFF);//接收響應
  90.                 if((t&0x1F)!=0x05)return 2;//響應錯誤                                                                                                                     
  91.         }                                                                                                                                                                       
  92.     return 0;//寫入成功
  93. }

  94. //向SD卡發送一個命令
  95. //輸入: u8 cmd   命令
  96. //      u32 arg  命令參數
  97. //      u8 crc   crc校驗值           
  98. //返回值:SD卡返回的響應                                                                                                                          
  99. u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
  100. {
  101.     u8 r1;        
  102.         u8 Retry=0;
  103.         SD_DisSelect();//取消上次片選
  104.         if(SD_Select())return 0XFF;//片選失效
  105.         //發送
  106.     SD_SPI_ReadWriteByte(cmd | 0x40);//分別寫入命令
  107.     SD_SPI_ReadWriteByte(arg >> 24);
  108.     SD_SPI_ReadWriteByte(arg >> 16);
  109.     SD_SPI_ReadWriteByte(arg >> 8);
  110.     SD_SPI_ReadWriteByte(arg);         
  111.     SD_SPI_ReadWriteByte(crc);
  112.         if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
  113.     //等待響應,或超時退出
  114.         Retry=0X1F;
  115.         do
  116.         {
  117.                 r1=SD_SPI_ReadWriteByte(0xFF);
  118.         }while((r1&0X80) && Retry--);         
  119.         //返回狀態值
  120.     return r1;
  121. }                                                                                                                                                                              
  122. //獲取SD卡的CID信息,包括制造商信息
  123. //輸入: u8 *cid_data(存放CID的內存,至少16Byte)         
  124. //返回值:0:NO_ERR
  125. //                 1:錯誤                                                                                                                  
  126. u8 SD_GetCID(u8 *cid_data)
  127. {
  128.     u8 r1;           
  129.     //發CMD10命令,讀CID
  130.     r1=SD_SendCmd(CMD10,0,0x01);
  131.     if(r1==0x00)
  132.         {
  133.                 r1=SD_RecvData(cid_data,16);//接收16個字節的數據         
  134.     }
  135.         SD_DisSelect();//取消片選
  136.         if(r1)return 1;
  137.         else return 0;
  138. }                                                                                                                                                                  
  139. //獲取SD卡的CSD信息,包括容量和速度信息
  140. //輸入:u8 *cid_data(存放CID的內存,至少16Byte)            
  141. //返回值:0:NO_ERR
  142. //                 1:錯誤                                                                                                                  
  143. u8 SD_GetCSD(u8 *csd_data)
  144. {
  145.     u8 r1;         
  146.     r1=SD_SendCmd(CMD9,0,0x01);//發CMD9命令,讀CSD
  147.     if(r1==0)
  148.         {
  149.             r1=SD_RecvData(csd_data, 16);//接收16個字節的數據
  150.     }
  151.         SD_DisSelect();//取消片選
  152.         if(r1)return 1;
  153.         else return 0;
  154. }  
  155. //獲取SD卡的總扇區數(扇區數)   
  156. //返回值:0: 取容量出錯
  157. //       其他:SD卡的容量(扇區數/512字節)
  158. //每扇區的字節數必為512,因為如果不是512,則初始化不能通過.                                                                                                                  
  159. u32 SD_GetSectorCount(void)
  160. {
  161.     u8 csd[16];
  162.     u32 Capacity;  
  163.     u8 n;
  164.         u16 csize;                                             
  165.         //取CSD信息,如果期間出錯,返回0
  166.     if(SD_GetCSD(csd)!=0) return 0;            
  167.     //如果為SDHC卡,按照下面方式計算
  168.     if((csd[0]&0xC0)==0x40)         //V2.00的卡
  169.     {        
  170.                 csize = csd[9] + ((u16)csd[8] << 8) + 1;
  171.                 Capacity = (u32)csize << 10;//得到扇區數                           
  172.     }else//V1.XX的卡
  173.     {        
  174.                 n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
  175.                 csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
  176.                 Capacity= (u32)csize << (n - 9);//得到扇區數   
  177.     }
  178.     return Capacity;
  179. }
  180. //初始化SD卡
  181. u8 SD_Init(void)
  182. {
  183.     u8 r1;      // 存放SD卡的返回值
  184.     u16 retry;  // 用來進行超時計數
  185.     u8 buf[4];  
  186.         u16 i;

  187.         SPI2_Init();                //初始化IO
  188.         SD_Select();
  189.          SD_SPI_SpeedLow();        //設置到低速模式
  190.          for(i=0;i<10;i++)SD_SPI_ReadWriteByte(0XFF);//發送最少74個脈沖
  191.         retry=20;
  192.         do
  193.         {
  194.                 r1=SD_SendCmd(CMD0,0,0x95);//進入IDLE狀態
  195.         }while((r1!=0X01) && retry--);
  196.          SD_Type=0;//默認無卡
  197.         if(r1==0X01)
  198.         {        
  199.                
  200.                 if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
  201.                 {
  202.                         for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);        //Get trailing return value of R7 resp
  203.                         if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
  204.                         {
  205.                                 retry=0X0FFE;
  206.                                 do
  207.                                 {
  208.                                         SD_SendCmd(CMD55,0,0X01);        //發送CMD55
  209.                                         r1=SD_SendCmd(CMD41,0x40000000,0X01);//發送CMD41
  210.                                         OLED_DisplayHex(0,2,16,16,r1);
  211.                                 }while(r1&&retry--);
  212.                                 
  213.                                 if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鑒別SD2.0卡版本開始
  214.                                 {        
  215.                                         OLED_DisplayHex(0,0,16,16,0x22);
  216.                                         for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
  217.                                         if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC;    //檢查CCS
  218.                                         else SD_Type=SD_TYPE_V2;   
  219.                                 }
  220.                         }
  221.                 }else//SD V1.x/ MMC        V3
  222.                 {
  223.                         SD_SendCmd(CMD55,0,0X01);                //發送CMD55
  224.                         r1=SD_SendCmd(CMD41,0,0X01);        //發送CMD41
  225.                         if(r1<=1)
  226.                         {               
  227.                                 SD_Type=SD_TYPE_V1;
  228.                                 retry=0XFFFE;
  229.                                 do //等待退出IDLE模式
  230.                                 {
  231.                                         SD_SendCmd(CMD55,0,0X01);        //發送CMD55
  232.                                         r1=SD_SendCmd(CMD41,0,0X01);//發送CMD41
  233.                                 }while(r1&&retry--);
  234.                         }else//MMC卡不支持CMD55+CMD41識別
  235.                         {
  236.                                 SD_Type=SD_TYPE_MMC;//MMC V3
  237.                                 retry=0XFFFE;
  238.                                 do //等待退出IDLE模式
  239.                                 {                                                                                            
  240.                                         r1=SD_SendCmd(CMD1,0,0X01);//發送CMD1
  241.                                 }while(r1&&retry--);  
  242.                         }
  243.                         if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR;//錯誤的卡
  244.                 }
  245.         }
  246.         SD_DisSelect();//取消片選
  247.         SD_SPI_SpeedHigh();//高速
  248.         if(SD_Type)return 0;
  249.         else if(r1)return r1;            
  250.         return 0xaa;//其他錯誤
  251. }
  252. //讀SD卡
  253. //buf:數據緩存區
  254. //sector:扇區
  255. //cnt:扇區數
  256. //返回值:0,ok;其他,失敗.
  257. u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
  258. {
  259.         u8 r1;
  260.         if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//轉換為字節地址
  261.         if(cnt==1)
  262.         {
  263.                 r1=SD_SendCmd(CMD17,sector,0X01);//讀命令
  264.                 if(r1==0)//指令發送成功
  265.                 {
  266.                         r1=SD_RecvData(buf,512);//接收512個字節           
  267.                 }
  268.         }else
  269.         {
  270.                 r1=SD_SendCmd(CMD18,sector,0X01);//連續讀命令
  271.                 do
  272.                 {
  273.                         r1=SD_RecvData(buf,512);//接收512個字節         
  274.                         buf+=512;  
  275.                 }while(--cnt && r1==0);         
  276.                 SD_SendCmd(CMD12,0,0X01);        //發送停止命令
  277.         }   
  278.         SD_DisSelect();//取消片選
  279.         return r1;//
  280. }
  281. //寫SD卡
  282. //buf:數據緩存區
  283. //sector:起始扇區
  284. //cnt:扇區數
  285. //返回值:0,ok;其他,失敗.
  286. u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
  287. {
  288.         u8 r1;
  289.         if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//轉換為字節地址
  290.         if(cnt==1)
  291.         {
  292.                 r1=SD_SendCmd(CMD24,sector,0X01);//讀命令
  293.                 if(r1==0)//指令發送成功
  294.                 {
  295.                         r1=SD_SendBlock(buf,0xFE);//寫512個字節           
  296.                 }
  297.         }else
  298.         {
  299.                 if(SD_Type!=SD_TYPE_MMC)
  300.                 {
  301.                         SD_SendCmd(CMD55,0,0X01);        
  302.                         SD_SendCmd(CMD23,cnt,0X01);//發送指令        
  303.                 }
  304.                  r1=SD_SendCmd(CMD25,sector,0X01);//連續讀命令
  305.                 if(r1==0)
  306.                 {
  307.                         do
  308.                         {
  309.                                 r1=SD_SendBlock(buf,0xFC);//接收512個字節         
  310.                                 buf+=512;  
  311.                         }while(--cnt && r1==0);
  312.                         r1=SD_SendBlock(0,0xFD);//接收512個字節
  313.                 }
  314.         }   
  315.         SD_DisSelect();//取消片選
  316.         return r1;//
  317. }        
復制代碼

所有資料51hei提供下載:
Desktop.zip (5.84 KB, 下載次數: 36)


評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:840500 發表于 2020-11-8 11:21 | 只看該作者
換了電源也不行呢 ?
回復

使用道具 舉報

板凳
ID:833622 發表于 2022-10-5 20:22 | 只看該作者
感謝,一直是0x01幾天下來一直沒找到原因,之前也試過電源不行,今天把開發板和SD模塊同時都接上5v瞬間返回0x00
回復

使用道具 舉報

地板
ID:79094 發表于 2024-5-5 21:44 | 只看該作者
sd卡 不是3.3 供電嗎
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩免费视频 | 亚洲精品在线91 | 九九精品在线 | www.伊人.com| 青青草网站在线观看 | 91精品久久久久久久久久 | 亚洲成人精品一区 | 播放一级黄色片 | 蜜桃臀av一区二区三区 | 精品福利在线 | 国产三级日本三级 | 国产欧美精品一区二区三区 | 一区二区在线免费观看 | av天天干| 女同久久| 国产在线高清 | 国产一区二区三区视频 | 色888www视频在线观看 | 青青久视频 | 精品人伦一区二区三区蜜桃网站 | 中文字幕一区二区在线观看 | 欧美国产视频 | 一区二区三区四区不卡视频 | 精品国产乱码久久久久久蜜柚 | 亚洲aⅴ| 国产一级电影在线 | 欧美专区在线视频 | 精品无码三级在线观看视频 | 一呦二呦三呦国产精品 | 亚洲乱码一区二区三区在线观看 | 国产日韩欧美激情 | 成人永久免费 | 毛片久久久 | 中文字幕成人 | 亚洲人成人一区二区在线观看 | 国产精品 欧美精品 | 成人精品| 夜久久 | 久久激情视频 | 国产一区二区三区www | 欧美一区二区在线观看 |