亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? mmc_sd.c

?? 基于stm32的MP3播放器
?? C
?? 第 1 頁 / 共 2 頁
字號:
/******************************************************************************* 
*  本文件為SPI操作SD卡的底層驅動文件
*  包括SPI模塊及相關IO的初始化,SPI讀寫SD卡(寫指令,讀數據等)
*******************************************************************************/   
#include "mmc_sd.h"	   							   
u8  SD_Type=0;//SD卡的類型	 
////////////////////////////////////////////////////////////////////////////////
// 以下是SPI模塊的初始化代碼,配置成主機模式,訪問SD卡
////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* Function Name  : SPI2_Configuration
* Description    : SPI模塊初始化,【包括相關IO口的初始化】
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI2_Configuration(void)
{	 
	RCC->APB2ENR|=1<<3;       //PORTB時鐘使能  
	RCC->APB1ENR|=1<<14;      //SPI2時鐘使能	 
	
	//存儲器映射,不用理    
	#ifdef  VECT_TAB_RAM  									   
	  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
	#else   							 
	  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
	#endif  
			    
	GPIOB->CRH&=0X0000FFFF;//PB13.14.15復用輸出
	GPIOB->CRH|=0XBBB30000;//PB12推挽輸出 	 
	GPIOB->ODR|=0XF000;    //PB12.13.14.15上拉  
	
	SPI2->CR1|=0<<10;//全雙工模式	
	SPI2->CR1|=1<<9; //軟件nss管理
	SPI2->CR1|=1<<8;  

	SPI2->CR1|=1<<2; //SPI主機
	SPI2->CR1|=0<<11;//8bit數據格式	
	SPI2->CR1|=1<<1; //空閑模式下SCK為1 CPOL=1
	SPI2->CR1|=1<<0; //數據采樣從第二個時間邊沿開始,CPHA=1  
	SPI2->CR1|=6<<3; //Fsck=Fcpu/256
	SPI2->CR1|=0<<7; //MSBfirst 
	
	SPI2->CR1|=1<<6; //SPI設備使能		 
}

/*******************************************************************************
* Function Name  : SPI2_SetSpeed
* Description    : SPI設置速度為高速
* Input          : u8 SpeedSet 
*                  如果速度設置輸入0,則低速模式,非0則高速模式
*                  SPI_SPEED_HIGH   1
*                  SPI_SPEED_LOW    0
* Output         : None
* Return         : None
*******************************************************************************/
void SPI2_SetSpeed(u8 SpeedSet)
{
	SPI2->CR1&=0XFFC7;//Fsck=Fcpu/256
	if(SpeedSet==SPI_SPEED_HIGH)//高速
	{
		SPI2->CR1|=0<<3;//Fsck=Fpclk/2=18Mhz	
	}else//低速
	{
		SPI2->CR1|=6<<3; //Fsck=Fpclk/256=281.25Khz
	}
	SPI2->CR1|=1<<6; //SPI設備使能	  
}
	 
/*******************************************************************************
* Function Name  : SPI2_ReadWriteByte
* Description    : SPI讀寫一個字節(發送完成后返回本次通訊讀取的數據)
* Input          : u8 TxData 待發送的數
* Output         : None
* Return         : u8 RxData 收到的數
*******************************************************************************/
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;          //返回收到的數據				    
}

