查看: 4708|回复: 12

[求助] K40 使用SPI驱动SD卡驱动程序

[复制链接]

该用户从未签到

5

主题

28

帖子

0

注册会员

Rank: 2

积分
80
最后登录
2019-9-30
发表于 2016-1-19 15:17:20 | 显示全部楼层 |阅读模式
            大家好,因为一些原因,必须要使用SPI驱动SD卡,第一次使用SPI驱动SD卡,求助一些 参考程序……
我知道答案 目前已有12人回答
回复

使用道具 举报

该用户从未签到

124

主题

3600

帖子

0

金牌会员

Rank: 6Rank: 6

积分
5781
最后登录
1970-1-1
发表于 2016-1-19 15:46:52 | 显示全部楼层
回复 支持 反对

使用道具 举报

该用户从未签到

5

主题

28

帖子

0

注册会员

Rank: 2

积分
80
最后登录
2019-9-30
 楼主| 发表于 2016-1-19 16:28:30 | 显示全部楼层
KL26那个例程包官网已经没有了?
回复 支持 反对

使用道具 举报

该用户从未签到

124

主题

3600

帖子

0

金牌会员

Rank: 6Rank: 6

积分
5781
最后登录
1970-1-1
发表于 2016-1-20 10:33:01 | 显示全部楼层
erpengcui 发表于 2016-1-19 16:28
KL26那个例程包官网已经没有了?

那就用FRDM-KL25的吧,改一下都文件就好。
http://www.nxp.com/zh-Hans/produ ... 25Z?lang_cd=zh-Hans
回复 支持 反对

使用道具 举报

该用户从未签到

5

主题

28

帖子

0

注册会员

Rank: 2

积分
80
最后登录
2019-9-30
 楼主| 发表于 2016-1-22 10:11:07 | 显示全部楼层
我是使用在KDS下使用PE配置的SPI总线,来驱动的SD卡。SPI总线配置的master模式,波特率是375K,其中SPI读写都可以成功,但是发送SD卡命令失败,无法初始化SD卡。
下面我贴出来修改的几个代码,请大家帮我看看,是不是这上面的原因啊。
uint8_t SD_SPI_ReadWriteByte(uint8_t data)
{
        dspi_status_t dspiResult;
        uint8_t tx[1];
        uint8_t rx[1];

        uint32_t wordsTransfer = 0;

        tx[0] = data;

        // Send the data.
        dspiResult = DSPI_DRV_MasterTransfer(dspiCom1_IDX, NULL, tx, NULL, 1);

        if (dspiResult != kStatus_DSPI_Success)
        {
                PRINTF("\r\nERROR: send data error \r\n");
                return;
        }
        // Wait until the transfer is complete.
        while (DSPI_DRV_MasterGetTransferStatus(dspiCom1_IDX, &wordsTransfer) == kStatus_DSPI_Busy)
         {}
        // Wait until slave is ready to send.
        OSA_TimeDelay(100);

        // Receive the data.
        dspiResult = DSPI_DRV_MasterTransfer(dspiCom1_IDX, NULL, NULL, rx, 1);
        if (dspiResult != kStatus_DSPI_Success)
        {
                PRINTF("\r\nERROR: receive data error \r\n");
                return;
        }
        // Wait until the transfer is complete.
        while (DSPI_DRV_MasterGetTransferStatus(dspiCom1_IDX, &wordsTransfer) == kStatus_DSPI_Busy)
        {}

    return rx[0];
}          

void SD_SPI_Init(void)
{
    //设置硬件上与SD卡相关联的控制引脚输出
        //禁止其他外设(NRF/W25Q64)对SD卡产生影响

        //RCC->APB2ENR|=1<<2;     //PORTA时钟使能
        //GPIOA->CRL&=0XFFF000FF;
        //GPIOA->CRL|=0X00033300;        //PA2.3.4 推挽
        //GPIOA->ODR|=0X7<<2;            //PA2.3.4上拉
        //SPI1_Init();
        //SD_CS=1;

        dspi_status_t dspiResult;
        dspiResult = DSPI_DRV_MasterInit(dspiCom1_IDX, &dspiCom1_MasterState, &dspiCom1_MasterConfig0);
        dspiResult = DSPI_DRV_MasterConfigureBus(dspiCom1_IDX, &dspiCom1_BusConfig0, &dspiCom1_calculatedBaudRate);
    DSPI_HAL_SetPcsStrobeCmd(SPI1_BASE_PTR, 0);
}

void SD_DisSelect(void)
{
        //SD_CS=1;
        DSPI_HAL_SetPcsStrobeCmd(SPI1_BASE_PTR, 0);
        SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
}
//选择sd卡,并且等待卡准备OK
//返回值:0,成功;1,失败;
uint8_t SD_Select(void)
{
        //SD_CS=0;
        DSPI_HAL_SetPcsStrobeCmd(SPI1_BASE_PTR,1);
        if(SD_WaitReady()==0)
                return 0;//等待成功
        SD_DisSelect();
            return 1;//等待失败
}
回复 支持 反对

使用道具 举报

该用户从未签到

5

主题

28

帖子

0

注册会员

Rank: 2

积分
80
最后登录
2019-9-30
 楼主| 发表于 2016-1-22 10:52:29 | 显示全部楼层
