This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430FR2633:在使用 SPI 模式为 Micro SDHC 发出 CMD0后、仅获取0xFF 作为响应。

Guru**** 2534260 points
Other Parts Discussed in Thread: MSP430F169, MSP430FR2633, MSP430F149

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/839591/msp430fr2633-only-getting-0xff-as-response-after-issuing-cmd0-for-micro-sdhc-using-spi-mode

器件型号:MSP430FR2633
主题中讨论的其他器件:CSDMSP430F169MSP430F149

我正在尝试初始化 SD 卡、以便我可以向其写入一些可以在以后读取的数据。 我不需要任何特殊的文件系统、因为我只向卡写入无符号字符。 我附上以下相关代码:

头文件定义:


#define CS (P3DIR |= BIT1)//将 CS 设置为输出
#define CS_H (P3OUT |= BIT1)//将 CS 设置为非活动(低电平有效)
#define CS_L (P3OUT |=~BIT1)//将 CS 设置为有效(低电平有效)
#define TX UCA1TXBUF //Tx 缓冲器
#define RX UCA1RXBUF //Rx 缓冲器
#define TX_READY (UCA1IFG & 0x0002)//忙时为0,就绪时为1
#define RX_READY (UCA1IFG & 0x0001)//空时为0、满时为1
#define SPI_SEND (x) UCA1TXBUF = x

//宏定义
#define HIGH (A)(((A>>>8)&0xFF)// Word 中的高字节
#define LOW (A)(A&0xFF)//字的低字节


#define 虚拟0xFF

//命令48位:[47]:起始(0);[46]:TX 位(1);[45:40] CMD 索引;[39:8]参数;[7:1] CRC7;[0]:结束(1)
#define GO_IDLE_STATE 0x40 //重置 SD 存储卡(CMD0)
#define SEND_OP_COND 0x41 //发送主机容量支持信息并激活卡的初始化过程(CMD1)
#define SWITCH_FUNE 0x46 //检查可切换功能(模式0)和切换卡功能(模式1)(CMD6)
#define SEND_IF_COND 0x48 //发送包含主机电源电压信息的 SD 存储卡接口条件,并询问存取的卡是否在该范围内运行(CMD8)
#define SEND_CSD 0x49 //要求所选卡发送其特定于卡的数据(CSD)(CMD9)
#define SEND_CID 0x4A //要求所选卡发送其卡 ID (CID)(CMD10)
#define STOP_TRANS 0x4C //强制卡在多块读取操作(CMD12)中停止传输
#define SEND_STATUS 0x4D //要求所选卡发送其状态寄存器(CMD13)
#define SET_BLOCKLEN 0x50 //设置 LOCK_UNLOCK 命令的长度(块大小否则锁定为512字节)(CMD16)
#define READ_SINGLE_LOCK 0x51 //读取大小为512字节的块(CMD17)
#define READ_MULT_blocks 0x52 //读取多个块 unil STOP_TRANS 命令问题(CMD18)
#define WRITE_BLOCK 0x58 //写入大小为512字节的块(CMD24)
#define WRITE_MULT_blocks 0x59 //在发出 STOP_TRANS 命令之前写入多个数据块(CMD25)
#define program_cSD 0x5B //对 CSD 的可编程位进行编程(CMD27)
#define ERASE_W_SA 0x60 //设置要擦除的第一个写入块的地址(CMD32)
#define ERASE_W_EA 0x61 //设置要擦除的最后一个写入块的地址(CMD33)
#define 擦除0x66 //擦除所有之前选择的写入块(CMD38)
#define LOCK_UNLOCK 0x6A //用于设置/重置密码或锁定/解锁卡。 传输的数据块包括所有命令详细信息。
//数据块锁定/未锁定的大小由 SET_BLOCKLEN (CMD42)设置
#define APP_CMD 0x77 //向卡定义下一个命令是 ACMD (CMD55)
#define GEN_CMD 0x78 //用于将数据块传输到卡或从卡获取数据块以用于通用/应用特定命令(CMD56)
#define READ_OCR 0x7A //读取卡的 OCR 寄存器,CCS 位被分配给 OCR[30]。 (CMD58)
#define CRC_ON_OFF 0x7B //打开或关闭 CRC 选项。 CRC 选项位中的"1"将开启该选项、"0"将关闭该选项(CMD59)