/*******************************************************************************
* Function Name  : SD_WaitReady
* Description    : 等待SD卡Ready
* Input          : None
* Output         : None
* Return         : u8 
*                   0: 成功
*                   other:失敗
*******************************************************************************/
u8 SD_WaitReady(void)
{
    u8 r1;
    u16 retry;
    retry = 0;
    do
    {
        r1 = SPI2_ReadWriteByte(0xFF);
        if(retry==0xfffe)return 1; 
    }while(r1!=0xFF); 
    return 0;
}	 
/*******************************************************************************
* Function Name  : SD_SendCommand
* Description    : 向SD卡發送一個命令
* Input          : u8 cmd   命令 
*                  u32 arg  命令參數
*                  u8 crc   crc校驗值
* Output         : None
* Return         : u8 r1 SD卡返回的響應
*******************************************************************************/
u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc)
{
    unsigned char r1;
    unsigned char Retry = 0;

    //????????
    SPI2_ReadWriteByte(0xff);
    //片選端置低,選中SD卡
    SD_CS_ENABLE();

    //發送
    SPI2_ReadWriteByte(cmd | 0x40);                         //分別寫入命令
    SPI2_ReadWriteByte(arg >> 24);
    SPI2_ReadWriteByte(arg >> 16);
    SPI2_ReadWriteByte(arg >> 8);
    SPI2_ReadWriteByte(arg);
    SPI2_ReadWriteByte(crc);
    
    //等待響應,或超時退出
    while((r1 = SPI2_ReadWriteByte(0xFF))==0xFF)
    {
        Retry++;
        if(Retry > 200)break; 
    }   
    //關閉片選
    SD_CS_DISABLE();
    //在總線上額外增加8個時鐘,讓SD卡完成剩下的工作
    SPI2_ReadWriteByte(0xFF);

    //返回狀態值
    return r1;
}


/*******************************************************************************
* Function Name  : SD_SendCommand_NoDeassert
* Description    : 向SD卡發送一個命令(結束是不失能片選,還有后續數據傳來)
* Input          : u8 cmd   命令 
*                  u32 arg  命令參數
*                  u8 crc   crc校驗值
* Output         : None
* Return         : u8 r1 SD卡返回的響應
*******************************************************************************/
u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc)
{
    unsigned char r1;
    unsigned char Retry = 0;

    //????????
    SPI2_ReadWriteByte(0xff);
    //片選端置低,選中SD卡
    SD_CS_ENABLE();

    //發送
    SPI2_ReadWriteByte(cmd | 0x40);                         //分別寫入命令
    SPI2_ReadWriteByte(arg >> 24);
    SPI2_ReadWriteByte(arg >> 16);
    SPI2_ReadWriteByte(arg >> 8);
    SPI2_ReadWriteByte(arg);
    SPI2_ReadWriteByte(crc);

    //等待響應,或超時退出
    while((r1 = SPI2_ReadWriteByte(0xFF))==0xFF)
    {
        Retry++;
        if(Retry > 200)break;   
    }
    //返回響應值
    return r1;
}

