收藏0 举报
/* * 函数名:SD_PowerON * 描述 :确保SD卡的工作电压和配置控制时钟 * 输入 :无 * 输出 :-SD_Error SD卡错误代码 * 成功时则为 SD_OK * 调用 :在 SD_Init() 调用 */ SD_Error SD_PowerON(void) { SD_Error errorstatus = SD_OK; uint32_t response = 0, count = 0, validvoltage = 0; uint32_t SDType = SD_STD_CAPACITY; /*!< Power ON Sequence -----------------------------------------------------*/ /*!< Configure the SDIO peripheral */ /*!< SDIOCLK = HCLK, SDIO_CK = HCLK/(2 + SDIO_INIT_CLK_DIV) */ /*!< on STM32F2xx devices, SDIOCLK is fixed to 48MHz */ /*!< SDIO_CK for initialization should not exceed 400 KHz */ /*初始化时的时钟不能大于400KHz*/ SDIO_InitStructure.SDIO_ClockDiv = SDIO_INIT_CLK_DIV; /* HCLK = 72MHz, SDIOCLK = 72MHz, SDIO_CK = HCLK/(178 + 2) = 400 KHz */ SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising; SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable; //不使用bypass模式,直接用HCLK进行分频得到SDIO_CK SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable; // 空闲时不关闭时钟电源 SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b; //1位数据线 SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;//硬件流 SDIO_Init(&SDIO_InitStructure); /*!< Set Power State to ON */ SDIO_SetPowerState(SDIO_PowerState_ON); /*!< Enable SDIO Clock */ SDIO_ClockCmd(ENABLE); /*下面发送一系列命令,开始卡识别流程*/ /*!< CMD0: GO_IDLE_STATE ---------------------------------------------------*/ /*!< No CMD response required */ SDIO_CmdInitStructure.SDIO_Argument = 0x0; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_GO_IDLE_STATE; //cmd0 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_No; //无响应 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; //则CPSM在开始发送命令之前等待数据传输结束。 SDIO_SendCommand(&SDIO_CmdInitStructure); //写命令进命令寄存器 errorstatus = CmdError();//检测是否正确接收到cmd0 if (errorstatus != SD_OK) //命令发送出错,返回 { /*!< CMD Response TimeOut (wait for CMDSENT flag) */ return(errorstatus); } /*!< CMD8: SEND_IF_COND ----------------------------------------------------*/ /*!< Send CMD8 to verify SD card interface operating condition */ /*!< Argument: - [31:12]: Reserved (shall be set to '0') - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V) - [7:0]: Check Pattern (recommended 0xAA) */ /*!< CMD Response: R7 */ SDIO_CmdInitStructure.SDIO_Argument = SD_CHECK_PATTERN; //接收到命令sd会返回这个参数 SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_SEND_IF_COND; //cmd8 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; //r7 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; //关闭等待中断 SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); /*检查是否接收到命令*/ errorstatus = CmdResp7Error(); if (errorstatus == SD_OK) //有响应则card遵循sd协议2.0版本 { CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; /*!< SD Card 2.0 ,先把它定义会sdsc类型的卡*/ SDType = SD_HIGH_CAPACITY; //这个变量用作acmd41的参数,用来询问是sdsc卡还是sdhc卡 } else //无响应,说明是1.x的或mmc的卡 { /*!< CMD55 */ SDIO_CmdInitStructure.SDIO_Argument = 0x00; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_APP_CMD); } /*!< CMD55 */ //为什么在else里和else外面都要发送CMD55? //发送cmd55,用于检测是sd卡还是mmc卡,或是不支持的卡 SDIO_CmdInitStructure.SDIO_Argument = 0x00; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; //r1 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_APP_CMD); //是否响应,没响应的是mmc或不支持的卡 /*!< If errorstatus is Command TimeOut, it is a MMC card */ /*!< If errorstatus is SD_OK it is a SD card: SD card 2.0 (voltage range mismatch) or SD card 1.x */ if (errorstatus == SD_OK) //响应了cmd55,是sd卡,可能为1.x,可能为2.0 { /*下面开始循环地发送sdio支持的电压范围,循环一定次数*/ /*!< SD CARD */ /*!< Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */ while ((!validvoltage) && (count < SD_MAX_VOLT_TRIAL)) { //因为下面要用到ACMD41,是ACMD命令,在发送ACMD命令前都要先向卡发送CMD55 /*!< SEND CMD55 APP_CMD with RCA as 0 */ SDIO_CmdInitStructure.SDIO_Argument = 0x00; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; //CMD55 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_APP_CMD); //检测响应 if (errorstatus != SD_OK) { return(errorstatus);//没响应CMD55,返回 } //acmd41,命令参数由支持的电压范围及HCS位组成,HCS位置一来区分卡是SDSc还是sdhc SDIO_CmdInitStructure.SDIO_Argument = SD_VOLTAGE_WINDOW_SD | SDType; //参数为主机可供电压范围及hcs位 SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_APP_OP_COND; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; //r3 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp3Error(); //检测是否正确接收到数据 if (errorstatus != SD_OK) { return(errorstatus); //没正确接收到acmd41,出错,返回 } /*若卡需求电压在SDIO的供电电压范围内,会自动上电并标志pwr_up位*/ response = SDIO_GetResponse(SDIO_RESP1); //读取卡寄存器,卡状态 validvoltage = (((response >> 31) == 1) ? 1 : 0); //读取卡的ocr寄存器的pwr_up位,看是否已工作在正常电压 count++; //计算循环次数 } if (count >= SD_MAX_VOLT_TRIAL) //循环检测超过一定次数还没上电 { errorstatus = SD_INVALID_VOLTRANGE; //SDIO不支持card的供电电压 return(errorstatus); } /*检查卡返回信息中的HCS位*/ if (response &= SD_HIGH_CAPACITY) //判断ocr中的ccs位 ,如果是sdsc卡则不执行下面的语句 { CardType = SDIO_HIGH_CAPACITY_SD_CARD; //把卡类型从初始化的sdsc型改为sdhc型 } }/*!< else MMC Card */ return(errorstatus); }
/* * 函数名:SD_InitializeCards * 描述 :初始化所有的卡或者单个卡进入就绪状态 * 输入 :无 * 输出 :-SD_Error SD卡错误代码 * 成功时则为 SD_OK * 调用 :在 SD_Init() 调用,在调用power_on()上电卡识别完毕后,调用此函数进**初始化 */ SD_Error SD_InitializeCards(void) { SD_Error errorstatus = SD_OK; uint16_t rca = 0x01; if (SDIO_GetPowerState() == SDIO_PowerState_OFF) { errorstatus = SD_REQUEST_NOT_APPLICABLE; return(errorstatus); } if (SDIO_SECURE_DIGITAL_IO_CARD != CardType)//判断卡的类型 { /*!< Send CMD2 ALL_SEND_CID */ SDIO_CmdInitStructure.SDIO_Argument = 0x0; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ALL_SEND_CID; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp2Error(); if (SD_OK != errorstatus) { return(errorstatus); } CID_Tab[0] = SDIO_GetResponse(SDIO_RESP1); CID_Tab[1] = SDIO_GetResponse(SDIO_RESP2); CID_Tab[2] = SDIO_GetResponse(SDIO_RESP3); CID_Tab[3] = SDIO_GetResponse(SDIO_RESP4); } /*下面开始SD卡初始化流程*/ if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_SECURE_DIGITAL_IO_COMBO_CARD == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType)) //使用的是2.0的卡 { /*!< Send CMD3 SET_REL_ADDR with argument 0 */ /*!< SD Card publishes its RCA. */ SDIO_CmdInitStructure.SDIO_Argument = 0x00; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_REL_ADDR; //cmd3 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; //r6 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp6Error(SD_CMD_SET_REL_ADDR, &rca); //把接收到的卡相对地址存起来。 if (SD_OK != errorstatus) { return(errorstatus); } } if (SDIO_SECURE_DIGITAL_IO_CARD != CardType) { RCA = rca; /*!< Send CMD9 SEND_CSD with argument as card's RCA */ SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)(rca << 16); SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_CSD; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp2Error(); if (SD_OK != errorstatus) { return(errorstatus); } CSD_Tab[0] = SDIO_GetResponse(SDIO_RESP1); CSD_Tab[1] = SDIO_GetResponse(SDIO_RESP2); CSD_Tab[2] = SDIO_GetResponse(SDIO_RESP3); CSD_Tab[3] = SDIO_GetResponse(SDIO_RESP4); } errorstatus = SD_OK; /*!< All cards get intialized */ return(errorstatus); }
本版积分规则 发表回复 回帖并转播 回帖后跳转到最后一页
扫码关注 21ic 官方微信
扫码关注嵌入式微处理器
扫码关注电源系统设计
扫码关注21ic项目外包
扫码浏览21ic手机版
本站介绍 | 申请友情链接 | 欢迎投稿 | 隐私声明 | 广告业务 | 网站地图 | 联系我们 | 诚聘英才
京公网安备 11010802024343号