//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// Title: myMMC ;
// Description: thu vien ghi-doc card MMC/SD cho PIC ;
// Chuong trinh duoc chinh sua tu thu vien ghi-doc card MMC/SD cho AVR ;
// Source website: www.hocavr.com ;
// Author: anhxtuan ;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//*************************KHONG THAY DOI BAT CU THU GI KE TU DONG NAY*******************************************
#include <htc.h>
#include "myMMC.h"
#include "uart.h"
//cai dat cho SPI o che do Master----------------------------------------------------------------------------
void SPI_MasterInit(void)
{
// I/O PORT init for SPI communication
TRISC3 = 0; // SCK pin is output
TRISC5 = 0; // SDO pin is output
TRISC4 = 1; // SDI pin is input
// init LATCH PIN: RC1
TRISC1 = 0; // is output
//SSPSTAT
SMP = 1; // data in sampled at middle
CKE = 1; // data out at rising edge (with CKP = 0)
//SSPCON
SSPCON = 0b00100000; // CKP = 0, SPI mode baudrate = Fosc/4
}
//Truyen 1 byte
unsigned char spi(unsigned char b)
{
WCOL = 0; // clear any write collision condition
SSPIF = 0; // clear SSP interrupt flag
SSPBUF = b; // load the SSP buffer with data
while(!SSPIF); // wait for SSPIF to be sent
return SSPBUF;
}
// end of SPI--------------------------------------------------------------------------------------------
// for mmc***********************************************
//nhan va so sanh Response tu mmc
char mmc_rResponse(char Response)
{
int Timeout = 0x0fff;
char Res;
while((Timeout--) > 0)
{
Res = spi(0xff);
if (Res == Response) break; //escape from while
}
if (Timeout == 0) return 1; //tra ve 1 neu timeout
else return 0; // ko co loi, tra ve 0
}
void mmc_tCommand(char Cmd, long arg)
{
//command la 48 bit lien tiep trong do
//bit47=0 (start bit)
//bit46=1 (transmission bit)
//bit45:40 la ma lenh
//bit39:8 la argument cua lenh
//bit7:1 Cyclic Redundancy Check (CRC)
//bit0=1 la end bit
cbi(SPI_PORT, SS_PIN); //kich hoat duong SS cua SPI, MMC duoc chon
spi(0xFF); //dummy, 1 lenh luon bat dau 0 nen send FF thi MMC ko dap ung
spi(Cmd | 0x40); //0x40=01000000 la ma bat buoc khi goi lenh
spi((char)(arg >>24));
spi((char)(arg >>16));
spi((char)(arg >> 8));
spi((char) arg);
spi(0x95); //CRC, cho lan dau nhung neu cac lan sau send 0x95 cung ko van de;
spi(0xFF); //ko quan tam return
}
char mmc_init(void)
{
// local variable
int i;
char mmc_status;
SPI_MasterInit();
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
for (i = 0; i < 10; i++)
spi(0xFF); //MMC se vao SPI mode neu duoc nhan nhieu hon 80 clock tren SCK
cbi(SPI_PORT, SS_PIN); //cho phep MMC hoat dong
mmc_tCommand(CMD0, 0); //lenh CMD0. reset mmc
if(mmc_rResponse(0x01) == 1){ //co loi kiem tra response
mmc_status = 1; // timeout khi reset
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return mmc_status;
}
//goi lenh CMD1 cho den khi nhan duoc response =0 hoac timeout
i = 0xffff; //max timeout
do{
mmc_tCommand(CMD1,0); //lenh CMD1
i--;
} while((spi(0xff) != 0) && (i > 0));
if(i == 0){ //co loi khi goi CMD1
mmc_status = 2; // loi CMD1
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return mmc_status;
}
mmc_tCommand(CMD16, Block_len); //lenh CMD16, set do dai sector,Block_len=512
if(mmc_rResponse(0x00) == 1){ //co loi kiem tra response
mmc_status=3; // timeout khi set len
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return mmc_status;
}
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return 0; //no error
}
char mmc_writeblock(long LBAddress, char *buff)
{
//local variable
long tempA;
int i;
char mmc_status;
tempA = LBAddress<<9;
//cach bo tri dia lba cho cho lenh write xxxxxxxx-xxxxxxxx , xxxxxxx0-00000000
//trong do x la cac bit cua dia chi, nhu vay 9 bit dau cua argument low ko dung
cbi(SPI_PORT, SS_PIN); //cho phep MMC hoat dong
mmc_tCommand(CMD24,tempA); //goi lenh cho phep ghi single sector, chu y cach set dia chi
if(mmc_rResponse(0x00) == 1){ //co loi kiem tra response
mmc_status=4; // timeout khi goi lenh write block
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return mmc_status;
}
//goi dau hieu (token) bao cho mmc biet sap co data den, dau hieu=0xFE
spi(0xFE);
//goi Block_len = 512 byte data
for (i = 0; i < Block_len; i++)
{
spi(buff[i]);
//uart_putc(buff[i]);
//if(buff[i] == 0) break;
}
//goi 2 byte checksum
spi(0xFF);
spi(0xFF);
//doc trai thai response, phai la 0x05
char status;
status = spi(0xff);
if((status & 0x0F) != 0x05){ //co loi kiem tra response
mmc_status = 5; // loi khi goi datablock
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return mmc_status;
}
__delay_ms(1);
//uart_puts("a\r\n");
//cho mmc het busy
i = 0xffff; // max timeout
while(!spi(0xff) && (--i)){;} // wait until we are not busy
if (i==0) {
mmc_status=6; // loi timeout khi cho busy
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return mmc_status;
}
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return 0;
}
char mmc_readblock(long LBAddress, char *buff)
{
long tempA;
int i;
char mmc_status;
tempA = LBAddress<<9;
//cach bo tri dia lba cho cho lenh write xxxxxxxx-xxxxxxxx , xxxxxxx0-00000000
//trong do x la cac bit cua dia chi, nhu vay 9 bit dau cua argument low ko dung
cbi(SPI_PORT, SS_PIN); //cho phep MMC hoat dong
mmc_tCommand(CMD17,tempA); //goi lenh cho phep doc single sector, chu y cach set dia chi
if(mmc_rResponse(0x00) == 1) //co loi kiem tra response
{
mmc_status = 7; // timeout khi goi len read block
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return mmc_status;
}
//kiem tra dau hieu (token) read
if(mmc_rResponse(0xFE) == 1) //co loi kiem tra response
{
mmc_status=8; // timeout khi goi len read block
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return mmc_status;
}
__delay_ms(1);
//sau day la goi Block_len=512 byte data
for (i = 0; i < Block_len; i++)
{
//
//uart_putc(spi(0xff));
//uart_putc(i);
//__delay_ms(50);
buff[i] = spi(0xff);
}
uart_puts("\r\nANHXTUAN\r\n");
//goi 2 byte checksum
spi(0xFF);
spi(0xFF);
sbi(SPI_PORT, SS_PIN); //disable SPI MMC
return 0;
}