找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1635|回复: 2
打印 上一主题 下一主题
收起左侧

单片机读写SD卡数据为什么发生变异(左移一位)附源码+图

[复制链接]
跳转到指定楼层
楼主
    本人想对SD卡进行简单读写操作,就对一个扇区写入数据,然后读出来。可是却碰到一个奇怪的问题,本人以SPI方式读写SD卡,在复位,初始化等过程都正常,但在对一个扇区写入数据时,在写入扇区写命令并得到SD卡正确的0回应后,随后写入的数据都发生变化,所有数据都左移一位,相当于所有数据都乘2。读数据倒正常。为了验正本人的SPI读写函数正确,特地在SD卡读写前先进行对SPI存储芯片25AA010A的读写测试,证明可以对25AA010A芯片正常写入16字节数据,也能正常读出数据。但对SD卡却出现奇怪现象,请高手指点问题出在哪。


这是本人的原理图:

这是终端显示情况:


SPI存储芯片写入内存图:



SPI终端监视图:


















以下是程序:
  1. #include<reg52.h>
  2. sbit SD_SCL=P3^5;
  3. sbit SD_SI=P3^6;
  4. sbit SD_SO=P3^7;
  5. sbit SD_CS=P3^4;


  6. #define DELAY_TIME 100
  7. #define TryNum 127


  8. #define INIT_CMD0_ERROR 0x01
  9. #define INIT_CMD1_ERROR 0x02
  10. #define WRITE_BLOCK_ERROR 0x03
  11. #define READ_BLOCK_ERROR 0x04


  12. unsigned char waitnum;


  13. #define uint unsigned int
  14. #define uchar unsigned char


  15. void delay(int i)
  16. {int x;
  17. for(x=0;x<i;x++);
  18. }
  19. //==============================================================
  20. unsigned char bdata _dat;
  21. sbit _dat7=_dat^7;
  22. sbit _dat6=_dat^6;
  23. sbit _dat5=_dat^5;
  24. sbit _dat4=_dat^4;
  25. sbit _dat3=_dat^3;
  26. sbit _dat2=_dat^2;
  27. sbit _dat1=_dat^1;
  28. sbit _dat0=_dat^0;


  29. void SD_spi_write(unsigned char x)
  30. {_dat=x;
  31. SD_SI=_dat7;
  32. SD_SCL=0;
  33. delay(waitnum);
  34. SD_SCL=1;
  35. delay(waitnum);

  36. SD_SI=_dat6;
  37. SD_SCL=0;
  38. delay(waitnum);
  39. SD_SCL=1;
  40. delay(waitnum);


  41. SD_SI=_dat5;
  42. SD_SCL=0;
  43. delay(waitnum);
  44. SD_SCL=1;
  45. delay(waitnum);

  46. SD_SI=_dat4;
  47. SD_SCL=0;
  48. delay(waitnum);
  49. SD_SCL=1;
  50. delay(waitnum);

  51. SD_SI=_dat3;
  52. SD_SCL=0;
  53. delay(waitnum);
  54. SD_SCL=1;
  55. delay(waitnum);

  56. SD_SI=_dat2;
  57. SD_SCL=0;
  58. delay(waitnum);
  59. SD_SCL=1;
  60. delay(waitnum);

  61. SD_SI=_dat1;
  62. SD_SCL=0;
  63. delay(waitnum);
  64. SD_SCL=1;
  65. delay(waitnum);

  66. SD_SI=_dat0;
  67. SD_SCL=0;
  68. delay(waitnum);
  69. SD_SCL=1;
  70. delay(waitnum);
  71. }
  72. unsigned char SD_spi_read()
  73. {SD_SO=1;
  74. SD_SCL=1;
  75. delay(waitnum);
  76. SD_SCL=0;
  77. delay(waitnum);
  78. _dat7=SD_SO;

  79. SD_SCL=1;
  80. delay(waitnum);
  81. SD_SCL=0;
  82. delay(waitnum);
  83. _dat6=SD_SO;

  84. SD_SCL=1;
  85. delay(waitnum);
  86. SD_SCL=0;
  87. delay(waitnum);
  88. _dat5=SD_SO;
  89. SD_SCL=1;
  90. delay(waitnum);
  91. SD_SCL=0;
  92. delay(waitnum);
  93. _dat4=SD_SO;

  94. SD_SCL=1;
  95. delay(waitnum);
  96. SD_SCL=0;
  97. delay(waitnum);
  98. _dat3=SD_SO;
  99. SD_SCL=1;
  100. delay(waitnum);
  101. SD_SCL=0;
  102. delay(waitnum);
  103. _dat2=SD_SO;

  104. SD_SCL=1;
  105. delay(waitnum);
  106. SD_SCL=0;
  107. delay(waitnum);
  108. _dat1=SD_SO;

  109. SD_SCL=1;
  110. delay(waitnum);
  111. SD_SCL=0;
  112. delay(waitnum);
  113. _dat0=SD_SO;


  114. return _dat;
  115. }


  116. //##########################################################
  117. char Rec_C;
  118. void SerInit()
  119. {SCON=0x50;
  120.   TMOD=0x22;
  121.   TH1=0xfd;
  122.   TL1=0xfd;
  123.   EA=1;
  124.   ES=1;
  125.   ET1=0;
  126.   TR1=1;
  127. }
  128. void Serp()interrupt 4
  129. {if(RI==1)
  130.    {Rec_C=SBUF;
  131.     RI=0;
  132.     }
  133. }
  134. void SendC(uchar ci)
  135. {SBUF=ci;
  136. while(TI==0);
  137. TI==0;
  138. }
  139. void Sendstr(uchar *cp)
  140. {int i=0;
  141. while(cp[ i]!=0)[ i]
  142.   {delay(50);
  143.    SendC(cp[ i]);[ i]
  144.    delay(50);
  145.    i++;
  146.    }
  147. }
  148. //##########################################################
  149. void SPI_Write_Addstr(int add,int num,char *cp)
  150. {int i;
  151. SD_CS=0;
  152. SD_spi_write(6);
  153. SD_CS=1;delay(8);
  154. SD_CS=0;
  155. SD_spi_write(2);
  156. SD_spi_write(add);
  157. for(i=0;i<num;i++)
  158.    {SD_spi_write(cp[ i]);[ i]
  159.     SendC(cp[ i]);[ i]
  160.         }
  161. SD_CS=1;
  162. }
  163. //-----------------------------------------------------------
  164. void SPI_Read_Addstr(int add,int len)
  165. {int i;
  166. SD_CS=0;
  167. SD_spi_write(3);
  168. SD_spi_write(add);
  169. for(i=0;i<len;i++)
  170.     SendC(SD_spi_read());
  171. SD_CS=1;
  172. }
  173. //###########################################################
  174. unsigned char SD_Write_Cmd(unsigned char *pcmd)
  175. {unsigned char temp,time=0;
  176. SD_CS=1;
  177. SD_spi_write(0xff);
  178. SD_CS=0;
  179. SD_spi_write(pcmd[0]);
  180. SD_spi_write(pcmd[1]);
  181. SD_spi_write(pcmd[2]);
  182. SD_spi_write(pcmd[3]);
  183. SD_spi_write(pcmd[4]);
  184. SD_spi_write(pcmd[5]);
  185. do{temp=SD_spi_read();
  186.     time++;
  187.         }while((temp==0xff)&&(time<TryNum));
  188. return temp;
  189. }
  190. //================================================================
  191. unsigned char SD_Reset()
  192. {unsigned char i,time,temp;
  193. unsigned char pcmd[]={0x40,0,0,0,0,0x95};
  194. SD_CS=1;
  195. for(i=0;i<0x0f;i++)
  196.   {SD_spi_write(0xff);
  197.    }
  198. SD_CS=0;
  199. time=0;
  200. do{temp=SD_Write_Cmd(pcmd);
  201.     time++;
  202.         if(time==TryNum){SD_CS=1;return(INIT_CMD0_ERROR);}
  203.     }while(temp!=0x01);
  204.   SD_CS=1;
  205.   SD_spi_write(0xff);
  206.   return 0;
  207. }
  208. //==================================================================
  209. unsigned char SD_Init()
  210. {unsigned char time,temp;
  211. unsigned char pcmd[]={0x41,0,0,0x02,0,0xff};
  212. SD_CS=0;
  213. time=0;
  214. do{temp=SD_Write_Cmd(pcmd);
  215.     time++;
  216.         if(time==TryNum){SD_CS=1;return(INIT_CMD1_ERROR);}
  217.         }while(temp!=0);
  218. SD_CS=1;
  219. SD_spi_write(0xff);
  220. return 0;
  221. }
  222. //==================================================================
  223. unsigned char SD_Write_Sector(unsigned long addr)
  224. {unsigned char temp,time;
  225. unsigned int i;
  226. unsigned char pcmd[]={0x58,0,0,0,0,0xff};
  227. waitnum=1;
  228. addr<<=9;
  229. pcmd[1]=((addr&0xff000000)>>24);
  230. pcmd[2]=((addr&0x00ff0000)>>16);
  231. pcmd[3]=((addr&0x0000ff00)>>8);
  232. SD_CS=0;
  233. time=0;
  234. do{temp=SD_Write_Cmd(pcmd);
  235.     time++;
  236.         if(time==TryNum){SD_CS=1;return temp;}
  237.         }while(temp!=0);//偿试写入命令并获取反应不超过127次
  238. for(i=0;i<100;i++)SD_spi_read();
  239. SD_spi_write(0xff);//此句本来应写入标志字0xfe;因写入数据会左移一位,所以写入0xff,左移1位后正好是0xfe;勉强完成写入扇区操作。
  240. for(i=0;i<512;i++)//写入512个#
  241.    {SD_spi_write(0x23);
  242.     if(i%32==0)Sendstr("\r");
  243.         SendC(0x23);
  244.         }
  245. SD_spi_write(0xff);
  246. SD_spi_write(0xff);
  247. temp=SD_spi_read();
  248. if((temp&0x1f)!=0x05){SD_CS=1;return WRITE_BLOCK_ERROR;}
  249. while(SD_spi_read()!=0xff);
  250. SD_CS=1;
  251. SD_spi_write(0xff);
  252. return 0;
  253. }
  254. //===================================================================
  255. unsigned char SD_Read_Sector(unsigned long addr)
  256. {unsigned char temp,time;
  257. unsigned int j;
  258. unsigned char pcmd[]={0x51,0,0,0,0,0xff};
  259. addr<<=9;
  260. pcmd[1]=((addr&0xff000000)>>24);
  261. pcmd[2]=((addr&0x00ff0000)>>16);
  262. pcmd[3]=((addr&0x0000ff00)>>8);
  263. SD_CS=0;
  264. time=0;
  265. do{temp=SD_Write_Cmd(pcmd);
  266.     time++;
  267.         if(time==TryNum){return READ_BLOCK_ERROR;}
  268.         }while(temp!=0);//偿试写入命令并获取反应不超过127次
  269. while(SD_spi_read()!=0xfe);//读到标志字0xfe为止
  270. for(j=0;j<512;j++)//读出512个字节
  271.    {temp=SD_spi_read();
  272.     if(j%32==0)Sendstr("\r");
  273.         SendC(temp);
  274.         }
  275. SD_spi_read();
  276. SD_spi_read();
  277. SD_CS=1;
  278. SD_spi_write(0xff);
  279. return 0;
  280. }
  281. //################################################################
  282. main()
  283. {uchar i,j;
  284. SerInit();
  285. Sendstr("SPI RW Test\r");
  286. SPI_Write_Addstr(0x40,16,"123456789abcdef");
  287. delay(1000);
  288. SendC('\r');
  289. SPI_Read_Addstr(0x40,16);
  290. Sendstr("\rSD RW Test...\r");
  291. waitnum=100;
  292. i=SD_Reset();
  293. Sendstr("\rreset=");
  294. SendC(i+0x30);
  295. i=SD_Init();
  296. Sendstr("\rinit=");
  297. SendC(i+0x30);
  298. waitnum=2;
  299. i=SD_Write_Sector(0x5);
  300. Sendstr("\rwrite sec=");
  301. SendC(i+0x30);
  302. i=SD_Read_Sector(0x6);
  303. Sendstr("\rread sec=");
  304. SendC(i+0x30);
  305. while(1);

  306. }
复制代码



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:328014 发表于 2018-12-14 04:06 | 只看该作者
所有数据都左移一位这个的确很怪,有没有换过sd卡?看样子应该还是程序的问题
回复

使用道具 举报

板凳
ID:404797 发表于 2018-12-14 06:55 | 只看该作者
是在proteus仿真的时候出现的,用真实SD卡只有一次复位成功,初始化没成功,其他就连复位都不成功,因实物SD卡读写没办法监测,所以有没有左移一位不知道。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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