SD卡读写+1602显示.docx
《SD卡读写+1602显示.docx》由会员分享,可在线阅读,更多相关《SD卡读写+1602显示.docx(20页珍藏版)》请在冰豆网上搜索。
SD卡读写+1602显示
SD卡
读
写
程
序
#include
#include
#include
#include
#include"define.h"
#include"Lcd1602.c"
#include"SD.c"
//*************************************************************************
//头文件定义define.h
//*************************************************************************
#defineucharunsignedchar
#defineuintunsignedint
#defineulongunsignedlong
//******Lcd1602端口定义******
#defineDATAPORTP0//定义P0口为LCD通讯端口
sbitLCM_RS=P2^2;//数据/命令端
sbitLCM_RW=P2^3;//读/写选择端
sbitLCM_EN=P2^4;
ucharcodestr0[]={"SDcardinti..."};
ucharcodestr1[]={"intisucceed!
"};
ucharcodestr2[]={"intifail!
"};
uchari;
//unsignedcharxdatapbuf[512];//片外数据缓冲区
voidinitLCM(void);//LCD初始化子程序
voidWriteCommandLCM(uchardat);//写指令到ICM子函数
voidWriteDataLCM(uchardat);//写数据到LCM子函数
voidDisplayOneChar(ucharX,ucharY,ucharDData);//显示指定坐标的一个字符子函数
voidDisplayListChar(ucharX,ucharY,ucharcode*DData);//显示指定坐标的一串字符子函数
//******SD卡端口定义*******
sbitCS=P1^0;
sbitMOSI=P1^1;
sbitSCK=P1^2;
sbitMISO=P1^3;
bitInit_Flag;
#defineCS_SD_EN(CS=0)//为低时表示片选
#defineCS_SD_DIS(CS=1)//disable
#defineSCK_SD_LOW(SCK=0)//low
#defineSCK_SD_HIGH(SCK=1)//SCK=1
#defineSI_SD_LOW(MOSI=0)//(SI,SO均相对SSD)
#defineSI_SD_HIGH(MOSI=1)//MOSI=1
#defineINIT_CMD0_ERROR0x01
#defineINIT_CMD1_ERROR0x02
#defineWRITE_BLOCK_ERROR0x03
#defineREAD_BLOCK_ERROR0x04
sbitLED1=P3^0;
sbitLED2=P3^1;
sbitLED4=P3^4;
sbitLED5=P3^5;
sbitLED6=P3^6;
sbitLED7=P3^7;
ucharbuffer[20];
ucharcodenumber[512]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x40,0x41,
0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49};
/************************************************/
//函数名称:
main(void)
//功能:
主函数
//输入参数:
无
//输出参数:
无
//*************************************************
main()
{
LED1=1;
LED2=1;
LED4=1;
LED5=1;
LED6=1;
LED7=1;
initLCM();
DisplayListChar(0,0,str0);
while(MMC_Init())
{
DisplayListChar(0,1,str2);
}
DisplayListChar(0,1,str1);
SD_write_sector(0x80,number);//向扇区为80*16的地址写入数据
SD_read_sector(0x80,buffer);//从扇区80*16地址处读取数据
while
(1)
{
delay_LCM(500);
delay_LCM(500);
WriteCommandLCM(0x01);//清屏
delay_LCM(500);
delay_LCM(500);
for(i=0;i<20;i++)
{
if(i<16)
{
DisplayOneChar(i,0,buffer[i]);
}
elseDisplayOneChar(i,1,buffer[i]);
delay_LCM(200);
}
}
}
//************************
//调用子程序Lcd1602.c
//************************
/***************一微秒延时子程序******************/
//函数名称:
voiddelayus(uintdelay)
//功能:
延时一微妙
//输入参数:
uintdelay
//输出参数:
无
//*************************************************
voiddelayus(uintdelay)
{
while(delay--);
}
/***************一毫秒延时子程序******************/
//函数名称:
voiddelay_LCM(uintdelay)
//功能:
延时一毫秒
//输入参数:
uintdelay
//输出参数:
无
//*************************************************
voiddelay_LCM(uintdelay)
{
while(delay--)
delayus(149);
}
/**********写指令到LCD1602子函数****************/
//函数名称:
voidWriteCommandLCM(uchardata)
//功能:
写指令到LCM
//输入参数:
uchardata
//输出参数:
无
//************************************************
voidWriteCommandLCM(uchardat)
{
delay_LCM(5);//延时5MS
LCM_EN=0;
LCM_RS=0;//选中指令寄存器
LCM_RW=0;//写模式
_nop_();
LCM_EN=1;
DATAPORT=dat;
_nop_();
_nop_();
LCM_EN=0;
}
/**********写数据到LCD1602子函数************/
//函数名称:
voidWriteDataLCM(uchardata)
//功能:
写数据到LCD1602
//输入参数:
ucahrdata
//输出参数:
无
//*****************************************
voidWriteDataLCM(uchardat)
{
delay_LCM(5);//延时5MS
LCM_EN=0;
LCM_RS=1;//选中数据寄存器
LCM_RW=0;//写模式
_nop_();
LCM_EN=1;
DATAPORT=dat;
_nop_();
_nop_();
LCM_EN=0;
LCM_RS=0;
}
/**********LCD1602初始化子函数***********/
//函数名称:
voidinitLCM(void)
//功能:
初始化LCD1602
//输入参数:
无
//输出参数:
无
//*****************************************
voidinitLCM(void)
{
DATAPORT=0;
delay_LCM(15);
WriteCommandLCM(0x38);//三次显示模式设置,不检测忙信号
delay_LCM(5);
WriteCommandLCM(0x38);
delay_LCM(5);
WriteCommandLCM(0x38);
delay_LCM(5);
WriteCommandLCM(0x38);//8bit数据传送,2行显示,5*7字型
WriteCommandLCM(0x08);//关闭显示
WriteCommandLCM(0x06);//显示光标右移设置
WriteCommandLCM(0x0c);//显示屏打开,光标不显示,不闪烁
WriteCommandLCM(0x01);//清屏
}
/****************显示指定坐标的一个字符子函数*************/
//函数名称:
voidDisplayOneChar(ucharX,ucharY,ucharDData)
//功能:
显示指定坐标的一个字符
//输入参数:
ucharX,ucharY,ucharDData
//输出参数:
无
//*****************************************
voidDisplayOneChar(ucharX,ucharY,ucharDData)
{
Y&=1;
X&=15;
if(Y)X|=0x40;//若y为1(显示第二行),地址码+0X40
X|=0x80;//指令码为地址码+0X80
WriteCommandLCM(X);
WriteDataLCM(DData);
}
/***********显示指定坐标的一串字符子函数***********/
//函数名称:
voidDisplayListChar(ucharX,ucharY,ucharcode*DData)
//功能:
显示指定坐标的一串字符
//输入参数:
ucharX,ucharY,ucharcode*DData
//输出参数:
无
//*****************************************
voidDisplayListChar(ucharX,ucharY,ucharcode*DData)
{
ucharListLength=0;
Y&=0x01;
X&=0x0f;
while(X<16)
{
DisplayOneChar(X,Y,DData[ListLength]);
ListLength++;
X++;
}
}
//**********************
//调用子程序SD.c
//**********************
/*******************************************/
//函数名称:
voiddelay_us()
//功能:
延时
//输入参数:
无
//输出参数:
无
//*****************************************
voiddelay_us()
{
uchari;
for(i=0;i<1;i++)
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
}
/*******************************************/
//函数名称:
voidwrite_byte_spi(uchardat)
//功能:
向SD_SPI卡写一个byte
//输入参数:
uchardat
//输出参数:
无
//*****************************************
voidwrite_byte_spi(uchardat)
{
uchari;
for(i=0;i<8;i++)
{
if(dat&0x80)
{
SI_SD_HIGH;//MOSI=1
}
else
{
SI_SD_LOW;//MOSI=0
}
SCK_SD_LOW;//SCK=0
if(Init_Flag)delay_us();
SCK_SD_HIGH;//SCK=1
if(Init_Flag)delay_us();
dat<<=1;
}
}
/***********************************************/
//函数名称:
ucharread_byte_spi(void)
//功能:
向SD_SPI读取一个byte
//输入参数:
无
//输出参数:
ucharrByte
//*****************************************
ucharread_byte_spi(void)
{
uchari,rByte=0;
for(i=0;i<8;i++)
{
SCK_SD_LOW;
if(Init_Flag)delay_us();
rByte<<=1;
rByte|=MISO;
SCK_SD_HIGH;
if(Init_Flag)delay_us();
}
returnrByte;
}
//****************************************************************************
//函数名称:
unsignedcharWrite_Command_MMC(unsignedchar*CMD)
//功能:
向SD卡发送指令
//入口参数:
unsignedchar*CMD
//返回参数:
Return:
thesecondbyteofresponseregisterofMMC/SD-Card
//****************************************************************************
unsignedcharWrite_Command_MMC(unsignedchar*CMD)
{
unsignedchartmp;
unsignedintretry=0;
unsignedchari;
CS_SD_DIS;//关片选CS=1
write_byte_spi(0xFF);//send8ClockImpulse
CS_SD_EN;//开片选CS=0
for(i=0;i<0x06;i++)//发送6个字节命令
{
write_byte_spi(*CMD++);
}
read_byte_spi();//readthefirstbyte,ignoreit.
do
{
tmp=read_byte_spi();//Onlylast8bitisusedhere.Readitout.
retry++;
if(retry==100)
{
CS_SD_DIS;//关片选CS=1
return(0);
}
}while(tmp==0xff);
CS_SD_DIS;//关片选CS=1
return(tmp);
}
//*********************************************************************
//函数名称:
unsignedcharMMC_Init(void)
//功能:
SD卡初始化
//入口参数:
无
//返回参数:
无
//*********************************************************************
unsignedcharMMC_Init(void)
{
uchari,retry,temp;
ucharCMD[]={0x40,0x00,0x00,0x00,0x00,0x95};
CS_SD_DIS;//关片选CS=1
for(i=0;i<200;i++)//等待SD卡准备完毕
{
_nop_();
}
Init_Flag=1;
for(i=0;i<0x0f;i++)
{
write_byte_spi(0xff);//延时74个以上的时钟
}
CS_SD_EN;//开片选CS=0
retry=0;//发送复位命令CMD0
do
{
temp=Write_Command_MMC(CMD);//retry200timestosendCMD0command
retry++;
if(retry==100)
{
return(INIT_CMD0_ERROR);//CMD0Error!
//timeout
}
}while(temp!
=0x01);
LED1=0;//test;
CS_SD_EN;//发送CMD1命令激活SD卡
CMD[0]=0x41;//Command10x41
CMD[5]=0xFF;
retry=0;
do
{
temp=Write_Command_MMC(CMD);//retry100timestosendCMD1command
retry++;
if(retry==100)
{
return(INIT_CMD1_ERROR);//CMD1Error!
//timeout
}
}
while(temp!
=0);
LED2=0;
Init_Flag=0;//Initiscompleted,cleartheflag
CS_SD_DIS;
return(0);//Allcommandshavebeentaken.
}
//****************************************************************************
//函数名称:
unsignedcharSD_write_sector(unsignedlongaddr,unsignedchar*Buffer)
//功能:
//向SD卡中的指定地址的扇区地址内写入512个字节,使用24号命令
//入口参数:
unsignedlongaddr,unsignedchar*Buffer
//返回参数:
unsignedchar
//****************************************************************************
unsignedcharSD_write_sector(ulongaddr,uchar*Buffer)
{
uchartemp,time;
uinti;
ucharpcnd[]={0x58,0x00,0x00,0x00,0x00,0xff};//24号命令的序列
addr<<=9;//addr=addr*512(左移9次,即2^9=512)
pcnd[1]=((addr&0xff000000)>>24);//将字节的地址写入到CMD24字节序列中
pcnd[2]=((addr&0x00ff0000)>>16);
pcnd[3]=((addr&0x0000ff00)>>8);
CS=0;//打开SD卡片选
time=0;
do
{
temp=Write_Command_MMC(pcnd);
time++;
if(time==100)
{
return(temp);//命令写入失败
}
}while(temp!
=0);
for(i=0;i<100;i++)//这里要插入若干时钟信号
{
read_byte_spi();
}
write_byte_spi(0xfe);//开始写入字节0xfe,后面就是要写入的512个字节
for(i=0;i<512;i++)//将缓冲区中要写入的512个字节写入SD卡中
{
write_byte_spi(*Buffer++);
}
write_byte_spi(0xff);
write_byte_spi(0xff);//两个字节的CRC校验码,不用关心
temp=read_byte_spi();
//P3=temp;
//while
(1);//读取返回值
if((temp&0x1f)!
=0x05)//如果返回值是xxx00101(temp的低五位)说明数据应已被SD卡接受
{
CS=1;
return(WRITE_BLOCK_ERROR);//写块数据失败
}
while(read_byte_spi()!
=0xff);
//等到SD卡不忙(数据被接受以后,SD卡要将这些数据写入到