1523|0

3836

帖子

19

TA的资源

纯净的硅(中级)

楼主
 

MSP430F5438A的MSP430 SD卡SPI读写操作 [复制链接]

本节提供了MSP430F5438A SPI读写SD卡的示例代码,使用官方函数库msp430_driverlib_2_60_00_02,使用IAR for msp430 6.3通过编译。


本节代码未对SD卡进行区分,因此只针对SDHC卡进行操作,程序在金士顿 8GB SDHC microSD卡经过验证可以正常运行。


sdhc.h

#ifndef _SDHC_H_
#define _SDHC_H_
 
#define SDHC_INIT_CLK 125000
#define SDHC_HIGH_CLK 3125000
#define SDHC_CS_PORT GPIO_PORT_P9
#define SDHC_CS_PIN  GPIO_PIN0
 
#define CMD0    0   /* GO_IDLE_STATE */  
#define CMD55   55  /* APP_CMD */  
#define ACMD41  41  /* SEND_OP_COND (ACMD) */  
#define CMD1    1   /* SEND_OP_COND */  
#define CMD17   17  /* READ_SINGLE_BLOCK */  
#define CMD8    8   /* SEND_IF_COND */  
#define CMD18   18  /* READ_MULTIPLE_BLOCK */  
#define CMD12   12  /* STOP_TRANSMISSION */  
#define CMD24   24  /* WRITE_BLOCK */  
#define CMD25   25  /* WRITE_MULTIPLE_BLOCK */  
#define CMD13   13  /* SEND_STATUS */  
#define CMD9    9   /* SEND_CSD */  
#define CMD10   10  /* SEND_CID */  
 
void SDHC_csInit(void);
void SDHC_csEnable(void);
void SDHC_csDisable(void);
void SDHC_spiInit(void);
void SDHC_spiEnable(void);
void SDHC_spiDisable(void);
uint8_t SDHC_writeByte(uint8_t data);
uint8_t SDHC_sendCmd(const uint8_t cmd,uint32_t arg,const uint8_t crc);
bool SDHC_reset(void);
bool SDHC_init(void);
bool SDHC_checkBusy(void);
bool SDHC_readBlock(uint32_t addr,uint8_t *buffer);
bool SDHC_writeBlock(uint32_t addr,uint8_t *buffer);
bool SDHC_readMultiBlock(uint32_t addr,uint8_t block_num,uint8_t *buffer);
bool SDHC_writeMultiBlock(uint32_t addr,uint8_t block_num,uint8_t *buffer);
#endif

sdhc.c
#include "driverlib.h"
#include "sdhc.h"
 
void SDHC_csInit(void)
{
  GPIO_setAsOutputPin(SDHC_CS_PORT,SDHC_CS_PIN);
}
 
void SDHC_csEnable(void)
{
  GPIO_setOutputLowOnPin(SDHC_CS_PORT,SDHC_CS_PIN);
}
 
void SDHC_csDisable(void)
{
  GPIO_setOutputHighOnPin(SDHC_CS_PORT,SDHC_CS_PIN);
  SDHC_writeByte(0xFF);
}
 
void SDHC_spiInit(void)
{
  GPIO_setAsPeripheralModuleFunctionInputPin(
     GPIO_PORT_P9,
     GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN3
  );
   
  //Initialize Master
  USCI_B_SPI_initMasterParam param = {0};
  param.selectClockSource = USCI_B_SPI_CLOCKSOURCE_SMCLK;
  param.clockSourceFrequency = UCS_getSMCLK();
  param.desiredSpiClock = SDHC_INIT_CLK;
  param.msbFirst = USCI_B_SPI_MSB_FIRST;
  param.clockPhase = USCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT;
  param.clockPolarity = USCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH;
  USCI_B_SPI_initMaster(USCI_B2_BASE, ¶m);
}
 
void SDHC_spiEnable(void)
{
  USCI_B_SPI_enable(USCI_B2_BASE);
}
 
void SDHC_spiDisable(void)
{
  USCI_B_SPI_disable(USCI_B2_BASE);
}
 
uint8_t SDHC_writeByte(uint8_t data)
{
  USCI_B_SPI_transmitData(USCI_B2_BASE,data);
  while(USCI_B_SPI_isBusy(USCI_B2_BASE));
  data = USCI_B_SPI_receiveData(USCI_B2_BASE);
  return data;
}
 
uint8_t SDHC_getResponse(void)
{
  uint8_t retrytime = 0;
  uint8_t response;
   
  while(retrytime <= 240)
  {
    response = SDHC_writeByte(0xFF);
    if(response == 0x00) break;
    if(response == 0x01) break;
    if(response == 0xFE) break;
    retrytime++;
  }
  return response;
}
 
uint8_t SDHC_sendCmd(const uint8_t cmd,uint32_t arg,const uint8_t crc)
{
  uint8_t rec;
  SDHC_writeByte((cmd & 0x3F) | 0x40);
  SDHC_writeByte(arg >> 24);
  SDHC_writeByte(arg >> 16);
  SDHC_writeByte(arg >> 8);
  SDHC_writeByte(arg);
  SDHC_writeByte(crc);
  rec = SDHC_getResponse(); 
  return rec;
}
 
bool SDHC_reset(void)
{
  uint8_t  i,rec;
  SDHC_csDisable(); //PULL HIGH CS
   
  for(i = 0;i < 16;i++)
  {
    SDHC_writeByte(0xFF);
  } //send 128 clocks for normal voltage and sync
   
  SDHC_csEnable(); //PULL LOW CS
   
  rec = SDHC_sendCmd(CMD0,0,0x95);
   
  SDHC_csDisable();
   
  if(rec != 0x01)
  {
    return false;
  }
  return true;
}
 
