找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3621|回复: 1
收起左侧

stm32 sd卡bootloader升级程序

[复制链接]
ID:473593 发表于 2019-3-13 11:01 | 显示全部楼层 |阅读模式
单片机源程序如下:
  1. #include "public.h"       

  2. //大篇幅修改V1.0代码.参考fatfs代码移植过来.
  3. //////////////////////////////////////////////////////////////////////////////////
  4. u8  SD_Type=0;//SD卡的类型



  5. ////////////////////////////////////移植修改区///////////////////////////////////
  6. //移植时候的接口
  7. //data:要写入的数据
  8. //返回值:读到的数据
  9. u8 SD_SPI_ReadWriteByte(u8 data)
  10. {
  11.         return SPIx_ReadWriteByte(data);
  12. }
  13. //SD卡初始化的时候,需要低速
  14. void SD_SPI_SpeedLow(void)
  15. {
  16.         SPIx_SetSpeed(SPI_SPEED_256);//设置到低速模式       
  17. }
  18. //SD卡正常工作的时候,可以高速了
  19. void SD_SPI_SpeedHigh(void)
  20. {
  21.         SPIx_SetSpeed(SPI_SPEED_4);//设置到高速模式       
  22. }
  23. //SPI硬件层初始化
  24. void SD_SPI_Init(void)
  25. {
  26.      //设置硬件上与SD卡相关联的控制引脚输出
  27.         //避免NRF24L01/W25X16等的影响
  28.         RCC->APB2ENR|=1<<2;       //PORTA时钟使能
  29.         GPIOA->CRL&=0XFFF000FF;
  30.         GPIOA->CRL|=0X00033300;//PA2.3.4 推挽             
  31.         GPIOA->ODR|=0X7<<2;    //PA2.3.4上拉
  32.         SPIx_Init();
  33.         SD_SPI_SpeedLow();//设置到低速模式         
  34.         SD_CS=1;
  35. }
  36. ///////////////////////////////////////////////////////////////////////////////////
  37. //取消选择,释放SPI总线
  38. void SD_DisSelect(void)
  39. {
  40.         SD_CS=1;
  41.         SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
  42. }
  43. //选择sd卡,并且等待卡准备OK
  44. //返回值:0,成功;1,失败;
  45. u8 SD_Select(void)
  46. {
  47.         SD_CS=0;
  48.         if(SD_WaitReady()==0)return 0;//等待成功
  49.         SD_DisSelect();
  50.         return 1;//等待失败
  51. }
  52. //等待卡准备好
  53. //返回值:0,准备好了;其他,错误代码
  54. u8 SD_WaitReady(void)
  55. {
  56.         u32 t=0;
  57.         do
  58.         {
  59.                 if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
  60.                 t++;                         
  61.         }while(t<0XFFFFFF);//等待
  62.         return 1;
  63. }
  64. //等待SD卡回应
  65. //Response:要得到的回应值
  66. //返回值:0,成功得到了该回应值
  67. //    其他,得到回应值失败
  68. u8 SD_GetResponse(u8 Response)
  69. {
  70.         u16 Count=0xFFF;//等待次数                                                             
  71.         while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到准确的回应            
  72.         if (Count==0)return MSD_RESPONSE_FAILURE;//得到回应失败   
  73.         else return MSD_RESPONSE_NO_ERROR;//正确回应
  74. }
  75. //从sd卡读取一个数据包的内容
  76. //buf:数据缓存区
  77. //len:要读取的数据长度.
  78. //返回值:0,成功;其他,失败;       
  79. u8 SD_RecvData(u8*buf,u16 len)
  80. {                                    
  81.         if(SD_GetResponse(0xFE))return 1;//等待SD卡发回数据起始令牌0xFE
  82.     while(len--)//开始接收数据
  83.     {
  84.         *buf=SD_SPI_ReadWriteByte(0xFF);
  85.         buf++;
  86.     }
  87.     //下面是2个伪CRC(dummy CRC)
  88.     SD_SPI_ReadWriteByte(0xFF);
  89.     SD_SPI_ReadWriteByte(0xFF);                                                                                                                      
  90.     return 0;//读取成功
  91. }
  92. //向sd卡写入一个数据包的内容 512字节
  93. //buf:数据缓存区
  94. //cmd:指令
  95. //返回值:0,成功;其他,失败;       
  96. u8 SD_SendBlock(u8*buf,u8 cmd)
  97. {       
  98.         u16 t;                            
  99.         if(SD_WaitReady())return 1;//等待准备失效
  100.         SD_SPI_ReadWriteByte(cmd);
  101.         if(cmd!=0XFD)//不是结束指令
  102.         {
  103.                 for(t=0;t<512;t++)SD_SPI_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间
  104.             SD_SPI_ReadWriteByte(0xFF);//忽略crc
  105.             SD_SPI_ReadWriteByte(0xFF);
  106.                 t=SD_SPI_ReadWriteByte(0xFF);//接收响应
  107.                 if((t&0x1F)!=0x05)return 2;//响应错误                                                                                                                      
  108.         }                                                                                                                                                                       
  109.     return 0;//写入成功
  110. }

  111. //向SD卡发送一个命令
  112. //输入: u8 cmd   命令
  113. //      u32 arg  命令参数
  114. //      u8 crc   crc校验值          
  115. //返回值:SD卡返回的响应                                                                                                                          
  116. u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
  117. {
  118.     u8 r1;       
  119.         u8 Retry=0;
  120.         SD_DisSelect();//取消上次片选
  121.         if(SD_Select())return 0XFF;//片选失效
  122.         //发送
  123.     SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令
  124.     SD_SPI_ReadWriteByte(arg >> 24);
  125.     SD_SPI_ReadWriteByte(arg >> 16);
  126.     SD_SPI_ReadWriteByte(arg >> 8);
  127.     SD_SPI_ReadWriteByte(arg);          
  128.     SD_SPI_ReadWriteByte(crc);
  129.         if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
  130.     //等待响应,或超时退出
  131.         Retry=0X1F;
  132.         do
  133.         {
  134.                 r1=SD_SPI_ReadWriteByte(0xFF);
  135.         }while((r1&0X80) && Retry--);         
  136.         //返回状态值
  137.     return r1;
  138. }                                                                                                                                                                              
  139. //获取SD卡的CID信息,包括制造商信息
  140. //输入: u8 *cid_data(存放CID的内存,至少16Byte)          
  141. //返回值:0:NO_ERR
  142. //                 1:错误                                                                                                                  
  143. u8 SD_GetCID(u8 *cid_data)
  144. {
  145.     u8 r1;          
  146.     //发CMD10命令,读CID
  147.     r1=SD_SendCmd(CMD10,0,0x01);
  148.     if(r1==0x00)
  149.         {
  150.                 r1=SD_RecvData(cid_data,16);//接收16个字节的数据         
  151.     }
  152.         SD_DisSelect();//取消片选
  153.         if(r1)return 1;
  154.         else return 0;
  155. }                                                                                                                                                                  
  156. //获取SD卡的CSD信息,包括容量和速度信息
  157. //输入:u8 *cid_data(存放CID的内存,至少16Byte)            
  158. //返回值:0:NO_ERR
  159. //                 1:错误                                                                                                                  
  160. u8 SD_GetCSD(u8 *csd_data)
  161. {
  162.     u8 r1;         
  163.     r1=SD_SendCmd(CMD9,0,0x01);//发CMD9命令,读CSD
  164.     if(r1==0)
  165.         {
  166.             r1=SD_RecvData(csd_data, 16);//接收16个字节的数据
  167.     }
  168.         SD_DisSelect();//取消片选
  169.         if(r1)return 1;
  170.         else return 0;
  171. }  
  172. //获取SD卡的总扇区数(扇区数)   
  173. //返回值:0: 取容量出错
  174. //       其他:SD卡的容量(扇区数/512字节)
  175. //每扇区的字节数必为512,因为如果不是512,则初始化不能通过.                                                                                                                  
  176. u32 SD_GetSectorCount(void)
  177. {
  178.     u8 csd[16];
  179.     u32 Capacity;  
  180.     u8 n;
  181.         u16 csize;                                              
  182.         //取CSD信息,如果期间出错,返回0
  183.     if(SD_GetCSD(csd)!=0) return 0;            
  184.     //如果为SDHC卡,按照下面方式计算
  185.     if((csd[0]&0xC0)==0x40)         //V2.00的卡
  186.     {       
  187.                 csize = csd[9] + ((u16)csd[8] << 8) + 1;
  188.                 Capacity = (u32)csize << 10;//得到扇区数                           
  189.     }else//V1.XX的卡
  190.     {       
  191.                 n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
  192.                 csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
  193.                 Capacity= (u32)csize << (n - 9);//得到扇区数   
  194.     }
  195.     return Capacity;
  196. }
  197. //初始化SD卡
  198. //返回值:0,正常.
  199. //                 其他,不正常.
  200. u8 SD_Initialize(void)
  201. {
  202.     u8 r1;      // 存放SD卡的返回值
  203.     u16 retry;  // 用来进行超时计数
  204.     u8 buf[4];  
  205.         u16 i;

  206.         SD_SPI_Init();                //初始化IO
  207.         SD_SPI_SpeedLow();        //设置到低速模式
  208.     //for(i=0;i<0xf00;i++);//纯延时,等待SD卡上电完成          
  209.         for(i=0;i<10;i++)SD_SPI_ReadWriteByte(0XFF);//发送最少74个脉冲
  210.         retry=20;
  211.         do
  212.         {
  213.                 r1=SD_SendCmd(CMD0,0,0x95);//进入IDLE状态
  214.         }while((r1!=0X01) && retry--);
  215.         SD_Type=0;//默认无卡
  216.         if(r1==0X01)
  217.         {
  218.                 if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
  219.                 {
  220.                         for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);        //Get trailing return value of R7 resp
  221.                         if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
  222.                         {
  223.                                 retry=0XFFFE;
  224.                                 do
  225.                                 {
  226.                                         SD_SendCmd(CMD55,0,0X01);        //发送CMD55
  227.                                         r1=SD_SendCmd(CMD41,0x40000000,0X01);//发送CMD41
  228.                                 }while(r1&&retry--);
  229.                                 if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始
  230.                                 {
  231.                                         for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
  232.                                         if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC;    //检查CCS
  233.                                         else SD_Type=SD_TYPE_V2;   
  234.                                 }
  235.                         }
  236.                 }else//SD V1.x/ MMC        V3
  237.                 {
  238.                         SD_SendCmd(CMD55,0,0X01);                //发送CMD55
  239.                         r1=SD_SendCmd(CMD41,0,0X01);        //发送CMD41
  240.                         if(r1<=1)
  241.                         {               
  242.                                 SD_Type=SD_TYPE_V1;
  243.                                 retry=0XFFFE;
  244.                                 do //等待退出IDLE模式
  245.                                 {
  246.                                         SD_SendCmd(CMD55,0,0X01);        //发送CMD55
  247.                                         r1=SD_SendCmd(CMD41,0,0X01);//发送CMD41
  248.                                 }while(r1&&retry--);
  249.                         }else
  250.                         {
  251.                                 SD_Type=SD_TYPE_MMC;//MMC V3
  252.                                 retry=0XFFFE;
  253.                                 do //等待退出IDLE模式
  254.                                 {                                                                                            
  255.                                         r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
  256.                                 }while(r1&&retry--);  
  257.                         }
  258.                         if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR;//错误的卡
  259.                 }
  260.         }
  261.         SD_DisSelect();//取消片选
  262.         SD_SPI_SpeedHigh();//高速
  263.         if(SD_Type)return 0;
  264.         else if(r1)return r1;           
  265.         return 0xaa;//其他错误
  266. }
  267. //读SD卡
  268. //buf:数据缓存区
  269. //sector:扇区
  270. //cnt:扇区数
  271. //返回值:0,ok;其他,失败.
  272. u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
  273. {
  274.         u8 r1;
  275.         if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址
  276.         if(cnt==1)
  277.         {
  278.                 r1=SD_SendCmd(CMD17,sector,0X01);//读命令
  279.                 if(r1==0)//指令发送成功
  280.                 {
  281.                         r1=SD_RecvData(buf,512);//接收512个字节          
  282.                 }
  283.         }else
  284.         {
  285.                 r1=SD_SendCmd(CMD18,sector,0X01);//连续读命令
  286.                 do
  287.                 {
  288.                         r1=SD_RecvData(buf,512);//接收512个字节         
  289.                         buf+=512;  
  290.                 }while(--cnt && r1==0);        
  291.                 SD_SendCmd(CMD12,0,0X01);        //发送停止命令
  292.         }   
  293.         SD_DisSelect();//取消片选
  294.         return r1;//
  295. }
  296. //写SD卡
  297. //buf:数据缓存区
  298. //sector:起始扇区
  299. //cnt:扇区数
  300. //返回值:0,ok;其他,失败.
  301. u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
  302. {
  303.         u8 r1;
  304.         if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//转换为字节地址
  305.         if(cnt==1)
  306.         {
  307.                 r1=SD_SendCmd(CMD24,sector,0X01);//读命令
  308.                 if(r1==0)//指令发送成功
  309.                 {
  310.                         r1=SD_SendBlock(buf,0xFE);//写512个字节          
  311.                 }
  312.         }else
  313.         {
  314.                 if(SD_Type!=SD_TYPE_MMC)
  315.                 {
  316.                         SD_SendCmd(CMD55,0,0X01);       
  317.                         SD_SendCmd(CMD23,cnt,0X01);//发送指令       
  318.                 }
  319.                 r1=SD_SendCmd(CMD25,sector,0X01);//连续读命令
  320.                 if(r1==0)
  321.                 {
  322.                         do
  323.                         {
  324.                                 r1=SD_SendBlock(buf,0xFC);//接收512个字节         
  325.                                 buf+=512;  
  326.                         }while(--cnt && r1==0);
  327.                         r1=SD_SendBlock(0,0xFD);//接收512个字节
  328.                 }
  329.         }   
  330.         SD_DisSelect();//取消片选
  331.         return r1;//
  332. }
复制代码

所有资料51hei提供下载:
bootloader.7z (325.73 KB, 下载次数: 76)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:130559 发表于 2019-4-9 16:17 | 显示全部楼层
找不到lib.h
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表