📄 mmc.c
字号:
#include <MSP430x16x.h>
#include "mmc.h"
//函数定义
void CS_LOW(void);
void CS_HIGH(void);
char mmcGetResponse(void);
char mmcGetXXResponse(const char resp);
char mmcCheckBusy(void);
void initSPI (void);
unsigned char spiSendByte(const unsigned char data);
char mmc_GoIdle();
// 全局变量
char mmc_buffer[512] = { 0 };
void CS_LOW(void)
{
P5OUT &= ~0x10;
return;
}
void CS_HIGH(void)
{
P5OUT |= 0x10;
return;
}
void initSPI (void)
{
//8位SPI主模式
UCTL1 = SWRST;
//时钟源为SMCLK,3线模式,上升沿数据有效
UTCTL1 = CKPH | SSEL1 | SSEL0 | STC;
//设置时钟频率,0x02: UCLK/2 (4 MHz)
UBR01 = 0x02;
UBR11 = 0x00;
//没有调整
UMCTL1 = 0x00;
//8位SPI主模式
UCTL1 = CHAR | SYNC | MM | SWRST;
//清除SWRST
UCTL1 &= ~SWRST;
//使能USART1的SPI模式
ME2 |= USPIE1;
//清除发送中断标志
while (!(IFG2 & UTXIFG1));
}
char initMMC (void)
{
int i;
//P5.1,P5.2,P5.3设置为SPI管脚
P5SEL |= 0x0E;
P5SEL &= ~0x11;
//P5.4输出高电平
P5OUT |= 0x10;
//P5.1,P5.3,P5.4为输出方向
P5DIR |= 0x1A;
//初始化SPI
initSPI();
//CS为高电平
CS_HIGH();
for(i = 0;i <= 9;i++)
{
spiSendByte(0xff);
}
//发送复位信号
return (mmc_GoIdle());
}
char mmc_GoIdle()
{
char response=0x01;
CS_LOW();
//发送复位命令,将MMC卡设置为SPI模式
mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);
//等待响应
if(mmcGetResponse()!=0x01) return MMC_INIT_ERROR;
while(response == 0x01)
{
CS_HIGH();
spiSendByte(0xff);
CS_LOW();
mmcSendCmd(MMC_SEND_OP_COND,0x00,0xff);
response=mmcGetResponse();
}
CS_HIGH();
spiSendByte(0xff);
return (MMC_SUCCESS);
}
char mmcGetResponse(void)
{
int i=0;
char response;
while(i <= 64)
{
//读取响应数据
response=spiSendByte(0xff);
if(response == 0x00)break;
if(response == 0x01)break;
i++;
}
return response;
}
char mmcGetXXResponse(const char resp)
{
int i=0;
char response;
while(i<=1000)
{
//读取响应数据
response=spiSendByte(0xff);
//响应一致时,退出
if(response == resp) break;
i++;
}
return response;
}
char mmcCheckBusy(void)
{
int i=0;
char response;
char rvalue;
while(i <= 64)
{
response = spiSendByte(0xff);
response &= 0x1f;
switch(response)
{
case 0x05:
{
rvalue = MMC_SUCCESS;
break;
}
case 0x0b: return(MMC_CRC_ERROR);
case 0x0d: return(MMC_WRITE_ERROR);
default:
rvalue = MMC_OTHER_ERROR;
break;
}
if(rvalue == MMC_SUCCESS) break;
i++;
}
i=0;
do
{
response = spiSendByte(0xff);
i++;
} while(response == 0);
return response;
}
char mmcReadBlock(const unsigned long address,
const unsigned long count,
unsigned char *pBuffer)
{
unsigned long i = 0;
char rvalue = MMC_RESPONSE_ERROR;
//为读操作设置块的长度
if (mmcSetBlockLength (count) == MMC_SUCCESS)
{
//片选信号为低
CS_LOW ();
//发送读单块的命令
mmcSendCmd (MMC_READ_SINGLE_BLOCK,address, 0xFF);
//判断响应是否正确
if (mmcGetResponse() == 0x00)
{
//得到响应数据
if (mmcGetXXResponse(MMC_START_DATA_BLOCK_TOKEN)
== MMC_START_DATA_BLOCK_TOKEN)
{
//读出数据
for (i = 0; i < count; i++)
{
pBuffer[i] = spiSendByte(0xff);
}
//取出CRC数据,本软件中没有使用
spiSendByte(0xff);
spiSendByte(0xff);
//返回成功标志
rvalue = MMC_SUCCESS;
}
else
{
//没有收到响应数据
rvalue = MMC_DATA_TOKEN_ERROR;
}
}
else
{
//读命令错误
rvalue = MMC_RESPONSE_ERROR;
}
}
else
{
//块设置命令错误
rvalue = MMC_BLOCK_SET_ERROR;
}
CS_HIGH ();
spiSendByte(0xff);
return rvalue;
}
char mmcWriteBlock (const unsigned long address,
const unsigned long count,
unsigned char *pBuffer)
{
unsigned long i = 0;
char rvalue = MMC_RESPONSE_ERROR;
// 设置块的长度
if (mmcSetBlockLength (count) == MMC_SUCCESS)
{
//选通片选管脚
CS_LOW ();
//发送写命令
mmcSendCmd (MMC_WRITE_BLOCK,address, 0xFF);
//判断命令是否正确
if (mmcGetXXResponse(MMC_R1_RESPONSE) == MMC_R1_RESPONSE)
{
//发送数据标志数据的起始
spiSendByte(0xff);
//为数据的传输提供时钟
spiSendByte(0xfe);
//写入数据
for (i = 0; i < count; i++)
{
spiSendByte(pBuffer[i]);
}
//写入CRC数据,本软件没有使用
spiSendByte(0xff);
spiSendByte(0xff);
//判断状态
mmcCheckBusy();
rvalue = MMC_SUCCESS;
}
else
{
//写命令错误
rvalue = MMC_RESPONSE_ERROR;
}
}
else
{
//块设置错误
rvalue = MMC_BLOCK_SET_ERROR;
}
CS_HIGH ();
//发送8个延时脉冲
spiSendByte(0xff);
return rvalue;
}
void mmcSendCmd (const char cmd, unsigned long data, const char crc)
{
char frame[6];
char temp;
int i;
//封装命令数据
frame[0]=(cmd | 0x40);
for(i = 3;i >= 0;i--)
{
temp = (char)(data >> (8 * i));
frame[4-i] = (temp);
}
//CRC数据
frame[5] = (crc);
//发送命令数据
for(i = 0;i < 6;i++)
{
spiSendByte(frame[i]);
}
}
char mmcSetBlockLength (const unsigned long blocklength)
{
CS_LOW ();
//发送设置块长度命令
mmcSendCmd(MMC_SET_BLOCKLEN, blocklength, 0xFF);
//得到响应,判断是否是R1响应数据
if(mmcGetResponse()!=0x00)
{
//初始化MMC卡
initMMC();
//发送设置块长度命令
mmcSendCmd(MMC_SET_BLOCKLEN, blocklength, 0xFF);
//得到响应数据
mmcGetResponse();
}
CS_HIGH ();
//发送8个延时脉冲
spiSendByte(0xff);
return MMC_SUCCESS;
}
unsigned char spiSendByte(const unsigned char data)
{
//等待发送中断标志
while ((IFG2 & UTXIFG1) == 0) ;
//发送数据
TXBUF1 = data;
//等待接收中断标志
while ((IFG2 & URXIFG1) == 0) ;
//接收数据
return (RXBUF1);
}
char mmcReadRegister (const char cmd_register,
const unsigned char length,
unsigned char *pBuffer)
{
char uc = 0;
char rvalue = MMC_TIMEOUT_ERROR;
if (mmcSetBlockLength (length) == MMC_SUCCESS)
{
//选通片选管脚
CS_LOW ();
//发送命令数据,CRC没有使用,最后一个字节为0XFF
mmcSendCmd(cmd_register, 0x000000, 0xff);
//等待响应
if (mmcGetResponse() == 0x00)
{
if (mmcGetXXResponse(0xfe)== 0xfe)
{
//读出内容
for (uc = 0; uc < length; uc++)
pBuffer[uc] = spiSendByte(0xff);
}
//CRC数据,本软件没有使用
spiSendByte(0xff);
spiSendByte(0xff);
rvalue = MMC_SUCCESS;
}
else
rvalue = MMC_RESPONSE_ERROR;
//片选管脚拉高
CS_HIGH ();
//发送8个延时脉冲
spiSendByte(0xff);
}
CS_HIGH ();
return rvalue;
}
unsigned long MMC_ReadCardSize(void)
{
//读出CSD寄存器的内容
unsigned long MMC_CardSize;
unsigned short i,j,b;
unsigned short response;
unsigned short mmc_C_SIZE;
unsigned char mmc_READ_BL_LEN,mmc_C_SIZE_MULT;
CS_LOW ();
//发送命令
spiSendByte(MMC_READ_CSD);
//发送4个空数据
for(i = 4; i > 0; i--) spiSendByte(0);
//发送CRC数据
spiSendByte(0xFF);
//取出响应数据
response = mmcGetResponse();
b = spiSendByte(0xFF);
if(!response )
{
while (b != 0xFE) b = spiSendByte(0xFF);
//位127:87
for(j = 5; j > 0; j--) b = spiSendByte(0xff);
// 位84:80
b = spiSendByte(0xff);
mmc_READ_BL_LEN = b & 0x0F;
b = spiSendByte(0xff);
// 位 73:62 C_Size
mmc_C_SIZE = (b & 0x03) << 10;
b = spiSendByte(0xff);
mmc_C_SIZE += b << 2;
b = spiSendByte(0xff);
mmc_C_SIZE += b >> 6;
// 位 55:53
b = spiSendByte(0xff);
// 位 49:47
mmc_C_SIZE_MULT = (b & 0x03) << 1;
b = spiSendByte(0xff);
mmc_C_SIZE_MULT += b >> 7;
// 位 41:37
b = spiSendByte(0xff);
b = spiSendByte(0xff);
b = spiSendByte(0xff);
b = spiSendByte(0xff);
b = spiSendByte(0xff);
}
//主机保持4个字节的时钟
for(j=4; j>0; j--) b = spiSendByte(0xff);
b = spiSendByte(0xff);
CS_LOW ();
MMC_CardSize = (mmc_C_SIZE + 1);
//大小计算
for(i = 2,j = mmc_C_SIZE_MULT + 2; j > 1; j--)
{
i <<= 1;
}
MMC_CardSize *= i;
//大小计算
for(i = 2,j = mmc_READ_BL_LEN; j > 1; j--)
{
i <<= 1;
}
MMC_CardSize *= i;
return (MMC_CardSize);
}
char mmc_check(void)
{
if (!(P5IN & BIT0))
{
return (MMC_SUCCESS);
}
else
{
return (MMC_INIT_ERROR);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -