系统介绍:
1.MCU :STM32L151RDT6
2.时钟配置: 外部晶振12M ,PLL分频得到48M给SDIO适配器使用,PLL分频得到系统主时钟32M SDIO外设 PCLK2时钟32M
3.SD_CK上电初始化时400KHz,初始化完成后分频改成24MHz。
SD原理图:
问题:
SD卡上电初始化没有问题,能够读取卡的CID,块的大小等信息。在测试块写入数据时提示SD_TX_UNDERRUN 错误,也就是FIFO下溢错误。
我尝试减小时钟频率的话出现SD_DATA_CRC_FAIL错误,也就是数据块CRC错误。不知什么原因造成的。我是按照原子STM32F407SD卡的例子改的。
- SD_Error SD_WriteBlock(u8 *buf,long long addr, u16 blksize)
- {
- SD_Error errorstatus = SD_OK;
-
- u8 power=0,cardstate=0;
-
- u32 timeout=0,bytestransferred=0;
-
- u32 cardstatus=0,count=0,restwords=0;
-
- u32 tlen=blksize; //总长度
-
- u32*tempbuff=(u32*)buf;
-
- if(buf==NULL)return SD_INVALID_PARAMETER;//参数错误
-
- SDIO->DCTRL=0x0; //数据寄存器清零关DMA
-
- SDIO_DataInitStructure.SDIO_DataBlockSize= 0;//清除DPSM状态机配置
- SDIO_DataInitStructure.SDIO_DataLength= 0 ;
- SDIO_DataInitStructure.SDIO_DataTimeOut=SD_DATATIMEOUT ;
- SDIO_DataInitStructure.SDIO_DPSM=SDIO_DPSM_Enable;
- SDIO_DataInitStructure.SDIO_TransferDir=SDIO_TransferDir_ToCard;
- SDIO_DataInitStructure.SDIO_TransferMode=SDIO_TransferMode_Block;
- SDIO_DataConfig(&SDIO_DataInitStructure);
-
-
- if(SDIO->RESP1&SD_CARD_LOCKED)return SD_LOCK_UNLOCK_FAILED;//卡锁了
- if(CardType==SDIO_HIGH_CAPACITY_SD_CARD) //大容量卡
- {
- blksize=512;
- addr/=512;
- }
- if((blksize>0)&&(blksize<=2048)&&((blksize&(blksize-1))==0))
- {
- power=convert_from_bytes_to_power_of_two(blksize);
-
- SDIO_CmdInitStructure.SDIO_Argument = blksize;//发送CMD16+设置数据长度 blksize,短响应
- SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
- 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_SET_BLOCKLEN); //等待R1响应
-
- if(errorstatus!=SD_OK)return errorstatus; //这里返回SD_OK
-
- }else return SD_INVALID_PARAMETER;
-
- SDIO_CmdInitStructure.SDIO_Argument = (u32)RCA<<16;//发送CMD13,查询卡的状态,短响应
- SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_STATUS;
- 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_SEND_STATUS); //等待R1响应
-
- if(errorstatus!=SD_OK)return errorstatus; //这里返回SD_OK
- cardstatus=SDIO->RESP1;
- timeout=SD_DATATIMEOUT;
- while(((cardstatus&0x00000100)==0)&&(timeout>0)) //¼ì²éREADY_FOR_DATAλÊÇ·ñÖÃλ
- {
- timeout--;
-
- SDIO_CmdInitStructure.SDIO_Argument = (u32)RCA<<16;//发送CMD13,查询卡的状态,短响应
- SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_STATUS;
- 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_SEND_STATUS); //等待R1响应
-
- if(errorstatus!=SD_OK)return errorstatus;
-
- cardstatus=SDIO->RESP1;
- }
- if(timeout==0)return SD_ERROR;
- SDIO_CmdInitStructure.SDIO_Argument = addr;//发送CMD24,写单块指令,短响应
- SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK;
- 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_WRITE_SINGLE_BLOCK);//等待R1响应
-
- if(errorstatus!=SD_OK)return errorstatus;//这里反会SD_OK
-
- StopCondition=0; //单块写不需要发送停止传输指令
- SDIO_DataInitStructure.SDIO_DataBlockSize= power<<4; ; //blksize, 控制器到卡
- SDIO_DataInitStructure.SDIO_DataLength= blksize ;
- SDIO_DataInitStructure.SDIO_DataTimeOut=SD_DATATIMEOUT ;
- SDIO_DataInitStructure.SDIO_DPSM=SDIO_DPSM_Enable;
- SDIO_DataInitStructure.SDIO_TransferDir=SDIO_TransferDir_ToCard;
- SDIO_DataInitStructure.SDIO_TransferMode=SDIO_TransferMode_Block;
- SDIO_DataConfig(&SDIO_DataInitStructure);
- timeout=SDIO_DATATIMEOUT;
-
- if(errorstatus!=SD_OK)return errorstatus; //这里返回OK
复制代码
|
对于SD卡FIFO下溢错误 解决办法1.降低SD_CK的频率 2.开启硬件流控制。
对于SD_DATA_CRC_FAIL错误,我调试的时候先让板子用1线模式调试能够正确写进数据,改成4线模式就出现SD_DATA_CRC_FAIL错误,那问题就是配置4线的程序有问题。后来我使用了官网例程的配置4线模式函数,降低时钟频率,运行SD_OK了。
In computing, buffer underrun or buffer underflow is a state occurring when a buffer used to communicate between two devices or processes is fed with data at a lower speed than the data is being read from it. This requires the program or device reading from the buffer to pause its processing while the buffer refills. This can cause undesired and sometimes serious side effects, since the data being buffered is generally not suited to stop-start access of this kind.
既然是TX Underrun,你把发送的频率提高一些试试?
评分
查看全部评分
24Mhz已经是SD_CK的最大时钟了 我用407的板子调试是没问题的 是不是这块芯片的SDIO硬件有问题