wyoujtg 发表于 2008-4-4 11:41:36

发个44b0的SD驱动(软件模拟SPI接口)

typedef unsigned charboolean;               /* 布尔变量                                 */
typedef unsigned charuint8;                   /* 无符号8位整型变量                        */
typedef signed   charint8;                  /* 有符号8位整型变量                        */
typedef unsigned short uint16;                  /* 无符号16位整型变量                     */
typedef signed   short int16;                   /* 有符号16位整型变量                     */
typedef unsigned int   uint32;                  /* 无符号32位整型变量                     */
typedef signed   int   int32;                   /* 有符号32位整型变量                     */
typedef float          fp32;                  /* 单精度浮点数(32位长度)               */
typedef double         fp64;                  /* 双精度浮点数(64位长度)

#define R00
#define R11
#define R1b 2
#define R23
#define R34

uint32 loop_time;
uint8rep;



#definenop()    do{;}while(0);

#defineCS_PIN    6//RS VD4
#defineDI_PIN    7//RW VD6

#defineSD_CS_PORT       rPDATE
#defineSD_CS_DDR_PORT   rPCONE
#defineSD_CS_PUP_PORT   rPUPE

#defineSD_DI_PORT       rPDATE
#defineSD_DI_DDR_PORT   rPCONE
#defineSD_DI_PUP_PORT   rPUPE


#defineDO_PIN    12//EN VD5
#defineCLK_PIN   13//RS VD4

#defineSD_DO_PORT       rPDATC
#defineSD_DO_DDR_PORT   rPCONC
#defineSD_DO_PUP_PORT   rPUPC

#defineSD_CLK_PORT       rPDATC
#defineSD_CLK_DDR_PORT   rPCONC
#defineSD_CLK_PUP_PORT   rPUPC

#define CS_LOW()   SD_CS_PORT&= ~(1<< CS_PIN)
#define CS_HIGH()SD_CS_PORT|= (1<< CS_PIN)
#define DI_LOW()   SD_DI_PORT&= ~(1<< DI_PIN)
#define DI_HIGH()SD_DI_PORT|= (1<< DI_PIN)
#define CLK_LOW()SD_CLK_PORT &= ~(1<< CLK_PIN)
#define CLK_HIGH() SD_CLK_PORT |= (1<< CLK_PIN)
#define DO()       SD_DO_PORT   & (0x01<<DO_PIN)

#define _400KHZ_ 128
#define _10MHZ_1

//-----------------------------------------------------------
//延时
static void loop(uint32 i)
//-----------------------------------------------------------
{
        while (i--)
        {
                ;//nop();
        }       
}

//-----------------------------------------------------------
//发送一字节数据
static void SPI_send(uint8 cmd)
//-----------------------------------------------------------
{
        uint8 i;
        uint8 MASK[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

        for (i = 0; i < 8; i++)
        {
                CLK_LOW();

                if (cmd & MASK)
         DI_HIGH();
                else
         DI_LOW();

                loop(loop_time);

                CLK_HIGH();
        }
}

//-----------------------------------------------------------
//接收一字节数据
static uint8 SPI_receive(void)
//-----------------------------------------------------------
{
        uint8 i;
        uint8 ret = 0;
        uint8 MASK[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

        for (i = 0; i < 8; i++)
        {
                CLK_LOW();

                loop(loop_time);

                if (DO())
                   ret |= MASK;

      CLK_HIGH();
        }
        return ret;
}

//-----------------------------------------------------------
//发送命令
static uint8 SendCommand(uint8 cmd, uint32 arg, uint8 ACK)
//-----------------------------------------------------------
{
        uint8 status;
        uint8 i;
        uint8 len;

        SPI_send(cmd|0x40);
        SPI_send(arg>>24);
        SPI_send(arg>>16);
        SPI_send(arg>>8);
        SPI_send(arg);
        SPI_send(0x95);

        switch (ACK)
        {
                case R0:
          return 1;
      case R1:
          len=1;
          break;
      case R2:
          len=2;
          break;
      case R3:
          len=5;
                  break;
      default:
          return 0;
          break;
        }

        for (i = 0; i < 100; i++)
        {
                status = SPI_receive();
      if (!(status & 0x80))
                  break;
    }

        if (i >= 100)
        {
          SPI_send(0xff);
      return 0;
        }

        rep = status;

        for (i = 1; i < len; i++)
        {
          rep = SPI_receive();
        }

        SPI_send(0xff);

        return 1;
}

//-----------------------------------------------------------
static void Reset(void)
//-----------------------------------------------------------
{
        CS_LOW();

        SendCommand(0x00,0x00,R0);

        CS_HIGH();
}

//-----------------------------------------------------------
static uint32 IsSD(void)
//-----------------------------------------------------------
{
        uint32 i;

        CS_LOW();

        for (i = 0; i < 1000; i++)
        {
           SendCommand(55,0x0000,R1);

       SendCommand(41,0x0000,R1);

       if (!rep)
             break;

       loop(200);
    }

    CS_HIGH();

    return i != 100;
}

//-----------------------------------------------------------
static uint32 IsMMC(void)
//-----------------------------------------------------------
{
        uint32 i;

        CS_LOW();

        for (i = 0; i < 1000; i++)
        {
       SendCommand(1, 0x0000, R1);

       if (!rep)
             break;

       loop(200);
    }

        CS_HIGH();

    return i != 100;
}

//-----------------------------------------------------------
int SD_erase(uint32 sector,uint8 *buff)
//-----------------------------------------------------------
{
        CS_LOW();

        if (!SendCommand(32,sector<<9,R1)||!SendCommand(33,sector<<9,R1)||!SendCommand(38,0x0000,R1))
        {
           CS_HIGH();

           return 0;
        }

    while (!DO())
             SPI_send(0xff);

    CS_HIGH();
   
    return 1;
}

uint32 SD_read(uint32 sector,uint8 *buff)
{
        uint32 i;

        CS_LOW();

        if (!SendCommand(17,sector<<9,R1))
        {
           CS_HIGH();
           //UART_puts("readerr1");
           return 0;
        }

        for (i = 0; i < 100; i++)
        {
       if (SPI_receive() == 0xfe)
             break;
    }

    if (i >= 100)
    {
       CS_HIGH();
       //UART_puts("readerr2");
       return 0;
    }

        for (i = 0; i < 512; i++)
        {
           *buff++ = SPI_receive();
    }

        SPI_receive();
        SPI_receive();

        SPI_send(0xff);

        CS_HIGH();
       
        //UART_puts("readOK");

        return 1;
}

uint32 SD_write(uint32 sector,uint8 *buff)
{
        uint32 i;

        CS_LOW();

        SendCommand(24,sector<<9,R1);

        SPI_send(0xfe);

        for (i = 0; i < 512; i++)
            SPI_send(buff);

        SPI_send(0xff);
        SPI_send(0xff);

        for (i = 0; i < 100; i++)
        {
           rep = SPI_receive();
       if (!rep)
             break;
    }
    if (i >= 100)
    {
       //UART_puts("writeerr1");
           return 0;
        }

    while (!DO())
                SPI_send(0xff);

    CS_HIGH();
   
    //UART_puts("writeOK");
//下面其实是复位   
    loop_time =_400KHZ_;
       
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
       
        IsSD();
       
        loop_time=_10MHZ_;
//完
    return 1;
}

void SD_install(void)
{
        loop_time =_400KHZ_;
       
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);
        SPI_send(0xff);

        Reset();

        if (!IsSD()&&!IsMMC())
        {
                //UART_puts("unknown card type!\n");
                return;
        }
        //UART_puts("SD/MMC card found!\n Now loading SD/MMC driver......\n");
        loop_time=_10MHZ_;
}

void SD_init(void)
{
        uint32 temp;
   
        temp = rPCONC;
        temp &= 0xf0ffffff;
        temp |= 0x04000000;
        rPCONC = temp;

        temp = rPCONE;
        temp &= 0xffff0fff;
        temp |= 0x00005000;
        rPCONE = temp;
          
        SD_install();
}
/*
一直想在自己的44b0开发板上,挂个SD卡,再上个FAT文件系统,
郁闷的是,44B0没有多媒体卡的接口,也没SPI接口,只能通过用IO软件模拟SPI接口,比较慢,不过还是可以用的
在论坛下了个在AVR上的用IO软件模拟SPI接口的程序,可惜调不通,后来在网上找到了个PC版的,改了下接口,调通了
不过,在我的SD卡上,也不知道为什么,写完一个扇区后要复位才可以再读扇区,不然会出现错误
有44b0的朋友帮忙下,能否建立个FAT文件系统
*/

hyz_avr 发表于 2008-4-4 13:42:07

支持一下..

bing0110 发表于 2008-4-4 14:03:35

ding

mcspic 发表于 2008-4-4 14:09:27

44B0的I/O速度太慢了,前几天我也是44B0用软件模拟SPI,用示波器看了下,全速的情况下SCK的频率也只有400KHZ左右

wufenghai 发表于 2008-4-5 20:59:48

请问S3C44B0X的SIO口不能当作SPI口用吗???,我现在正在用S3C44B0X SIO+MCP2515 SPI扩展CAN接口,但是没调通,很郁闷

R28FA 发表于 2008-4-6 11:36:06

mark

544746174 发表于 2008-5-18 10:01:38

S3C44B0X的SIO口能当作SPI,S3C44B0X SIO+MCP2515 SPI扩展CAN接口,是可以的

zhanliang1985 发表于 2011-3-12 09:31:16

您那个AVR上的用IO软件模拟SPI接口的程序在哪?

honey655729 发表于 2011-3-12 11:22:37

好的,谢谢了,

csdnct 发表于 2012-5-15 22:47:00

抄袭别人的东西请注明来源
页: [1]
查看完整版本: 发个44b0的SD驱动(软件模拟SPI接口)