//特定于应用的命令(ACMD)、始终按 CMD55执行、设置与 CMD 相同

#define APP_SD_STATUS 0x4D //发送 SD 状态(ACMD13)
#define APP_NUM_W_BKS 0x56 //发送正确写入的(无错误)块的编号。 具有32位+ CRC 数据块的响应(ACMD22)
#define APP_SET_W_BLK_ER_N 0x57 //设置写入前要预擦除的写入块数量(用于更快的多块 WR 命令)(ACMD23)
#define APP_START_INIT 0x69 //发送主机容量支持信息并激活卡的初始化过程。 保留位应设置为"0"(ACMD41)
#define APP_SET_CLR_CARD_D 0x6A//Connect[1]/Disconnect [0]卡 CS (引脚1)上的50k Ω 上拉电阻器。 上拉电阻器可用于卡检测(ACMD42)
#define APP_SEND_SCR 0x73 //读取 SD 配置寄存器(SCR)

相关功能


void sd_Send_Cmd (const char cmd、unsigned long 数据、const char CRC)

unsigned char frame[6];
字符温度;
int i;
FRAME[0]=(CMD|0x40);
for (i = 3;i >=0;i---)

temp =(char)(data>>>(8*I));
FRAME[4-I]=(温度);

帧[5]= CRC;

SD_Send_SPI_Frame (帧、6);

unsigned char getResponse()

int i = 0;

unsigned char 响应;

while (i <= 25000)

响应= SD_Send_SPI_Char (虚拟);
if (RESPONSE == 0x00) break;
if (RESPONSE == 0x01) break;
i++;

退货响应;

空 SD_Card_Init()

CSCTL5 |= 0x0003 | 0x0030;//MCLK 和 SMCLK 因 SD 卡功能而减少
CS_H;//在加电期间将 CS 设置为 OFF (至少74个时钟周期)
unsigned int i;
for (i = 0;i <= 9;i++)

SD_Send_SPI_Char (虚拟);//8位* 10 = 80个时钟周期

goIdle();

CSCTL5 &=~(0x0003)|(0x0030);//将时钟恢复到所需速度  



unsigned char goIdle()

无符号字符响应= 0x01;
CS_L;
SD_Send_Cmd (GO_IDLE_STATE、0、0x95);
if (getResponse()!= 0x01)

退货(2);

while (响应= 0x01)

CS_H;
SD_Send_SPI_Char (虚拟);
CS_L;
SD_Send_Cmd (SEND_OP_COND、0x00、0xff);
响应= getResponse();

CS_H;
SD_Send_SPI_Char (虚拟);
返回(1);

unsigned char sd_Send_SPI_Char (unsigned char x)

while (TX_READY = 0);//等待 TXBuffer 变为 Free
SPI_SEND (x);
while (RX_READY = 0);//等待接收数据
返回(RX);

unsigned long SD_Send_SPI_Frame (unsigned char* pbuffer、unsigned int SZ)

unsigned int i;
对于(I = 0;I < SZ;I++)

while (TX_READY = 0);
SPI_SEND (pbuffer[i]);
while (RX_READY = 0);
pbuffer[i]= RX;

返回(0);


主函数



void main (void)


WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器

//根据 MCLK 的器件数据表的要求配置一个 FRAM 等待状态
//在配置时钟系统之前在8MHz 以上运行。
FRCTL0 = FRCTLPW | NWAITS_1;

_bis_SR_register (SCG0);//禁用 FLL
CSCTL3 |= SELREF_REFOCLK;//将 REFO 设置为 FLL 基准源
CSCTL0 = 0;//清除 DCO 和 MOD 寄存器
CSCTL1 &=~(DCORSEL_7);//首先清除 DCO 频率选择位
CSCTL1 |= DCORSEL_5;//设置 DCO = 16MHz
CSCTL2 = FLLD_0 + 487;// DCOCLKDIV = 16MHz
_DELAY_CYCLES (3);
_BIC_SR_register (SCG0);//启用 FLL
while (CSCTL7 &(FLLUNLOCK0 | FLLUNLOCK1));// FLL 锁定