bool SDHC_init(void)
{
  uint8_t rec;
  uint16_t retrytime = 0;
   
  SDHC_csEnable();
   
  rec = SDHC_sendCmd(CMD8,0x1AA,0x87);
   
  if(rec != 0x01)
  {
    //SD card not support ver2.0 or later
    SDHC_csDisable();
    return false;
  }
   
  rec = SDHC_writeByte(0xFF);
  rec = SDHC_writeByte(0xFF);
  rec = SDHC_writeByte(0xFF);
  rec = SDHC_writeByte(0xFF);
   
  if(rec != 0xAA)
  {
    SDHC_csDisable();
    return false;
  }
  do
  { 
    do
    {
      rec = SDHC_sendCmd(CMD55,0,0xff);
      retrytime++;
    }while(rec != 0x01 && retrytime < 200);
    if(retrytime >= 200)
    {
      SDHC_csDisable();
      return false;
    }
    rec = SDHC_sendCmd(ACMD41,0x40000000,0xFF);
    retrytime++;
  }while(rec != 0x00 && retrytime < 200);
  if(retrytime >= 200)
  {
    SDHC_csDisable();
    return false;
  }
  SDHC_csDisable();
  //SPI HIGH SPEED
  USCI_B_SPI_changeMasterClockParam clockparam = {0};
  clockparam.clockSourceFrequency = UCS_getSMCLK();
  clockparam.desiredSpiClock = SDHC_HIGH_CLK;
  USCI_B_SPI_changeMasterClock(USCI_B2_BASE, &clockparam);
  return true;
}
 
bool SDHC_checkBusy(void)
{
  uint16_t i = 0,response;
  bool rvalue = false;
  while(i <= 240)
  {
    response = SDHC_writeByte(0xFF);
    response = response & 0x1F;
    if(response == 0x05) {rvalue = true; break;}
    i++;
  }
  i = 0;
  do
  {
    response = SDHC_writeByte(0xFF);
    i++;
    if(i >= 65000)
    {
      rvalue = false;
      break;
    }
  }while(response == 0x00);
  return rvalue;
}
 
bool SDHC_readBlock(uint32_t addr,uint8_t *buffer)
{
  uint8_t rec;
  uint16_t i;
  SDHC_csEnable();
   
  rec = SDHC_sendCmd(CMD17,addr,0x55);
  if(rec != 0x00)
  {
    SDHC_csDisable();
    return false;
  }
   
  rec = SDHC_getResponse();
  if(rec != 0xFE)
  {
    SDHC_csDisable();
    return false;
  }
   
  for(i = 0; i < 512;i++)
  {
    *buffer ++ = SDHC_writeByte(0xFF);
  }
  SDHC_writeByte(0xFF);
  SDHC_writeByte(0xFF);
   
  SDHC_csDisable();
  return true;
}
 
bool SDHC_writeBlock(uint32_t addr,uint8_t *buffer)
{
  uint8_t rec;
  uint16_t i;
  bool rvalue = true;
  SDHC_csEnable();
   
  rec = SDHC_sendCmd(CMD24,addr,0xFF);
  if(rec != 0x00)
  {
    SDHC_csDisable();
    return false;
  }
   
  SDHC_writeByte(0xFE);
  for(i = 0; i < 512;i++)
  {
    SDHC_writeByte(*buffer ++);
  }
  SDHC_writeByte(0xFF);
  SDHC_writeByte(0xFF);
   
  rvalue = SDHC_checkBusy();
  SDHC_csDisable();
  return rvalue;
}
 
bool SDHC_readMultiBlock(uint32_t addr,uint8_t block_num,uint8_t *buffer)
{
  uint8_t rec;
  uint16_t i;
  SDHC_csEnable();
   
  rec = SDHC_sendCmd(CMD18,addr,0xFF);
  if(rec != 0x00)
  {
    SDHC_csDisable();
    return false;
  }
   
  do
  {
    rec = SDHC_getResponse();
    if(rec != 0xFE)
    {
      SDHC_csDisable();
      return false;
    }
     
    for(i = 0; i < 512;i++)
    {
      *buffer ++ = SDHC_writeByte(0xFF);
    }
    SDHC_writeByte(0xFF);
    SDHC_writeByte(0xFF);
  }while(-- block_num);
   
  rec = SDHC_sendCmd(CMD12,0,0xFF);
  SDHC_csDisable();
  return true;
}
 
bool SDHC_writeMultiBlock(uint32_t addr,uint8_t block_num,uint8_t *buffer)
{
  uint8_t rec;
  uint16_t i;
  bool rvalue = true;
  SDHC_csEnable();
   
  rec = SDHC_sendCmd(CMD25,addr,0xFF);
  if(rec != 0x00)
  {
    SDHC_csDisable();
    return false;
  }
   
  do
  {
    SDHC_writeByte(0xFC);
    for(i = 0; i < 512;i++)
    {
      SDHC_writeByte(*buffer ++);
    }
    SDHC_writeByte(0xFF);
    SDHC_writeByte(0xFF);
     
    rvalue = SDHC_checkBusy();
    if(!rvalue) break;
  }while(-- block_num);
   
  rec = SDHC_sendCmd(0xFD,0,0xFF);
  i = 0;
  do
  {
    rec = SDHC_writeByte(0xFF);
    i++;
    if(i >= 65000)
    {
      rvalue = false;
      break;
    }
  }while(rec == 0x00);
  SDHC_csDisable();
  return rvalue;
}

 

 
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
艾睿电子& Silicon Labs 有奖直播 | 全新蓝牙信道探测:从技术创新到实际应用
直播时间:3月12日(周三)上午10:00
直播奖励:多功能榨汁机、蓝牙音箱、手机支架

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表