关于SPI驱动SD卡就是初始化失败

2019-07-20 05:55发布

本帖最后由 chao超 于 2018-9-30 08:54 编辑

这些指令应该是没有什么问题应为初始化有时可以成功
void SPI2_SetSpeed(u8 SpeedSet)
{
        SpeedSet&=0X07;                        //限制范围
        SPI2->CR1&=0XFFC7;
        SPI2->CR1|=SpeedSet<<3;        //设置SPI1速度  
        SPI2->CR1|=1<<6;                 //SPI设备使能
}



u8 SPI2_ReadWriteByte(u8 TxData)
{         
         
        while((SPI2->SR&1<<1)==0);                //等待发送区空
        SPI2->DR=TxData;                                   //发送一个byte  
        while((SPI2->SR&1<<0)==0){}                //等待接收完一个byte  
         return SPI2->DR;                          //返回收到的数据                                    
}

void SPI2_Init(void)
{
         u16 tempreg=0;
        RCC->AHB1ENR|=1<<1;            //使能PORTB时钟         
        RCC->AHB1ENR|=1<<2;            //使能PORTC时钟        
        RCC->APB1ENR|=1<<14;           //SPI1时钟使能
         
        GPIO_Set(GPIOC,1<<1,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);        //PB3~5复用功能输出
        GPIO_Set(GPIOC,1<<2,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);        //PB3~5复用功能输出        
        GPIO_Set(GPIOC,1<<3,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);        //PB3~5复用功能输出        
        GPIO_Set(GPIOB,1<<13,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);        //PB3~5复用功能输出         

        GPIO_AF_Set(GPIOB,13,5);        //PB3,AF5
         GPIO_AF_Set(GPIOC,2,5);        //PB4,AF5
         GPIO_AF_Set(GPIOC,3,5);        //PB5,AF5
        
        //这里只针对SPI口初始化
        RCC->APB1RSTR|=1<<14;        //复位SPI1
        RCC->APB1RSTR&=~(1<<14);//停止复位SPI1
        tempreg|=0<<10;                        //全双工模式        
        tempreg|=1<<9;                        //软件nss管理
        tempreg|=1<<8;                        
        tempreg|=1<<2;                        //SPI主机  
        tempreg|=0<<11;                        //8位数据格式        
        tempreg|=1<<1;                        //空闲模式下SCK为1 CPOL=1
        tempreg|=1<<0;                        //数据采样从第2个时间边沿开始,CPHA=1  
         //对SPI1属于APB2的外设.时钟频率最大为84Mhz频率.
        tempreg|=7<<3;                        //Fsck=Fpclk1/256
        tempreg|=0<<7;                        //MSB First  
        
        tempreg|=1<<6;                        //SPI启动
        SPI2->CR1=tempreg;                 //设置CR1
                SPI2->CRCPR =0;
        SPI2->CRCPR=0x0007;
        SPI2->I2SCFGR&=~(1<<11);//选择SPI模式
        SPI2_ReadWriteByte(0xff);//启动传输        

}

         void SPI_Send_Cmd(u8 cmdindex,u32 arg,u8 crc)
        {
                  CS=0;        
               
                  SPI2_ReadWriteByte( 0x40|cmdindex);
              
                  SPI2_ReadWriteByte( arg>>24 );

                  SPI2_ReadWriteByte( arg>>16 );

                  SPI2_ReadWriteByte( arg>>8  );

                  SPI2_ReadWriteByte( arg>>0  );

                  SPI2_ReadWriteByte( crc  );

      CS=1;
        }

          u8 CmdErrorR1( void )
        {
        
                u8 rec,i=30;
        CS=0;
                while(i--)
                {
                        rec=SPI2_ReadWriteByte(0xff);               
                          if(rec==0x01)
                                {  
                        CS=1;   
                        SPI2_ReadWriteByte(0xff);               
                        return 0;
                               }
                        
                }
                CS=1;
                return 1;
              
        }

                u8 CmdError_r1(void)
        {
           u8 rec=0,i=30;        
                CS=0;
                while(i--)
                {
                        rec=SPI2_ReadWriteByte(0xff);        
                          if(rec==0x00)
                                {  
                CS=1;   
                SPI2_ReadWriteByte(0xff);
                return 0;
                                }        
        }
                CS=1;
                return 1;               
        }
        
                  u8 CmdErrorr1( void )
        {
        
                u8 rec,i=30;
        CS=0;
                while(i--)
                {
                rec=SPI2_ReadWriteByte(0xff);               
                  if(rec==0x01)
                        {  
                CS=1;   
                SPI2_ReadWriteByte(0xff);               
                return 0;
                        }
                        
                }
                CS=1;
                return 1;
              
        }
               
        void CmdErrorR3( void )
        {
                u8 rec;        
                CS=0;
                rec=SPI2_ReadWriteByte(0xff);        
                ARG_Tab[3]=SPI2_ReadWriteByte(0xff);        
                ARG_Tab[2]=SPI2_ReadWriteByte(0xff);
                ARG_Tab[1]=SPI2_ReadWriteByte(0xff);
                ARG_Tab[0]=SPI2_ReadWriteByte(0xff);
               
                SPI2_ReadWriteByte(0xff);
                CS=1;         
        }
        
   u8 SD_PowerOn(void)
   {

    u8 i=0;
        u8 errorstatus=0;
        u32 count=0,validvoltage=0;
        u32 SDType=0;
          CS=1;
    GPIOC->ODR |=1<<2;
    GPIOC->ODR |=1<<3;           
            for(i=0;i<10;i++)
        {
     SPI2_ReadWriteByte(0xff);
               
         }
            
        for(i=0;i<200;i++)
        {
                SPI_Send_Cmd(SD_CMD_GO_IDLE_STATE,0,0x95);//发arg送CMD0进入SPI模式命令.                                                                                                  
                errorstatus=CmdErrorR1();
                if(errorstatus==0) break;
         }

         if(errorstatus)return errorstatus;//返回错误状态
        
    printf("SPI MODE is OK ");
    for(i=0;i<200;i++)
        {
           SPI_Send_Cmd(SD_CMD_HS_SEND_EXT_CSD,SD_CHECK_PATTERN,0x01);//发送CMD8,短响应,检查SD卡接口特性.
                                                                                                                 //arg[11:8]:01,支持电压范围,2.7~3.6V
                                                                                                                //arg[7:0]:默认0XAA
                                                                                                        
                errorstatus=CmdErrorR1();                 //等待R1响应
                SPI_Send_Cmd((u8)58,0,0x01);//发送CMD58
                CmdErrorR3();
                if(errorstatus==0) break;        
        }
        if(errorstatus)return errorstatus;//返回错误状态
//         
//           if(errorstatus==0)                                                                 //R1响应正常
//        {
                        CardType=SDIO_STD_CAPACITY_SD_CARD_V2_0;                //SD 2.0卡
                        SDType=SD_HIGH_CAPACITY;                                                   //高容量卡
                        printf("Card returns response without illegal command ");
                        
                    SPI_Send_Cmd(SD_CMD_APP_CMD,0,0x01);//发送CMD55
                        errorstatus=CmdErrorR1();                        
                if(errorstatus)return errorstatus;//返回错误状态  
                printf("/*******************/ ");                                
                        
                 while((!validvoltage)&&(count<200))
                {        


                        SPI_Send_Cmd(SD_CMD_APP_CMD,0,0x01);//发送CMD55
                        errorstatus=CmdErrorR1();                        
                if(errorstatus)return errorstatus;//返回错误状态  
                printf("/*******************/ ");                                
                        
                    SPI_Send_Cmd(SD_CMD_SD_APP_OP_COND,SDType|SD_VOLTAGE_WINDOW_SD,0x01);//发送CMD41
                        errorstatus=CmdError_r1();
               
                if(errorstatus==0)return errorstatus;           //响应错误
                printf("/********ddd***********/ ");         运行到这里就不行了,不知道怎么回事
               
                        SPI_Send_Cmd( (u8)58,0,0x01);//发送CMD58
                        CmdErrorR3();
//                        validvoltage=((ARG_Tab[3] & 0x80)?1:0);                        //判断SD卡上电是否完成
//                        count++;
           if(ARG_Tab[3] & 0x80) validvoltage=1; count++;
                                   
                }               
                printf("check the function ");
               
                if(count>=200)
                {
                        errorstatus=SD_INVALID_VOLTRANGE;
                        printf("SD_INVALID_VOLTRANGE ");
                        return 0;
                }
               
                if(ARG_Tab[3]&=0x40)
                {
                        CardType=SDIO_HIGH_CAPACITY_SD_CARD;
                        printf("SDIO_HIGH_CAPACITY_SD_CARD ");
                }         
        
               
//        }
        
//    else
//   {
//                printf(" illegal command ");   
//                SPI_Send_Cmd(55,0,0x01);//发送CMD55
//                errorstatus=CmdErrorR1();               
//        if(errorstatus)return errorstatus;//返回错误状态  
//                SPI_Send_Cmd(41,SD_VOLTAGE_WINDOW_SD,0x01);//发送CMD41
//                errorstatus=CmdError_r1();
//    if(errorstatus)return errorstatus;//返回错误状态  
//    else                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
//        {
//                CardType=SDIO_STD_CAPACITY_SD_CARD_V1_1;
//                printf("SDIO_STD_CAPACITY_SD_CARD_V1_1 ");        
//                return 0;
//        }
//        
//   }

   return 0;        


   }


   u8 Read_SDSocket(u8 *buff, u32 address ,u8 mode )  
   {
           u8 errorstatus=0,i=0,j=0;
           if(mode==0)  // read block
           {
   for(i=0;i<60;i++)
   {                  
   SPI_Send_Cmd( SD_CMD_READ_SINGLE_BLOCK, address, 0x01);//发送CMD17
   errorstatus=CmdError_r1();
   if(errorstatus==0)break;            
   }           
   if(errorstatus)  return errorstatus;  
        
   printf("Read_SDSocket ");
   CS=0;   
   while( !(SPI2_ReadWriteByte(0xff)==0xfe)  ){}

    printf("www ");           
   for(i=0;i<64;i++)
   {   
           
          *buff=SPI2_ReadWriteByte(0xff);
           buff++;
                  
   }

   SPI2_ReadWriteByte(0xff); //tow byte CRC
   SPI2_ReadWriteByte(0xff);
   CS=1;
       }
      else if(mode==1) // read multiple block
           {
   SPI_Send_Cmd( (u8)18, address, 0x01);//发送CMD18
   errorstatus=CmdError_r1();
   if(errorstatus)  return errorstatus;
   CS=0;           
   while( !(SPI2_ReadWriteByte(0xff)==0xFE)  ){}
   CS=1;
           for(j=0;j<Size;j++)  // 读多块的大小可以通过改SIZE来实现 SIZE越大读的区域就越多当然不可能无限扩大
       {        
                   CS=0;   
                   for(i=0;i<64;i++)
                   {
                          *buff=SPI2_ReadWriteByte(0xff);
                           buff++;           
                   }           
                           SPI2_ReadWriteByte(0xff); //tow byte CRC
                           SPI2_ReadWriteByte(0xff);
           CS=1;                  
           }
           
   SPI_Send_Cmd( (u8)12,0,0x01);//发送CMD10           
           }  
           return 0;
   }


     u8 Write_SDSocket(u8 *buff, u32 address ,u8 mode )  
   {
           u8 errorstatus=0,i=0,j=0;
           if(mode==0)  // read block
           {
   SPI_Send_Cmd( (u8)24, address, 0x01);//发送CMD17
   errorstatus=CmdError_r1();
   if(errorstatus)  return errorstatus;
   printf("Write_SDSocket ");
   for(i=0;i<5;i++)                  
   SPI2_ReadWriteByte(0xff);

   SPI2_ReadWriteByte(0xFE);           
   for(i=0;i<64;i++)
   {
           SPI2_ReadWriteByte(*buff);
           buff++;           
   }
   SPI2_ReadWriteByte(0xff); //send tow byte CRC
   SPI2_ReadWriteByte(0xff);

  while( !(SPI2_ReadWriteByte(0xff)==0x05)  ){}
  while( !(SPI2_ReadWriteByte(0xff)==0xff)  ){}         
       }
      else if(mode==1) // read multiple block
           {
   SPI_Send_Cmd( (u8)25, address, 0x01);//发送CMD10
   errorstatus=CmdError_r1();
   if(errorstatus)  return errorstatus;
                  
                        for(j=0;j<Size;j++)
        {                  
                for(i=0;i<5;i++)                  
                SPI2_ReadWriteByte(0xff);

                SPI2_ReadWriteByte(0xFC);           
                for(i=0;i<64;i++)
                  {
                SPI2_ReadWriteByte(*buff);
                buff++;           
                  }
                SPI2_ReadWriteByte(0xff); //send tow byte CRC
                SPI2_ReadWriteByte(0xff);
                while( !(SPI2_ReadWriteByte(0xff)==0x05)  ){}
        }
        
   SPI2_ReadWriteByte(0xFD);
   while( !(SPI2_ReadWriteByte(0xff)==0xff)  ){}        

           }  
   return 1;
   }
   求解决红 {MOD}处的问题

0条回答

一周热门 更多>