Micro SD卡(TF卡)spi

转自:http://blog.csdn.net/ming1006/article/details/7283689


上一篇文章已经介绍了Micro SD卡SPI模式的实现方法,这里给出自己写的基于nios ii的Micro SD卡读写程序(IO口模拟spi)。

    硬件设计就不多说了,主要是添加4的1为PIO口来模拟SPI的CS、SCLK、MISO和MOSI。

    以下是代码:

    头文件SD_spi_solution.h

  1. #ifndef SD_SPI_SOLUTION_H_  
  2. #define SD_SPI_SOLUTION_H_  
  3.   
  4. #include<system.h>  
  5. #include<alt_types.h>  
  6. #include<altera_avalon_pio_regs.h>  
  7.   
  8. #define CMD0    0   /* GO_IDLE_STATE */  
  9. #define CMD55   55  /* APP_CMD */  
  10. #define ACMD41  41  /* SEND_OP_COND (ACMD) */  
  11. #define CMD1    1   /* SEND_OP_COND */  
  12. #define CMD17   17  /* READ_SINGLE_BLOCK */  
  13. #define CMD8    8   /* SEND_IF_COND */  
  14. #define CMD18   18  /* READ_MULTIPLE_BLOCK */  
  15. #define CMD12   12  /* STOP_TRANSMISSION */  
  16. #define CMD24   24  /* WRITE_BLOCK */  
  17. #define CMD25   25  /* WRITE_MULTIPLE_BLOCK */  
  18. #define CMD13   13  /* SEND_STATUS */  
  19. #define CMD9    9   /* SEND_CSD */  
  20. #define CMD10   10  /* SEND_CID */  
  21.   
  22. #define CSD     9  
  23. #define CID     10  
  24.   
  25. //delay 1us(actually not,it maybe is several us,I don't test it)  
  26. void usleep(alt_u8 i);  
  27.   
  28. //set CS low  
  29. void CS_Enable();  
  30.   
  31. //set CS high and send 8 clocks  
  32. void CS_Disable();  
  33.   
  34. //write a byte  
  35. void SDWriteByte(alt_u8 data);  
  36.   
  37. //read a byte  
  38. alt_u8 SDReadByte();  
  39.   
  40. //send a command and send back the response  
  41. alt_u8  SDSendCmd(alt_u8 cmd,alt_u32 arg,alt_u8 crc);  
  42.   
  43. //reset SD card  
  44. alt_u8 SDReset();  
  45.   
  46. //initial SD card  
  47. alt_u8 SDInit();  
  48.   
  49. //read a single sector  
  50. alt_u8 SDReadSector(alt_u32 addr,alt_u8 * buffer);  
  51.   
  52. //read multiple sectors  
  53. alt_u8 SDReadMultiSector(alt_u32 addr,alt_u8 sector_num,alt_u8 * buffer);  
  54.   
  55. //write a single sector  
  56. alt_u8 SDWriteSector(alt_u32 addr,alt_u8 * buffer);  
  57.   
  58. //write multiple sectors  
  59. alt_u8 SDWriteMultiSector(alt_u32 addr,alt_u8 sector_num,alt_u8 * buffer);  
  60.   
  61. //get CID or CSD  
  62. alt_u8 SDGetCIDCSD(alt_u8 cid_csd,alt_u8 * buffer);  
  63.   
  64. //spi speed(0-255),0 is fastest  
  65. alt_u8 spi_speed;  
  66.   
  67. #endif /* SD_SPI_SOLUTION_H_ */  
    源文件SD_spi_Solution.c

  1. #include"SD_spi_Solution.h"  
  2.   
  3. alt_u8 spi_speed = 10;//the spi speed(0-255),0 is fastest  
  4.   
  5. //delay 1us(actually not,it maybe is several us,I don't test it)  
  6. void usleep(alt_u8 i)  
  7. {  
  8.     while(i --);  
  9. }  
  10.   
  11. //set CS low  
  12. void CS_Enable()  
  13. {  
  14.     //set CS low  
  15.     IOWR_ALTERA_AVALON_PIO_DATA(CS_BASE, 0x00);  
  16. }  
  17.   
  18. //set CS high and send 8 clocks  
  19. void CS_Disable()  
  20. {  
  21.     //set CS high  
  22.     IOWR_ALTERA_AVALON_PIO_DATA(CS_BASE, 0x01);  
  23.     //send 8 clocks  
  24.     SDWriteByte(0xff);  
  25. }  
  26.   
  27. //write a byte  
  28. void SDWriteByte(alt_u8 data)  
  29. {  
  30.     alt_u8 i;  
  31.   
  32.     //write 8 bits(MSB)  
  33.     for(i = 0;i < 8;i ++)  
  34.     {  
  35.         IOWR_ALTERA_AVALON_PIO_DATA(SCLK_BASE, 0x00);  
  36.         usleep(spi_speed);  
  37.         if(data & 0x80) IOWR_ALTERA_AVALON_PIO_DATA(DI_BASE, 0x01);  
  38.         else IOWR_ALTERA_AVALON_PIO_DATA(DI_BASE, 0x00);  
  39.         data <<= 1;  
  40.         IOWR_ALTERA_AVALON_PIO_DATA(SCLK_BASE, 0x01);  
  41.         usleep(spi_speed);  
  42.     }  
  43.   
  44.     //when DI is free,it should be set high  
  45.     IOWR_ALTERA_AVALON_PIO_DATA(DI_BASE, 0x01);  
  46. }  
  47.   
  48. //read a byte  
  49. alt_u8 SDReadByte()  
  50. {  
  51.     alt_u8 data = 0x00,i;  
  52.   
  53.     //read 8 bit(MSB)  
  54.     for(i = 0;i < 8;i ++)  
  55.     {  
  56.         IOWR_ALTERA_AVALON_PIO_DATA(SCLK_BASE, 0x00);  
  57.         usleep(spi_speed);  
  58.         IOWR_ALTERA_AVALON_PIO_DATA(SCLK_BASE, 0x01);  
  59.         data <<= 1;  
  60.         if(IORD_ALTERA_AVALON_PIO_DATA(DO_BASE)) data |= 0x01;  
  61.         usleep(spi_speed);  
  62.     }  
  63.   
  64.     return data;  
  65. }  
  66.   
  67. //send a command and send back the response  
  68. alt_u8  SDSendCmd(alt_u8 cmd,alt_u32 arg,alt_u8 crc)  
  69. {  
  70.     alt_u8 r1,time = 0;  
  71.   
  72.     //send the command,arguments and CRC  
  73.     SDWriteByte((cmd & 0x3f) | 0x40);  
  74.     SDWriteByte(arg >> 24);  
  75.     SDWriteByte(arg >> 16);  
  76.     SDWriteByte(arg >> 8);  
  77.     SDWriteByte(arg);  
  78.     SDWriteByte(crc);  
  79.   
  80.     //read the respond until responds is not '0xff' or timeout  
  81.     do{  
  82.         r1 = SDReadByte();  
  83.         time ++;  
  84.         //if time out,return  
  85.         if(time > 254) break;  
  86.     }while(r1 == 0xff);  
  87.   
  88.     return r1;  
  89. }  
  90.   
  91. //reset SD card  
  92. alt_u8 SDReset()  
  93. {  
  94.     alt_u8 i,r1,time = 0;  
  95.   
  96.     //set CS high  
  97.     CS_Disable();  
  98.   
  99.     //send 128 clocks  
  100.     for(i = 0;i < 16;i ++)  
  101.     {  
  102.         SDWriteByte(0xff);  
  103.     }  
  104.   
  105.     //set CS low  
  106.     CS_Enable();  
  107.   
  108.     //send CMD0 till the response is 0x01  
  109.     do{  
  110.         r1 = SDSendCmd(CMD0,0,0x95);  
  111.         time ++;  
  112.         //if time out,set CS high and return r1  
  113.         if(time > 254)  
  114.         {  
  115.             //set CS high and send 8 clocks  
  116.             CS_Disable();  
  117.             return r1;  
  118.         }  
  119.     }while(r1 != 0x01);  
  120.   
  121.     //set CS high and send 8 clocks  
  122.     CS_Disable();  
  123.   
  124.     return 0;  
  125. }  
  126.   
  127. //initial SD card(send CMD55+ACMD41 or CMD1)  
  128. alt_u8 SDInit()  
  129. {  
  130.     alt_u8 r1,time = 0;  
  131.   
  132.     //set CS low  
  133.     CS_Enable();  
  134.   
  135.     //check interface operating condition  
  136.     r1 = SDSendCmd(CMD8,0x000001aa,0x87);  
  137.     //if support Ver1.x,but do not support Ver2.0,set CS high and return r1  
  138.     if(r1 == 0x05)  
  139.     {  
  140.         //set CS high and send 8 clocks  
  141.         CS_Disable();  
  142.         return r1;  
  143.     }  
  144.     //read the other 4 bytes of response(the response of CMD8 is 5 bytes)  
  145.     r1=SDReadByte();  
  146.     r1=SDReadByte();  
  147.     r1=SDReadByte();  
  148.     r1=SDReadByte();  
  149.   
  150.     do{  
  151.         //send CMD55+ACMD41 to initial SD card  
  152.         do{  
  153.             r1 = SDSendCmd(CMD55,0,0xff);  
  154.             time ++;  
  155.             //if time out,set CS high and return r1  
  156.             if(time > 254)  
  157.             {  
  158.                 //set CS high and send 8 clocks  
  159.                 CS_Disable();  
  160.                 return r1;  
  161.             }  
  162.         }while(r1 != 0x01);  
  163.   
  164.         r1 = SDSendCmd(ACMD41,0x40000000,0xff);  
  165.   
  166.         //send CMD1 to initial SD card  
  167.         //r1 = SDSendCmd(CMD1,0x00ffc000,0xff);  
  168.         time ++;  
  169.   
  170.         //if time out,set CS high and return r1  
  171.         if(time > 254)  
  172.         {  
  173.             //set CS high and send 8 clocks  
  174.             CS_Disable();  
  175.             return r1;  
  176.         }  
  177.     }while(r1 != 0x00);  
  178.   
  179.     //set CS high and send 8 clocks  
  180.     CS_Disable();  
  181.   
  182.     return 0;  
  183. }  
  184.   
  185. //read a single sector  
  186. alt_u8 SDReadSector(alt_u32 addr,alt_u8 * buffer)  
  187. {  
  188.     alt_u8 r1;  
  189.     alt_u16 i,time = 0;  
  190.   
  191.     //set CS low  
  192.     CS_Enable();  
  193.   
  194.     //send CMD17 for single block read  
  195.     r1 = SDSendCmd(CMD17,addr << 9,0x55);  
  196.     //if CMD17 fail,return  
  197.     if(r1 != 0x00)  
  198.     {  
  199.         //set CS high and send 8 clocks  
  200.         CS_Disable();  
  201.         return r1;  
  202.     }  
  203.   
  204.     //continually read till get the start byte 0xfe  
  205.     do{  
  206.         r1 = SDReadByte();  
  207.         time ++;  
  208.         //if time out,set CS high and return r1  
  209.         if(time > 30000)  
  210.         {  
  211.             //set CS high and send 8 clocks  
  212.             CS_Disable();  
  213.             return r1;  
  214.         }  
  215.     }while(r1 != 0xfe);  
  216.   
  217.     //read 512 Bits of data  
  218.     for(i = 0;i < 512;i ++)  
  219.     {  
  220.         buffer[i] = SDReadByte();  
  221.     }  
  222.   
  223.     //read two bits of CRC  
  224.     SDReadByte();  
  225.     SDReadByte();  
  226.   
  227.     //set CS high and send 8 clocks  
  228.     CS_Disable();  
  229.   
  230.     return 0;  
  231. }  
  232.   
  233. //read multiple sectors  
  234. alt_u8 SDReadMultiSector(alt_u32 addr,alt_u8 sector_num,alt_u8 * buffer)  
  235. {  
  236.     alt_u16 i,time = 0;  
  237.     alt_u8 r1;  
  238.   
  239.     //set CS low  
  240.     CS_Enable();  
  241.   
  242.     //send CMD18 for multiple blocks read  
  243.     r1 = SDSendCmd(CMD18,addr << 9,0xff);  
  244.     //if CMD18 fail,return  
  245.     if(r1 != 0x00)  
  246.     {  
  247.         //set CS high and send 8 clocks  
  248.         CS_Disable();  
  249.         return r1;  
  250.     }  
  251.   
  252.     //read sector_num sector  
  253.     do{  
  254.         //continually read till get start byte  
  255.         do{  
  256.             r1 = SDReadByte();  
  257.             time ++;  
  258.             //if time out,set CS high and return r1  
  259.             if(time > 30000 || ((r1 & 0xf0) == 0x00 && (r1 & 0x0f)))  
  260.             {  
  261.                 //set CS high and send 8 clocks  
  262.                 CS_Disable();  
  263.                 return r1;  
  264.             }  
  265.         }while(r1 != 0xfe);  
  266.         time = 0;  
  267.   
  268.         //read 512 Bits of data  
  269.         for(i = 0;i < 512;i ++)  
  270.         {  
  271.             *buffer ++ = SDReadByte();  
  272.         }  
  273.   
  274.         //read two bits of CRC  
  275.         SDReadByte();  
  276.         SDReadByte();  
  277.     }while( -- sector_num);  
  278.     time = 0;  
  279.   
  280.     //stop multiple reading  
  281.     r1 = SDSendCmd(CMD12,0,0xff);  
  282.   
  283.     //set CS high and send 8 clocks  
  284.     CS_Disable();  
  285.   
  286.     return 0;  
  287. }  
  288.   
  289. //write a single sector  
  290. alt_u8 SDWriteSector(alt_u32 addr,alt_u8 * buffer)  
  291. {  
  292.     alt_u16 i,time = 0;  
  293.     alt_u8 r1;  
  294.   
  295.     //set CS low  
  296.     CS_Enable();  
  297.   
  298.     do{  
  299.         do{  
  300.             //send CMD24 for single block write  
  301.             r1 = SDSendCmd(CMD24,addr << 9,0xff);  
  302.             time ++;  
  303.             //if time out,set CS high and return r1  
  304.             if(time > 254)  
  305.             {  
  306.                 //set CS high and send 8 clocks  
  307.                 CS_Disable();  
  308.                 return r1;  
  309.             }  
  310.         }while(r1 != 0x00);  
  311.         time = 0;  
  312.   
  313.         //send some dummy clocks  
  314.         for(i = 0;i < 5;i ++)  
  315.         {  
  316.             SDWriteByte(0xff);  
  317.         }  
  318.   
  319.         //write start byte  
  320.         SDWriteByte(0xfe);  
  321.   
  322.         //write 512 bytes of data  
  323.         for(i = 0;i < 512;i ++)  
  324.         {  
  325.             SDWriteByte(buffer[i]);  
  326.         }  
  327.   
  328.         //write 2 bytes of CRC  
  329.         SDWriteByte(0xff);  
  330.         SDWriteByte(0xff);  
  331.   
  332.         //read response  
  333.         r1 = SDReadByte();  
  334.         time ++;  
  335.         //if time out,set CS high and return r1  
  336.         if(time > 254)  
  337.         {  
  338.             //set CS high and send 8 clocks  
  339.             CS_Disable();  
  340.             return r1;  
  341.         }  
  342.     }while((r1 & 0x1f)!= 0x05);  
  343.     time = 0;  
  344.   
  345.     //check busy  
  346.     do{  
  347.         r1 = SDReadByte();  
  348.         time ++;  
  349.         //if time out,set CS high and return r1  
  350.         if(time > 60000)  
  351.         {  
  352.             //set CS high and send 8 clocks  
  353.             CS_Disable();  
  354.             return r1;  
  355.         }  
  356.     }while(r1 != 0xff);  
  357.   
  358.     //set CS high and send 8 clocks  
  359.     CS_Disable();  
  360.   
  361.     return 0;  
  362. }  
  363.   
  364. //write several blocks  
  365. alt_u8 SDWriteMultiSector(alt_u32 addr,alt_u8 sector_num,alt_u8 * buffer)  
  366. {  
  367.     alt_u16 i,time = 0;  
  368.     alt_u8 r1;  
  369.   
  370.     //set CS low  
  371.     CS_Enable();  
  372.   
  373.     //send CMD25 for multiple block read  
  374.     r1 = SDSendCmd(CMD25,addr << 9,0xff);  
  375.     //if CMD25 fail,return  
  376.     if(r1 != 0x00)  
  377.     {  
  378.         //set CS high and send 8 clocks  
  379.         CS_Disable();  
  380.         return r1;  
  381.     }  
  382.   
  383.     do{  
  384.         do{  
  385.             //send several dummy clocks  
  386.             for(i = 0;i < 5;i ++)  
  387.             {  
  388.                 SDWriteByte(0xff);  
  389.             }  
  390.   
  391.             //write start byte  
  392.             SDWriteByte(0xfc);  
  393.   
  394.             //write 512 byte of data  
  395.             for(i = 0;i < 512;i ++)  
  396.             {  
  397.                 SDWriteByte(*buffer ++);  
  398.             }  
  399.   
  400.             //write 2 byte of CRC  
  401.             SDWriteByte(0xff);  
  402.             SDWriteByte(0xff);  
  403.   
  404.             //read response  
  405.             r1 = SDReadByte();  
  406.             time ++;  
  407.             //if time out,set CS high and return r1  
  408.             if(time > 254)  
  409.             {  
  410.                 //set CS high and send 8 clocks  
  411.                 CS_Disable();  
  412.                 return r1;  
  413.             }  
  414.         }while((r1 & 0x1f)!= 0x05);  
  415.         time = 0;  
  416.   
  417.         //check busy  
  418.         do{  
  419.             r1 = SDReadByte();printf("n%d",r1);  
  420.             time ++;  
  421.             //if time out,set CS high and return r1  
  422.             if(time > 30000)  
  423.             {  
  424.                 //set CS high and send 8 clocks  
  425.                 CS_Disable();  
  426.                 return r1;  
  427.             }  
  428.         }while(r1 != 0xff);  
  429.         time = 0;  
  430.     }while(-- sector_num);  
  431.   
  432.     //send stop byte  
  433.     SDWriteByte(0xfd);  
  434.   
  435.     //check busy  
  436.     do{  
  437.         r1 = SDReadByte();  
  438.         time ++;  
  439.         //if time out,set CS high and return r1  
  440.         if(time > 30000)  
  441.         {  
  442.             //set CS high and send 8 clocks  
  443.             CS_Disable();  
  444.             return r1;  
  445.         }  
  446.     }while(r1 != 0xff);  
  447.   
  448.     //set CS high and send 8 clocks  
  449.     CS_Disable();  
  450.   
  451.     return 0;  
  452. }  
  453.   
  454. //get CID or CSD  
  455. alt_u8 SDGetCIDCSD(alt_u8 cid_csd,alt_u8 * buffer)  
  456. {  
  457.     alt_u8 r1;  
  458.     alt_u16 i,time = 0;  
  459.   
  460.     //set CS low  
  461.     CS_Enable();  
  462.   
  463.     //send CMD10 for CID read or CMD9 for CSD  
  464.     do{  
  465.         if(cid_csd == CID)  
  466.             r1 = SDSendCmd(CMD10,0,0xff);  
  467.         else  
  468.             r1 = SDSendCmd(CMD9,0,0xff);  
  469.         time ++;  
  470.         //if time out,set CS high and return r1  
  471.         if(time > 254)  
  472.         {  
  473.             //set CS high and send 8 clocks  
  474.             CS_Disable();  
  475.             return r1;  
  476.         }  
  477.     }while(r1 != 0x00);  
  478.     time = 0;  
  479.   
  480.     //continually read till get 0xfe  
  481.     do{  
  482.         r1 = SDReadByte();  
  483.         time ++;  
  484.         //if time out,set CS high and return r1  
  485.         if(time > 30000)  
  486.         {  
  487.             //set CS high and send 8 clocks  
  488.             CS_Disable();  
  489.             return r1;  
  490.         }  
  491.     }while(r1 != 0xfe);  
  492.   
  493.     //read 512 Bits of data  
  494.     for(i = 0;i < 16;i ++)  
  495.     {  
  496.         *buffer ++ = SDReadByte();  
  497.     }  
  498.   
  499.     //read two bits of CRC  
  500.     SDReadByte();  
  501.     SDReadByte();  
  502.   
  503.     //set CS high and send 8 clocks  
  504.     CS_Disable();  
  505.   
  506.     return 0;  
  507. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值