/*******************************************************************************
* Function Name  : SD_Init
* Description    : 初始化SD卡
* Input          : None
* Output         : None
* Return         : u8 
*                  0:NO_ERR
*                  1:TIME_OUT
*                  99:NO_CARD
*******************************************************************************/
u8 SD_Init(void)
{
    u16 i;      // 用來循環計數
    u8 r1;      // 存放SD卡的返回值
    u16 retry;  // 用來進行超時計數
    u8 buff[6];
					 
	SPI2_Configuration();
	SPI2_SetSpeed(0);
	SD_CS_ENABLE();
					  
    // 純延時,等待SD卡上電完成
    for(i=0;i<0xf00;i++);

    //先產生>74個脈沖,讓SD卡自己初始化完成
    for(i=0;i<10;i++)
    {
        SPI2_ReadWriteByte(0xFF);
    }

    //-----------------SD卡復位到idle開始-----------------
    //循環連續發送CMD0,直到SD卡返回0x01,進入IDLE狀態
    //超時則直接退出
    retry = 0;
    do
    {
        //發送CMD0,讓SD卡進入IDLE狀態
        r1 = SD_SendCommand(CMD0, 0, 0x95);
        retry++;
    }while((r1 != 0x01) && (retry<200));
    //跳出循環后,檢查原因:初始化成功?or 重試超時?
    if(retry==200) return 1;   //超時返回1	  
    //-----------------SD卡復位到idle結束-----------------	 
    //獲取卡片的SD版本信息
    r1 = SD_SendCommand_NoDeassert(8, 0x1aa, 0x87);	     
    //如果卡片版本信息是v1.0版本的,即r1=0x05,則進行以下初始化
    if(r1 == 0x05)
    {
        //設置卡類型為SDV1.0,如果后面檢測到為MMC卡,再修改為MMC
        SD_Type = SD_TYPE_V1;	   
        //如果是V1.0卡,CMD8指令后沒有后續數據
        //片選置高,結束本次命令
        SD_CS_DISABLE();
        //多發8個CLK,讓SD結束后續操作
        SPI2_ReadWriteByte(0xFF);	  
        //-----------------SD卡、MMC卡初始化開始-----------------	 
        //發卡初始化指令CMD55+ACMD41
        // 如果有應答,說明是SD卡,且初始化完成
        // 沒有回應,說明是MMC卡,額外進行相應初始化
        retry = 0;
        do
        {
            //先發CMD55,應返回0x01;否則出錯
            r1 = SD_SendCommand(CMD55, 0, 0);
            if(r1 != 0x01)return r1;	  
            //得到正確響應后,發ACMD41,應得到返回值0x00,否則重試200次
            r1 = SD_SendCommand(ACMD41, 0, 0);
            retry++;
        }while((r1!=0x00) && (retry<400));
        // 判斷是超時還是得到正確回應
        // 若有回應:是SD卡;沒有回應:是MMC卡
        
        //----------MMC卡額外初始化操作開始------------
        if(retry==400)
        {
            retry = 0;
            //發送MMC卡初始化命令(沒有測試)
            do
            {
                r1 = SD_SendCommand(1, 0, 0);
                retry++;
            }while((r1!=0x00)&& (retry<400));
            if(retry==400)return 1;   //MMC卡初始化超時		    
            //寫入卡類型
            SD_Type = SD_TYPE_MMC;
        }
        //----------MMC卡額外初始化操作結束------------	    
        //設置SPI為高速模式
        SPI2_SetSpeed(1);   
		SPI2_ReadWriteByte(0xFF);
        
        //禁止CRC校驗	   
		r1 = SD_SendCommand(CMD59, 0, 0x95);
        if(r1 != 0x00)return r1;  //命令錯誤,返回r1   	   
        //設置Sector Size
        r1 = SD_SendCommand(CMD16, 512, 0x95);
        if(r1 != 0x00)return r1;//命令錯誤,返回r1		 
        //-----------------SD卡、MMC卡初始化結束-----------------

    }//SD卡為V1.0版本的初始化結束	 
    //下面是V2.0卡的初始化
    //其中需要讀取OCR數據,判斷是SD2.0還是SD2.0HC卡
    else if(r1 == 0x01)
    {
        //V2.0的卡,CMD8命令后會傳回4字節的數據,要跳過再結束本命令
        buff[0] = SPI2_ReadWriteByte(0xFF);  //should be 0x00
        buff[1] = SPI2_ReadWriteByte(0xFF);  //should be 0x00
        buff[2] = SPI2_ReadWriteByte(0xFF);  //should be 0x01
        buff[3] = SPI2_ReadWriteByte(0xFF);  //should be 0xAA	    
        SD_CS_DISABLE();	  
        SPI2_ReadWriteByte(0xFF);//the next 8 clocks			 
        //判斷該卡是否支持2.7V-3.6V的電壓范圍
        //if(buff[2]==0x01 && buff[3]==0xAA) //不判斷,讓其支持的卡更多
        {	  
            retry = 0;
            //發卡初始化指令CMD55+ACMD41
    		do
    		{
    			r1 = SD_SendCommand(CMD55, 0, 0);
    			if(r1!=0x01)return r1;	   
    			r1 = SD_SendCommand(ACMD41, 0x40000000, 0);
                if(retry>200)return r1;  //超時則返回r1狀態  
            }while(r1!=0);		  
            //初始化指令發送完成,接下來獲取OCR信息		   
            //-----------鑒別SD2.0卡版本開始-----------
            r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);
            if(r1!=0x00)return r1;  //如果命令沒有返回正確應答,直接退出,返回應答		 
            //讀OCR指令發出后,緊接著是4字節的OCR信息
            buff[0] = SPI2_ReadWriteByte(0xFF);
            buff[1] = SPI2_ReadWriteByte(0xFF); 
            buff[2] = SPI2_ReadWriteByte(0xFF);
            buff[3] = SPI2_ReadWriteByte(0xFF);

            //OCR接收完成,片選置高
            SD_CS_DISABLE();
            SPI2_ReadWriteByte(0xFF);

            //檢查接收到的OCR中的bit30位(CCS),確定其為SD2.0還是SDHC
            //如果CCS=1:SDHC   CCS=0:SD2.0
            if(buff[0]&0x40)SD_Type = SD_TYPE_V2HC;    //檢查CCS	 
            else SD_Type = SD_TYPE_V2;	    
            //-----------鑒別SD2.0卡版本結束----------- 
            //設置SPI為高速模式
            SPI2_SetSpeed(1);  
        }	    
    }
    return r1;
}