CSCTL4 = SELMS_DCOCLKDIV | SELA_REFOCLK;//将默认 REFO (~32768Hz)设置为 ACLK 源、ACLK = 32768Hz
//默认 DCOCLKDIV 为 MCLK 和 SMCLK 源
CSCTL5 |= 0x0003 | 0x0030;//MCLK 和 SMCLK 因 SD 卡功能而减少

P1DIR |= BIT7;//将 MCLK 设置为输出
SDI;
SCLK;
Lat;//初始

//开始 SPI 设置

P2SEL0 |= BIT4 | BIT5 | BIT6;//设置 CLK、SOMI、MOSI (UCA1)
P3SEL0 |= BIT1;//设置 GPIO 作为 CS

UCA0CTLW0 |= UCSWRST;

UCA1CTLW0 |= UCMST|UCSYNC|UCCKPL|UCMSB|UCSTEM;

UCA1CTLW0 |= UCSSEL_SMCLK;

UCA1BR0 = 0x01;
UCA1BR1 = 0;
UCA1MCTLW = 0;
UCA1CTLW0 &=~UCSWRST;
UCA1IE |= UCRXIE | UCTXIE;


PM5CTL0 &=~LOCKLPM5;//禁用 GPIO 上电默认高阻抗模式
//激活先前配置的端口设置
FC1_write (7、511、511、511);
P1SEL1 |= BIT7;//将 MCLK 引脚设置为第二功能->GCLK=16MHz
unsigned int ij;
for (ij = 0;ij < 16;ij++)

DATA[ij]= 0x11111111111111;//亮度设置

同时(1)//测试//14.88m

SD_Card_Init();

/*由于缺乏相关性而导致的其余代码剪切(以下代码已经过测试并正常工作)*/

 

 


我最初在不调整初始化周期时钟的情况下放入代码、并且我一直得到0xFF 用于响应。 我添加了在 SD 初始化期间将 SMCLK 降至~250kHz 的代码。 但是、我在响应线中一直得到0xFF。 我已经查看了 MSP430F169的 MMC/SD 卡示例代码、并认为我对 MSP430FR2633进行了必要的更改、但我一直遇到问题。

如果我尝试启动 SD 卡时才获得0xFF、那么对我为什么要获得0xFF 有任何帮助、将会非常有帮助!

在 Advanced 中感谢您的任何帮助!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Parker、

    您是否通过 SPI 总线确认 MSP430FR2633通过 SPI 正确发送数据?

    您对原始 MMC/SD 卡示例代码进行了哪些修改?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    当我看到您对 CS_L 的定义错误时、我停止读取您的代码。 您需要&=。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Wei、


    我今天讨论了 SPI 总线、它似乎可以发送数据。  

    我对 MMC/SD 示例代码所做的唯一修改是更改端口/寄存器定义、以便代码能够支持 MSP430FR2633而不是 MSP430F149。  

    其他人指出、我以错误的方式清除 CS 引脚(我使用的是 y |=~x、而它应该是 y &=~x)。  

    我现在尝试示波 CS 引脚、但没有从 CS 引脚获得任何读数。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的、我现在看到了这一点、感谢您指出这一点。 它没有解决我的问题、但如果不被发现、会造成更多问题。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已经打开和关闭了 CS 引脚、但现在我从 CS 引脚获得了一个奇怪的读数。

    当它变为高电平时、它在560mV 时停止、然后当它变为低电平时、我获得-2.82V 的读数。 我不知道为什么在 CS 引脚上获得负电压。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已经多次编写了自己的 SD 例程、并不是太困难。 但细节确实很重要。 我的最新努力是针对使用其版本 SD 接口的 teensy 3.6。 但我在一段时间前做了一个可能具有教育意义的 SPI 版本:

    我注意到的另一件事是在 SPI 读取/写入代码中。 检查发送缓冲区是否为空是浪费了精力。 如果这是您访问 SPI 端口的唯一位置、它将始终为空。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Parker、

    您是否检查了 David 的最后一个回复?

    我假设您已经解决了您的问题、因为我已经听过您几天了。 因此、我想通过点击"TI 认为已解决"来暂时关闭该主题。 如果仍有问题、请随时答复。