在线情况
楼主
  • 头像
  • 级别
    • 积分14
    • 经验1391
    • 文章11
    • 注册2007-01-04
    430读写SD卡
    用了Ti读写SD 卡例子,但是URCTL总是为0X20,而且sd发出都是高电平,没有其他响应,不知什么原因,谢谢大家了

     看DC版主曾经发表过过一个读写SD卡的程序,不知有没有做过,
            发出复位SD卡命令后,收到总为高电平,响应不正确,解决不了啊
    微控网感谢您的参与
    在线情况
    2
    • 头像
    • 级别
      • 积分14
      • 经验1391
      • 文章11
      • 注册2007-01-04
      void initSPI (void)
      {
        UCTL0 = SWRST;                            // 8-bit SPI Master **SWRST**
        UTCTL0 = CKPH | SSEL1 | SSEL0 | STC;      // SMCLK, 3-pin mode, clock idle low, data valid on rising edge, UCLK delayed
        UBR00 = 0x20;                             // 0x02: UCLK/2 (4 MHz), works also with 3 and 4
        UBR10 = 0x00;                             // -"-
        UMCTL0 = 0x00;                            // no modulation
        UCTL0 = CHAR | SYNC | MM | SWRST;         // 8-bit SPI Master **SWRST**
        UCTL0 &= ~SWRST;                          // clear SWRST
        ME1 |= USPIE0;                            // Enable USART1 SPI mode
        while (!(IFG1 & UTXIFG0));                // USART1 TX buffer ready (empty)?
      }


      // Initialize MMC card
      char initMMC (void)
      {

        //raise SS and MOSI for 80 clock cycles
        //SendByte(0xff) 10 times with SS high
        //RAISE SS
        int i;

        // Port 3 Function           Dir       On/Off
        //         3.0-mmcCD         Out       0 - card inserted
        //         3.1-Dout          Out       0 - off    1 - On -> init in SPI_Init
        //         3.2-Din           Inp       0 - off    1 - On -> init in SPI_Init
        //         3.3-Clk           Out       -                 -> init in SPI_Init
        //         2.6-mmcCS         Out       0 - Active 1 - none Active
       
        P2DIR |= BIT6;
        P3SEL |= 0x0E;
        P3SEL &= ~0x11;
        P3OUT |= 0x10;
        P3DIR |= 0x0A;

        initSPI();
        //initialization sequence on PowerUp
        CS_LOW();
        for(i=0;i<10;i++)
          spiSendByte(0xff);
        CS_HIGH();
        for(i=0;i<=9;i++)
          spiSendByte(0xff);

        return (mmc_GoIdle());
      }


      char mmc_GoIdle(void)
      {
        char response=0x01;
        CS_LOW();

        //Send Command 0 to put MMC in SPI mode
        mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);
        //Now wait for READY RESPONSE
        if(mmcGetResponse()!=0x00)//应该是收到响应R1,也就是0,可是我总是收到是高电平,也不知是不是太快了,没收到,示波器看了,没有低电平的产生
          return MMC_INIT_ERROR;

        while(response==0x00)
        {
          CS_HIGH();
          spiSendByte(0xff);
          CS_LOW();
          mmcSendCmd(MMC_SEND_OP_COND,0x00,0xff);
          response=mmcGetResponse();
        }
        CS_HIGH();
        spiSendByte(0xff);
        return (MMC_SUCCESS);
      }

      // mmc Get Responce
      char mmcGetResponse(void)
      {
        //Response comes 1-8bytes after command
        //the first bit will be a 0
        //followed by an error code
        //data will be 0xff until response
        int i=0;

        char response;

        while(i<=64)
        {
          response=spiSendByte(0xff);
          if(response==0x00)break;
          if(response==0x01)break;
          i++;
        }
        return response;
      }
      微控网感谢您的参与
      在线情况
      3
      • 头像
      • 级别
      • 门派
      • 职务总版主
      • 声望+9
      • 财富5
      • 积分3065
      • 经验390701
      • 文章6744
      • 注册2006-03-07
      这位兄弟,真不好意思。上次发表过的是转载国外的一位工程师的程序。SD卡操作我也没做过。
      [COLOR=#0000ff]欢迎发贴分享设计心得、开源DIY...[/COLOR]
      在线情况
      4
      • 头像
      • 级别
        • 积分14
        • 经验1391
        • 文章11
        • 注册2007-01-04
        谢谢版主
        我用示波器看了,结果并不是没有响应,有响应R1,只是在执行这个函数mmcGetResponse()之前,响应已经给过了。也就是说,在命令和响应有个时间间隔N(CR),这个间隔很短,以至于还没等到我执行接受响应语句,响应就已经发完了,真FT。
        可是我还是不明白,我的MCLK为8M,而我的SPI的CLOCK仅为250K,按SD卡的技术文档命令和响应时间间隔N(CR)为0~8个时钟个数,单位为8个Clock周期。我认为单位为8个SPI的Clock周期,也就是0~64个SPI的Clock周期。这样算来,执行语句的速度怎么也应该能收到响应吧!
        困惑中,DC版主提供点高见
        har mmc_GoIdle(void)
        {
          char response=0x01;
          CS_LOW();

          //Send Command 0 to put MMC in SPI mode
          mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);
          //Now wait for READY RESPONSE
          if(mmcGetResponse()!=0x00)
            return MMC_INIT_ERROR;
        微控网感谢您的参与
        在线情况
        5
        • 头像
        • 级别
        • 门派
        • 职务论坛版主
        • 积分55
        • 经验17687
        • 文章198
        • 注册2006-03-07
          //         3.0-mmcCD         Out       0 - card inserted
          //         3.1-Dout          Out       0 - off    1 - On -> init in SPI_Init
          //         3.2-Din           Inp       0 - off    1 - On -> init in SPI_Init
          //         3.3-Clk           Out       -                 -> init in SPI_Init
          //         2.6-mmcCS         Out       0 - Active 1 - none Active
        上面是你的MCU IO配置吗?
        P3.1 MOSI(SIMO) :主出从入
        P3.2 MISO(SOMI) :主入从出

        你现在的接法有错误!
            你把SD/MMC 卡做为SPI主机了。实际上MPS430才是主机。
        这样一来你不是把430的SPI OUT,与SD/MMC卡的OUT 相连了。
        你把SPI与SD/MMC卡的DIN,DOUT交换一下口,最好是串一个100~330的电阻保护。
        试试看!

        仔细看看下图的SD卡接口
        MCU SIMO ----->DI
        MCU SOMI ----->DO

        [imga]../../upload/2006/05/01/152955.gif[/imga]
        微控网感谢您的参与
        在线情况
        6
        • 头像
        • 级别
          • 积分14
          • 经验1391
          • 文章11
          • 注册2007-01-04
          首先谢谢debug,感谢您能花时间回答我的问题

          您看的太仔细了。这是ti提供的接法,确实按它的接法是没法收到响应的。我疏忽了,在帖上去之前没有更改过来。现在问题就是在430执行接受响应的语句之前,响应已经发生。我想应该是spi接受有问题。这个问题在软件或者是在硬件上如何解决?

          我用示波器看SD卡的输出,其输出一直为高(111……),在执行完mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);后产生数据为(……11)0 1000 0000(11……)但是我读RXBUF0里的值为0xFF,而0x01这个我想要的值没有收到!

          我想在软件上解决的方法就是读控制SD卡的CLOCK,在430没有执行接受响应的语句之前,430不提供时钟信号,这样SD卡应该不会提供响应(个人想法)。但是430的spi模块似乎是只要MOSI和 MISO有数据传输就提供CLOCK!所以我困在这里。
          另外,就是为什么在CSPY中执行一个函数,GO比单步运行的时间快很多,是不是执行GO频率和单步频率不一样?
          [ 这个贴子最后由george500在2007-1-16 14:47:50编辑过 ]
          在线情况
          7
          • 头像
          • 级别
          • 门派
          • 职务论坛版主
          • 积分55
          • 经验17687
          • 文章198
          • 注册2006-03-07
          SPI 接口的通信方式是:
          写数据:主机MOSI向从机发SCK和MOSI数据。不理会MISO.
          读数据:主机向从机发SCK,并读取MISO的数据。不理会MOSI。

          430的SPI我用过,我的测试方法是这样的。
          将430的SPI口的MIOS,MOSI相连。
          用下面的程序测试

          //输入SPI输出数据,返回SPI 8CLK 的读数。
          unsignd char SPI(unsiged char OutData);

          unsigned char a,i;
          for(i=0; i<128; i++)
          {
          a=SPI(i);
          }

          我当时测的结果是这样的。
          OUT IN
          0    xx
          1   0
          2   1
          3   2
          ......
          SPI是一个8位的移位寄存器,只有8BIT满了后,我们的程序才读得出来,
          但是上面的例子中,写的同时马上读,是读不到的,原因是从8位的移位寄存器到总线要1个以上的CPU时钟才可。
          你先把你的SPI训服了,再弄你的SD卡。
          微控网感谢您的参与
          在线情况
          8
          • 头像
          • 级别
            • 积分14
            • 经验1391
            • 文章11
            • 注册2007-01-04
            程序通过了,发出复位命令后就收到正确的响应了。
            确实是SPI的事!
            可是又发现问题

            430发出命令计算卡容量:cardSize=MMC_ReadCardSize();计算出的结果是2032 664 576bytes
            但是卡放入读卡器中用WinHex查看,它给出的结果是Free Space:2030 960 640bytes,Total Capacity(总容量):2031 226 368bytes。(这个Free Space是总容量减去文件系统所占的容量后的真正的数据区容量)。问题就是430计算的卡容量与用WinHex查看的结果不一致。

            我觉得这个卡容量的误差倒是不大,可能是两个程序计算容量的算法上的不一致。更要命的问题是,430执行写SD卡命令mmcWriteSector(266240, buffer); (266240是我用WinHex查看SD卡真正数据区的开始地址,前面是引导扇区、FAT和根目录区),然后执行读SD卡命令mmcReadSector(266240, bbuffer);用cspy中watch查看buffer和bbuffer两个数组,发现内容确实一样,但是我用WinHex查看查看SD卡地址266240,没有写入任何数全是0!

            不知debug对这种现象有什么高见
            再次感谢debug的解释,谢谢您
            微控网感谢您的参与
            在线情况
            9
            • 头像
            • 级别
            • 门派
            • 职务论坛版主
            • 积分55
            • 经验17687
            • 文章198
            • 注册2006-03-07
            实读:  2032 664 576bytes  79280000
            WinHex:2030 960 640bytes  790E0000  
            相差1A0000 1.625MByte
            如果你可以确定你写入数据到SD卡后,读的回的Buffer不是同一个缓冲区,或是同一个缓冲区但清0过。那就可以证明你的R/W 没有问题。

            另外你用WinHex查看下下这两下扇,有没有一个是你想要的数据:
            266240 + (0x1A0000 / 512)
            266240 - (0x1A0000 / 512)
            微控网感谢您的参与
            在线情况
            10
            • 头像
            • 级别
              • 积分14
              • 经验1391
              • 文章11
              • 注册2007-01-04
              看到了,[em05]
              相差了249个扇区!我怎么就没想到在附近的扇区看看是否有数。

              这样的话,按照块地址来写数据,在做文件系统时就很麻烦。假设做成文件的话,文件大小为一个簇,在数据区的一个簇写入数据,同时在FAT1FAT2中标记一个字节和在根目录中占用32个字节,而SD卡写操作只能以扇区的首地址写入,但是在FAT1FAT2中430必须在指定地址写一个字节(根目录也是一样)。这样的话用430以文件形式存储在SD卡将很难实现

              是不是只能做一个文件大小正好为512个簇?(这样在FAT中可以直接写)
              微控网感谢您的参与
              在线情况
              11
              • 头像
              • 级别
              • 门派
              • 职务论坛版主
              • 积分55
              • 经验17687
              • 文章198
              • 注册2006-03-07
              这是一个FAT16文件系统的源码,你试试把你的读/写扇区的函数改到里面,再继续玩你的SD卡。
              有几点注意:
              1.扇区 不等于 簇,在FAT系统中记录的是簇号。 一个簇由多个扇区组成。在调试FAT16文件系统,时你最好在网上下一个关于 磁盘文件系统 的资料放在一边参考。
              2.在FAT系统读写文件总是有问题时,记得对SD卡做一下格式化,但一定要选择FAT16类型,通常默认的是FAT32的。
              [img]../images/fileType/rar.gif[/img]此主题相关文件 [url=../../upload/software/FAT16.rar]FAT16.rar[/url]
              微控网感谢您的参与
              在线情况
              12
              • 头像
              • 级别
                • 积分14
                • 经验1391
                • 文章11
                • 注册2007-01-04
                太感谢了,debug。文件系统程序写的好清楚!佩服佩服啊 Orz

                我刚才试了一下,就是RAM小了点
                那个全局变量BUFFER占用了512字节
                看来得换一个1610了,149是不行了

                微控网感谢您的参与
                Powered by LeadBBS 9.2 .
                Page created in 0.6089 seconds with 5 queries.