OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7664|回复: 2

请教一下STM32有关FAT32格式SD卡的读写问题

[复制链接]

60

主题

153

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
369
金钱
369
注册时间
2013-12-23
在线时间
32 小时
发表于 2013-12-23 09:54:02 | 显示全部楼层 |阅读模式
刚入门STM32,在做一个SD卡的读写实现的功能,从网上下了不少资料,修改之后在我的开发板上运行f_mount成功,但是在open的时候总是返回FR_NOT_READY的错误,从原理图上看SD DI,SD DO, CLK和CS分别为PB15,PB14,PB13,PB12下面是部分代码:
/*-----------------------------------------------------------------------*/
/* Open or Create a File                                                 */
/*-----------------------------------------------------------------------*/

FRESULT f_open (
    FIL *fp,            /* Pointer to the blank file object */
    const TCHAR *path,    /* Pointer to the file name */
    BYTE mode            /* Access mode and file open mode flags */
)
{
    FRESULT res;
    DIR dj;
    BYTE *dir;
    DEF_NAMEBUF;
    fp->fs = 0;            /* Clear file object */
#if !_FS_READONLY
    mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
    res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ));     //此处已返回3  FR_NOT_READY
跟进到chk_mounted里面后发现此函数中只有这里return的是FR_NOT_READY

fs->fs_type = 0;                    /* Clear the file system object */
    fs->drv = LD2PD(vol);                /* Bind the logical drive and a physical drive */
    stat = disk_initialize(fs->drv);    /* Initialize low level disk I/O layer */
    printf("stat = %d", stat);     //stat返回1,if语句为true
    if (stat & STA_NOINIT)                /* Check if the initialization succeeded */
        return FR_NOT_READY;            /* Failed to initialize due to no media or hard error */
进入disk_initialize之后
    case 0 :
            Status = MSD0_Init();  //这里出现问题
            printf("##333## %d", Status);  //返回的值为1
            if(Status==0){
                return RES_OK;
            }else{
                return STA_NOINIT;    //返回1
            }
然后进入MSD0_Init
    /* Start send CMD0 till return 0x01 means in IDLE state */
    for(retry=0; retry<0xFFF; retry++)     //这里是超时后才退出的
    {
        r1 = MSD0_send_command(CMD0, 0, 0x95);
        if(r1 == 0x01)
        {
            printf("$$$  %d", r1);
            retry = 0;
            break;
        }
    }
进入MSD0_send_command后r1的值为1
int MSD0_send_command(uint8_t cmd, uint32_t arg, uint8_t crc)
{
  uint8_t r1;
  uint8_t retry;

  /* Dummy byte and chip enable */
  MSD0_spi_read_write(DUMMY_BYTE);
  //MSD0_spi_read_write(DUMMY_BYTE);
  MSD0_card_enable();

  /* Command, argument and crc */
  MSD0_spi_read_write(cmd | 0x40);
  MSD0_spi_read_write(arg >> 24);
  MSD0_spi_read_write(arg >> 16);
  MSD0_spi_read_write(arg >> 8);
  MSD0_spi_read_write(arg);
  MSD0_spi_read_write(crc);
 
  /* Wait response, quit till timeout */
  for(retry=0; retry<200; retry++)
  {
     r1 = MSD0_spi_read_write(DUMMY_BYTE);   //返回1
     if(r1 != 0xFF)
     {
         break;
     }
  }

  /* Chip disable and dummy byte */
  MSD0_card_disable();
  MSD0_spi_read_write(DUMMY_BYTE);
 //printf(".............................................  %d",r1);
  return r1;  //此处返回值是0
}
然后进入 MSD0_spi_read_write
__inline int MSD0_spi_read_write(uint8_t data)
{   
    uint8_t retry=0;
  /* Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
  {       
          retry++;      
        if(retry>200)
        {   
            //printf("###");
            return 0;
        }
  }
  /* Send byte through the SPI1 peripheral */
    SPI_I2S_SendData(SPI2, data);
    retry=0;
  /* Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
  {
          retry++;       
        if(retry>200)
        {   
            return 0;
        }
  }
  /* Return the byte read from the SPI1 bus */
  return SPI_I2S_ReceiveData(SPI2);
}
其中SPI_I2S_GetFlagStatus是这样的
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)
{
  FlagStatus bitstatus = RESET;
  /* Check the parameters*/
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
  assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG));
  /* Check the status of the specified SPI/I2S flag */
  if ((SPIx->SR & SPI_I2S_FLAG) != (uint16_t)RESET)
  {
    /* SPI_I2S_FLAG is set */
    bitstatus = SET;
  }
  else
  {
    /* SPI_I2S_FLAG is reset */
    bitstatus = RESET;
  }
  /* Return the SPI_I2S_FLAG status */
  return  bitstatus;    //此处返回的是0
}

我的SPI的配置是这样的
void MSD0_SPI_Configuration(void)
{       
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

  /* SPI2 Remap enable */     
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /*SPI2_SD_CS -> PB12 */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
     
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12GPIO_Pin_14;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  MSD0_card_disable();

  MSD0_SPIHighSpeed(0);       

  SPI_Cmd(SPI2, ENABLE);
}
我使用的是SPI2,请教原子和各位为什么会出现FR_NOT_READY的错误,不知道是我的SPI配置的不正确还是其他什么原因?

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

38

主题

2061

帖子

6

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3273
金钱
3273
注册时间
2012-1-16
在线时间
37 小时
发表于 2013-12-23 10:21:54 | 显示全部楼层
可以参考下战舰的代码。
站在巨人的肩膀上不断的前进。。。
回复 支持 反对

使用道具 举报

60

主题

153

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
369
金钱
369
注册时间
2013-12-23
在线时间
32 小时
 楼主| 发表于 2013-12-23 10:27:30 | 显示全部楼层
谢谢,刚刚找到问题所在因为用的是SPI2,所以RCC_APB2PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);要改成RCC_APB1PeriphClockCmd
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-13 19:19

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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