//實(shí)驗(yàn)?zāi)康模簩W(xué)習(xí)SD卡的操作
//軟件設(shè)計(jì)
//??????? 1、SD卡采用SPI通信
//??????? 2、先往SD里順序?qū)懭?-255共256個(gè)數(shù)據(jù),然后再讀回送LCD1602顯示
//硬件要求:
//??????? 撥碼開(kāi)關(guān)S11置ON
//??????? 跳線J18全部接通
#include
? _FOSC(CSW_FSCM_OFF & XT_PLL4);? //4倍頻晶振,F(xiàn)ailsafe 時(shí)鐘關(guān)閉
? _FWDT(WDT_OFF);???????????????? //關(guān)閉看門(mén)狗定時(shí)器
? _FBORPOR(PBOR_OFF & MCLR_EN);?? //掉電復(fù)位禁止,MCLR復(fù)位使能。
? _FGS(CODE_PROT_OFF);??????????? //代碼保護(hù)禁止
#define? cs? PORTGbits.RG9??????? //定義SD卡片選腳
#define rs LATBbits.LATB4???????? //定義LCD控制位(注意這里只能用LATB寄存器,不能直接用PORTB寄存器)
#define rw LATBbits.LATB5
#define e? LATBbits.LATB6
unsigned char __attribute__((address(0x900))) lcd[3]={0,0,0};
void? spi_init();???????????????? //申明系統(tǒng)初始函數(shù)
void? spi_low();????????????????? //申明產(chǎn)生低波特率函數(shù)(SD卡初始化使用)
void? spi_high();???????????????? //申明產(chǎn)生高波特率函數(shù)(SD卡初始化后使用)
unsigned char sd_reset();???????? //申明SD卡初始化函數(shù)
unsigned char SD_SendCommand(unsigned char cmd,unsigned long arg); //申明寫(xiě)SD卡命令函數(shù)
unsigned char SPI_WriteByte(unsigned char val);??????????????????? //申明寫(xiě)一字節(jié)函數(shù)
unsigned char SPI_ReadByte(void);????????????????????????????????? //申明接收一字節(jié)函數(shù)
unsigned char SD_WriteSingleBlock(unsigned long sector);?????????? //申明寫(xiě)SD卡單BLOCK數(shù)據(jù)函數(shù)
unsigned char SD_ReadSingleBlock(unsigned long sector);??????????? //申明讀SD卡單BLOCK數(shù)據(jù)函數(shù)
void lcd_display();??????????????????????????????????????????????? //申明結(jié)果顯示函數(shù)
void? delay();???????????????????????????????????????????????????? //申明延時(shí)函數(shù)(顯示時(shí)用)
//系統(tǒng)初始化函數(shù)
void spi_init()
{
? TRISG=0x00d0;??????????????????????? //設(shè)置SDI為輸出,其他C口為輸出
? TRISB=0X0000;??????????????????????? //設(shè)置B口為輸出
? TRISD=0X0000;??????????????????????? //設(shè)置D口為輸出
? SPI2CON=0x0278;????????????????????? //空閑時(shí)總線為高電平,fosc/64
? SPI2STAT=0x8000;???????????????????? // 輸出數(shù)據(jù)的末尾采樣輸入數(shù)據(jù),上升沿發(fā)送數(shù)據(jù)
}
//*************************寫(xiě)LCD程序****************************************
//寫(xiě)一個(gè)字節(jié)數(shù)據(jù)函數(shù)
//在電平發(fā)生改變后需要插入一段延時(shí)時(shí)間,否則LCD反應(yīng)不過(guò)來(lái)。
void write(unsigned char x)
?{
? PORTD=x;?????????????????? //待顯示數(shù)據(jù)送PORTD口
? delay();??????????????????
? rs=1;????????????????????? //該字節(jié)數(shù)據(jù)為數(shù)據(jù),而不是命令
? delay();
? rw=0;????????????????????? //此次操作為寫(xiě),而不是讀
? delay();
? e=0;?????????????????????? //拉低使能信號(hào)
? delay();?????????????????? //保持使能信號(hào)為低一段時(shí)間
? e=1;?????????????????????? //拉高使能信號(hào),建立LCD操作所需要的上升沿
? delay();
?}
//********************LCD顯示設(shè)置函數(shù)**************************************
//在電平發(fā)生改變后需要插入一段延時(shí)時(shí)間,否則LCD反應(yīng)不過(guò)來(lái)。
void lcd_enable()
?{
?? delay();
?? rs=0;???????????????????? //該字節(jié)數(shù)據(jù)為命令,而不是數(shù)據(jù)
?? delay();
?? rw=0;???????????????????? //此次操作為寫(xiě),而不是讀
?? delay();
?? e=0;????????????????????? //拉低使能信號(hào)
?? delay();????????????????? //保持使能信號(hào)為低一段時(shí)間
?? e=1;????????????????????? //拉高使能信號(hào),建立LCD操作所需要的上升沿
?? delay();
}
//*********************LCD初始化函數(shù)**************************************
void lcd_init()
?{
??? PORTD=0X1;???????????????? //清除顯示
??? lcd_enable();
??? PORTD=0X38;??????????????? //8位2行5*7點(diǎn)陣
??? lcd_enable();
??? PORTD=0X0e;??????????????? //顯示開(kāi),光標(biāo)開(kāi),閃爍
??? lcd_enable();
??? PORTD=0X06;??????????????? //文字不動(dòng),光標(biāo)右移
??? lcd_enable();
??? PORTD=0X86;??????????????? //時(shí)間顯示地址
??? lcd_enable();
?}
//***********************LCD顯示函數(shù)************************************
void lcd_display()
?{?
??? unsigned char i,j;
??? lcd_init();
??? for(i=0;i<3;i++)????????? //一共3字節(jié)數(shù)據(jù)
?????? {
???????? write(lcd[i]);?????? //查表獲取數(shù)據(jù)并調(diào)用寫(xiě)一個(gè)字節(jié)數(shù)據(jù)函數(shù)送LCD顯示
???????? for(j=0;j<5;j++)???? //延時(shí)一段時(shí)間(主要是為了控制顯示的速度)
????????? {delay();}
?????? }
?}
//****************寫(xiě)一字節(jié)函數(shù)***************************
unsigned char SPI_WriteByte(unsigned char val)
{
?SPI2BUF = val;??????????????? //待發(fā)送數(shù)據(jù)裝載到發(fā)送寄存器
?while(!IFS1bits.SPI2IF);????? //等待發(fā)送完成
??? IFS1bits.SPI2IF=0;??????????? //清除發(fā)送完成標(biāo)志位
?return SPI2BUF;?????????????? //讀取接收寄存器(即使是無(wú)效數(shù)據(jù)也需清空)
}
//****************接收一字節(jié)函數(shù)**************************
unsigned char SPI_ReadByte(void)
{
?SPI2BUF = 0xff;?????????????? //發(fā)送寄存器裝載數(shù)據(jù),以啟動(dòng)數(shù)據(jù)接收
?while(!IFS1bits.SPI2IF);????? //等待接收完成
??? IFS1bits.SPI2IF=0;??????????? //清除接收完成標(biāo)志位
?return SPI2BUF;?????????????? //讀取接收到的數(shù)據(jù)
}
//*****************發(fā)送命令函數(shù)****************************
unsigned char SD_SendCommand(unsigned char cmd,unsigned long arg)
{
?unsigned char r1;
?unsigned char retry1=0;????? //重復(fù)操作次數(shù)
?
?cs=0;??????????????????????? //使能片選信號(hào)
?
?SPI_WriteByte(cmd | 0x40);?? //分別寫(xiě)入命令
?SPI_WriteByte(arg>>24);????? //數(shù)據(jù)段第4字節(jié)
?SPI_WriteByte(arg>>16);????? //數(shù)據(jù)段第3字節(jié)
?SPI_WriteByte(arg>>8);?????? //數(shù)據(jù)段第2字節(jié)
?SPI_WriteByte(arg);????????? //數(shù)據(jù)段第1字節(jié)
?SPI_WriteByte(0x95);???????? //CRC效驗(yàn)和
?
?while((r1 = SPI_WriteByte(0xff)) == 0xff)//等待響應(yīng)
??if(retry1++ > 200) break;//超時(shí)退出?????
????
?cs=1;??????????????????????? //清初片選信號(hào)
?return r1;?????????????????? //返回狀態(tài)值
}
//*******************SD開(kāi)初始化函數(shù)**************************
unsigned char sd_reset()
{
?unsigned char i,tmp;
?unsigned char retry;??????????? //重復(fù)次數(shù)
?unsigned char r1=0;?????????????
?retry=0;
?delay();
?delay();
?do
?{
??????? for(i=0;i<100;i++) SPI_WriteByte(0xff);
?????
??r1 = SD_SendCommand(0,0);//發(fā)idle命令?
??retry++;
??if(retry>20) return 1;?? //超時(shí)退出?
?} while(r1 != 0x01);????? //等待IDLE命令返回
?retry = 0;???????????????????
??? cs=0;
??do
?{
??????? for(i=0;i<100;i++) SPI_WriteByte(0xff);
??r1 = SD_SendCommand(1, 0);???????? //發(fā)Active命令
??retry++;
??if(retry>254) return 1;??????????? //超時(shí)退出
?????? } while(r1);??
??? for(i=0;i<100;i++) SPI_WriteByte(0xff);
?r1 = SD_SendCommand(59, 0);??????????? //關(guān)crc?
?? if (r1) return 1;????????????? //返回不正確,退出初始化
?for(i=0;i<100;i++) SPI_WriteByte(0xff);
??? r1 = SD_SendCommand(16, 512);????????? //設(shè)扇區(qū)大小512
??? if(r1!=0) return 1;??????????????????? //返回不正確,退出初始化
?return 0;????????????????????????????? //正常返回?
}
//********************寫(xiě)一個(gè)扇區(qū)**************************?
unsigned char SD_WriteSingleBlock(unsigned long sector)
{
?unsigned char r1;
?unsigned int i;
??? unsigned char retry=0;
?do
?{
??????? for(i=0;i<100;i++) SPI_WriteByte(0xff);
??r1 = SD_SendCommand(24, sector<<9);//寫(xiě)命令
??retry++;
??if(retry>10) return 1;???????????? //超時(shí)退出?
?} while(r1 != 0x00);?
?cs=0;
?
?SPI_WriteByte(0xff);
?SPI_WriteByte(0xff);
?SPI_WriteByte(0xff);
?SPI_WriteByte(0xff);
?SPI_WriteByte(0xff);
?SPI_WriteByte(0xff);?????????????????
?SPI_WriteByte(0xfe);????????????????? //發(fā)開(kāi)始符
?
?for(i=0; i<512; i++)????????????????? //送512字節(jié)數(shù)據(jù)
?{
??????? if(i<255) SPI_WriteByte(i);?????? //發(fā)送0--255
??else SPI_WriteByte(512-i);??????? //發(fā)送255--0
????????
?}
?
?SPI_WriteByte(0x95);
?SPI_WriteByte(0x95);???????????????? //16-bits CRC
?r1 = SPI_WriteByte(0xff);??????????? //讀響應(yīng)位
??? if(retry++ >10) return 1;??????????? //超時(shí)退出
??? while(!((r1&0x0f)==5));????????????? //等待數(shù)據(jù)成功接受返回信息
??? while(!(SPI_WriteByte(0xff)));?????? //等待SD卡內(nèi)部編程完成
??
?return 0;
}
?????
//******************讀SD卡一個(gè)扇區(qū)************************
unsigned char SD_ReadSingleBlock(unsigned long sector)
{
?unsigned char r1,temp;
?unsigned int i,j;
?unsigned char retry=0;
?do
?{
??r1 = SD_SendCommand(17, sector<<9);//讀命令
??retry++;
??if(retry>10) return 1;???????????? //超時(shí)退出
?} while(r1 != 0x00);?
?cs=0;
?while(SPI_WriteByte(0xff)!= 0xfe)????? //等待接收到開(kāi)始字節(jié)
???? {
?????? if(retry++ >100) return 1;????????? //超時(shí)退出
???? }
?for(i=0; i<512; i++)?????????????????? //讀512個(gè)數(shù)據(jù)
?{
??temp = SPI_WriteByte(0xff);??????? //讀取接收到的數(shù)據(jù)
??????? lcd[0]=(temp/100)+48;
??????? lcd[1]=((temp%100)/10)+48;
??????? lcd[2]=((temp%100)%10)+48;
??????? lcd_display();???????????????????? //讀取數(shù)據(jù)送顯示
??????? for(j=0;j<500;j++) {delay();}
?}
?SPI_WriteByte(0xff);?????????????????? //偽16-bits crc
?SPI_WriteByte(0xff);
?
?cs=1;
?return 0;
}
//***********************延時(shí)程序*************************
void? delay()????????????? //延時(shí)程序
??? {
???? int i;???????????????? //定義整形變量
???? for(i=0x100;i--;);???? //延時(shí)
??? }
//************************主函數(shù)**************************???
int main(void)
{
???? unsigned char loop,res;
???? delay();
???? delay();
???? delay();
???? loop=1;
????
???? cs=1;
???? while(loop)
???? {
??????? spi_init();??????????????????? //調(diào)用系統(tǒng)初始化函數(shù)
??????? res= sd_reset();?????????????? //調(diào)用SD卡初始化函數(shù)
??????????? if(res) break;???????????? //SD卡初始化是否正常,不正常,退出循環(huán),不執(zhí)行下面的讀寫(xiě)操作
??????? SD_WriteSingleBlock(1);??????? //調(diào)用寫(xiě)SD卡單BLOCK函數(shù),其中扇區(qū)號(hào)為1
??????????? if(res) break;
??????? SD_ReadSingleBlock(1);???????? //調(diào)用讀SD卡單BLOCK函數(shù),其中扇區(qū)號(hào)為1
?????????? if(res) break;
??????? loop=0;
???????? while(1);
???? }
???? while(1);
}???
評(píng)論
查看更多