这上面的是可以正常进行的,
但是SD init老是失败,返回255
//初始化SD卡
uint8_t SD_Initialize(void)
{
        uint8_t r1;      // 存放SD卡的返回值
    uint16_t retry;  // 用来进行超时计数
    uint8_t buf[4];
        uint16_t i;

        SD_SPI_Init();                //初始化IO
        SD_SPI_SpeedLow();        //设置到低速模式
        for(i=0; i<10; i++)
                SD_SPI_ReadWriteByte(0XFF);//发送最少74个脉冲

        retry = 20;
        do
        {
                r1 = SD_SendCmd(CMD0, 0, 0x95);//进入IDLE状态
        }while((r1 != 0X01) && retry--);

        SD_Type = 0;//默认无卡
        if(r1 == 0X01)
        {
                if(SD_SendCmd(CMD8, 0x1AA, 0x87) == 1)//SD V2.0
                {
                        for(i = 0;i < 4; i++)
                                buf[i] = SD_SPI_ReadWriteByte(0XFF);        //Get trailing return value of R7 resp

                        if(buf[2] == 0X01&&buf[3] == 0XAA)//卡是否支持2.7~3.6V
                        {
                                retry=0XFFFE;
                                do
                                {
                                        SD_SendCmd(CMD55, 0, 0X01);        //发送CMD55
                                        r1 = SD_SendCmd(CMD41, 0x40000000, 0X01);//发送CMD41
                                }while(r1&&retry--);

                                if(retry&&SD_SendCmd(CMD58, 0, 0X01) == 0)//鉴别SD2.0卡版本开始
                                {
                                        for(i=0; i<4; i++)
                                                buf[i]=SD_SPI_ReadWriteByte(0XFF);//得到OCR值

                                        if(buf[0]&0x40)
                                                SD_Type = SD_TYPE_V2HC;    //检查CCS
                                        else
                                                SD_Type = SD_TYPE_V2;
                                 }
                          }
                }
                else//SD V1.x/ MMC        V3
                {
                        SD_SendCmd(CMD55, 0, 0X01);                //发送CMD55
                        r1=SD_SendCmd(CMD41, 0, 0X01);        //发送CMD41
                        if(r1 <= 1)
                        {               
                                SD_Type = SD_TYPE_V1;
                                retry = 0XFFFE;
                                do //等待退出IDLE模式
                                {
                                        SD_SendCmd(CMD55, 0, 0X01);        //发送CMD55
                                        r1 = SD_SendCmd(CMD41, 0, 0X01);//发送CMD41
                                 }while(r1&&retry--);
                         }
                         else//MMC卡不支持CMD55+CMD41识别
                         {
                                 SD_Type = SD_TYPE_MMC;//MMC V3
                                 retry = 0XFFFE;
                                 do //等待退出IDLE模式
                                 {
                                         r1 = SD_SendCmd(CMD1, 0, 0X01);//发送CMD1
                                 }while(r1&&retry--);
                          }

                         if(retry==0 || SD_SendCmd(CMD16, 512, 0X01) != 0)
                         SD_Type = SD_TYPE_ERR;//错误的卡
                  }
        }

        SD_DisSelect();//取消片选
        SD_SPI_SpeedHigh();//高速
        if(SD_Type)
                return 0;
        else if(r1)
                return r1;

        return 0xaa;//其他错误
}
回复 支持 反对

使用道具 举报

该用户从未签到

5

主题

28

帖子

0

注册会员

Rank: 2

积分
80
最后登录
2019-9-30
 楼主| 发表于 2016-1-22 10:56:20 | 显示全部楼层
有比较熟悉这块的可以帮我看看,调出来以后我一定把K40 SPI驱动SD卡这个驱动分享出来,供后面用到的人参考使用。
回复 支持 反对

使用道具 举报

该用户从未签到

5

主题

28

帖子

0

注册会员

Rank: 2

积分
80
最后登录
2019-9-30
 楼主| 发表于 2016-1-22 11:59:35 | 显示全部楼层
本帖最后由 erpengcui 于 2016-1-22 12:08 编辑

其中,
do
        {
                r1 = SD_SendCmd(CMD0, 0, 0x95);//进入IDLE状态
        }while((r1 != 0X01) && retry--);
这个地方,r1一直不是1,最后超时……有没有人遇到过相类似的问题啊?
回复 支持 反对

使用道具 举报

该用户从未签到

124

主题

3600

帖子

0

金牌会员

Rank: 6Rank: 6

积分
5781
最后登录
1970-1-1
发表于 2016-1-25 10:26:28 | 显示全部楼层
erpengcui 发表于 2016-1-22 11:59
其中,
do
        {

建议参考YL-KL26的SD SPI代码
https://www.nxpic.org.cn/module/forum/thread-597356-1-1.html
回复 支持 反对

使用道具 举报

该用户从未签到

5

主题

28

帖子

0

注册会员

Rank: 2

积分
80
最后登录
2019-9-30
 楼主| 发表于 2016-1-27 10:54:54 | 显示全部楼层
FSL_TICS_ZP 发表于 2016-1-25 10:26
建议参考YL-KL26的SD SPI代码
https://www.nxpic.org.cn/module/forum/thread-597356-1-1.html

我是在kds下,直接用PE配置的SPI,和使用SDK里面的驱动来做的SPI相关操作, 复位SD时,SPI发送数据示波器可以量到的,就是量不到SD卡的输出
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2025-9-6 15:01 , Processed in 0.111171 second(s), 30 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表