/*******************************************************************************
* Function Name  : SD_ReceiveData
* Description    : 從SD卡中讀回指定長度的數據,放置在給定位置
* Input          : u8 *data(存放讀回數據的內存>len)
*                  u16 len(數據長度)
*                  u8 release(傳輸完成后是否釋放總線CS置高 0:不釋放 1:釋放)
* Output         : None
* Return         : u8 
*                  0:NO_ERR
*                  other:錯誤信息
*******************************************************************************/
u8 SD_ReceiveData(u8 *data, u16 len, u8 release)
{
    u16 retry;
    u8 r1;

    // 啟動一次傳輸
    SD_CS_ENABLE();
    //等待SD卡發回數據起始令牌0xFE
    retry = 0;										   
	do
    {
        r1 = SPI2_ReadWriteByte(0xFF);
        retry++;
        if(retry>2000)  //2000次等待后沒有應答,退出報錯
        {
            SD_CS_DISABLE();
            return 1;
        }
    }while(r1 != 0xFE);
		   
    //開始接收數據
    while(len--)
    {
        *data = SPI2_ReadWriteByte(0xFF);
        data++;
    }

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
中文字幕精品—区二区四季| 精品久久久久久久人人人人传媒 | 亚洲h在线观看| 国产精品久久久久久久久久久免费看| 欧美zozo另类异族| 日韩欧美激情在线| 欧美成人官网二区| 精品久久久影院| 精品裸体舞一区二区三区| 日韩一区二区免费视频| 欧美一区二区三区啪啪| 欧美一区永久视频免费观看| 3d动漫精品啪啪一区二区竹菊| 欧美精品免费视频| 日韩一区国产二区欧美三区| 欧美一区国产二区| 久久综合给合久久狠狠狠97色69| 精品国产网站在线观看| 久久久99精品免费观看| 中文一区二区在线观看| 中文字幕五月欧美| 亚洲一区二区三区激情| 舔着乳尖日韩一区| 国产在线精品免费av| 成人晚上爱看视频| 欧美在线不卡视频| 精品久久久网站| 国产精品毛片a∨一区二区三区| 中文字幕在线不卡国产视频| 一区二区三区小说| 蜜芽一区二区三区| 国产+成+人+亚洲欧洲自线| 99久久久免费精品国产一区二区| 色一情一乱一乱一91av| 91麻豆精品国产| 日本一区二区动态图| 亚洲一区在线观看视频| 激情久久久久久久久久久久久久久久| 国产风韵犹存在线视精品| 色哟哟国产精品| 精品久久久久av影院| 亚洲欧美另类久久久精品 | 午夜免费欧美电影| 国产美女精品一区二区三区| 色伊人久久综合中文字幕| 精品日韩欧美一区二区| 国产精品成人在线观看| 日韩国产欧美一区二区三区| 国产一区二区在线观看视频| 欧美三级电影网| 国产日本欧美一区二区| 日韩黄色一级片| 91视频观看免费| 精品女同一区二区| 亚洲123区在线观看| 成人在线视频一区| 日韩欧美中文字幕精品| 亚洲欧美精品午睡沙发| 国产精品一区二区久久精品爱涩 | 自拍视频在线观看一区二区| 蜜臀精品久久久久久蜜臀| 在线欧美日韩精品| 中文字幕亚洲在| 国产福利一区在线观看| 欧美精品xxxxbbbb| 亚洲最大成人综合| 99这里都是精品| 久久久亚洲高清| 久久精品噜噜噜成人88aⅴ| 欧美性极品少妇| 综合久久久久久久| 成人av在线影院| 久久精品视频免费| 久久99国产精品久久| 欧美日韩mp4| 亚洲成人激情综合网| 92国产精品观看| 国产精品剧情在线亚洲| 国产高清不卡一区| 精品剧情v国产在线观看在线| 婷婷一区二区三区| 欧美精品精品一区| 日本午夜一本久久久综合| 欧美日韩一区久久| 亚洲成a人片综合在线| 在线欧美日韩国产| 亚洲一区二区精品视频| 在线观看国产一区二区| 一区二区免费看| 欧美最猛黑人xxxxx猛交| 一区二区三区四区av| 欧美性猛交xxxx乱大交退制版| 亚洲精品国产第一综合99久久| 91蝌蚪porny| 亚洲一级二级三级| 欧美猛男gaygay网站| 免费美女久久99| 精品日韩一区二区三区免费视频| 蜜臀久久99精品久久久久久9 | 欧美成人三级在线| 精品一区二区三区香蕉蜜桃 | 成人精品小蝌蚪| **欧美大码日韩| 欧美优质美女网站| 奇米色777欧美一区二区| 欧美tickle裸体挠脚心vk| 激情综合色播激情啊| 国产精品无人区| 色哟哟国产精品| 日本一道高清亚洲日美韩| 日韩一区二区三区四区五区六区 | 婷婷开心久久网| 精品国产一区二区三区四区四| 国产成人在线视频网址| 一区二区视频在线看| 日韩一区二区在线免费观看| 国产成人在线色| 亚洲国产美女搞黄色| 欧美草草影院在线视频| 99久久精品国产导航| 日本91福利区| 国产精品你懂的在线| 欧美高清视频不卡网| 国产精品正在播放| 亚洲伊人伊色伊影伊综合网| 精品国产精品网麻豆系列| 一本色道**综合亚洲精品蜜桃冫| 日韩成人dvd| 综合网在线视频| 欧美xxxxxxxxx| 日本高清不卡aⅴ免费网站| 狠狠色丁香九九婷婷综合五月| 日韩美女啊v在线免费观看| 91精品国产麻豆| 色婷婷av一区二区三区软件| 久久精品99久久久| 亚洲亚洲精品在线观看| 久久精品一区二区三区四区| 精品视频1区2区| 99re8在线精品视频免费播放| 日本亚洲视频在线| 一区二区在线观看视频| 国产欧美va欧美不卡在线| 欧美一区二区三区四区五区| 成人中文字幕在线| 黑人精品欧美一区二区蜜桃| 亚洲韩国精品一区| 亚洲同性gay激情无套| 久久久久久一二三区| 91精品免费观看| 精品视频色一区| 色香蕉久久蜜桃| 91在线播放网址| 丁香婷婷综合网| 国产一区在线精品| 另类小说欧美激情| 日韩制服丝袜av| 一区二区久久久久| 综合激情成人伊人| 伊人婷婷欧美激情| 亚洲人成网站影音先锋播放| 国产精品美女www爽爽爽| 日本一区二区三区国色天香| 欧美精品一区二区久久久| 日韩一区二区三区四区| 555www色欧美视频| 欧美日韩国产天堂| 6080午夜不卡| 日韩西西人体444www| 欧美一级欧美三级| 91麻豆精品国产91久久久资源速度 | 欧美国产精品久久| 国产偷国产偷亚洲高清人白洁| 欧美大胆一级视频| 精品久久久久久久久久久久包黑料| 91精品国产欧美日韩| 日韩免费观看高清完整版| 日韩丝袜情趣美女图片| 日韩欧美国产一二三区| 26uuu亚洲| 国产午夜精品理论片a级大结局| 久久久综合九色合综国产精品| 亚洲精品一区在线观看| 久久久久久电影| 国产精品乱人伦| 一区二区三区免费网站| 亚洲va国产天堂va久久en| 蜜臀久久久99精品久久久久久| 卡一卡二国产精品 | 亚洲一级二级在线| 免费观看日韩电影| 国产福利一区二区三区在线视频| 国产精品123| 日本韩国欧美在线| 日韩精品一区二区在线观看| 久久久午夜精品| 亚洲精品国产成人久久av盗摄| 午夜精品福利视频网站| 国产麻豆成人精品| 99久久综合国产精品|