Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
#include <mega32.h>
#include <delay.h>
#define MMC_CS_PORT PORTB
#define MMC_CS_DDR DDRB
#define MMC_CS_PIN 4
// MMC commands (taken from sandisk MMC reference)
#define MMC_GO_IDLE_STATE 0 // initialize card to spi-type access
#define MMC_SEND_OP_COND 1 // set card operational mode
#define MMC_SEND_CSD 9 // get card"s CSD
#define MMC_SEND_CID 10 // get card's CID
#define MMC_SEND_STATE 13
#define MMC_SET_BLOCKLEN 16 //set number of byte to transferblock
#define MMC_READ_SINGLE_BLOCK 17 //read a block
#define MMC_WRITE_BLOCK 24 //write a block
#define MMC_PROGRAM_CSD 27
#define MMC_SET_WRITE_PROT 28
#define MMC_CLR_WRITE_PROT 29
#define MMC_SEND_WRITE_PORT 30
#define MMC_TAG_SECTOR_START 32
#define MMC_TAG_SECTOR_END 33
#define MMC_UNTAG_SECTOR 34
#define MMC_TAG_ERASE_GROUP_START 35 // sets beginning of erase group(mass erase)
#define MMC_TAG_ERASE_GROUP_END 36 //sets end of erase group (mass erase)
#define MMC_UNTAG_ERASE_GROUP 37
#define MMC_ERASE 38
#define MMC_CRC_ON_OFF 59
#define MMC_R1_BUSY 0X80
#define MMC_R1_PARAMETER 0X40
#define MMC_R1_ADDRESS 0X20
#define MMC_R1_ERASE_SEQ 0X10
#define MMC_R1_COM_CRC 0X08
#define MMC_R1_ILLEGAL_COM 0X04
#define MMC_R1_ERASE_RESET 0X02
#define MMC_R1_IDLE_STATE 0X01
#define MMC_STARTBLOCK_READ 0XFE
#define MMC_STARTBLOCK_WRITE 0XFE
#define MMC_STARTBLOCK_MWRITE 0XFC
#define MMC_STOPTRAN_WRITE 0XFD
#define MMC_DE_MASK 0X1F
#define MMC_DE_ERROR 0X01
#define MMC_DE_CC_ERROR 0X02
#define MMC_DE_ECC_FAIL 0X04
#define MMC_DE_OUT_OF_RANGE 0X04
#define MMC_DE_CARD_LOCKED 0X04
#define MMC_DR_MASK 0X1F
#define MMC_DR_ACCEPT 0X05
#define MMC_DR_REJECT_CRC 0X0B
#define MMC_DR_REJECT_WRITE_ERROR 0X0D
void mmclint(void);
unsigned char mmcreset(void);
unsigned char mmcsendcommand(unsigned char cmd, unsigned long int argument);
unsigned char mmcread(unsigned long int sector, unsigned char* buffer);
unsigned char mmcwrite(unsigned long int sector, unsigned char* buffer);
unsigned char mmccommand(unsigned char cmd, unsigned long int argument);
//----------------------------------
void spilnit()
{
PORT.7=1;
DDRB.7=1;
DDRB.6=0;
DDRB.5=1;
DDRB.4=1;
69) SPCR=0X52;
70) SPCR=0X00;
}
unsigned char spitransferbyte(unsigned char data)
{
unsigned char received =0;
76) SPDR = data;
77) while(!(SPSR&(1<<7)));
received = SPDR;
return (received);
}
//////////////////////////////////////
void mmclnit(void)
{
spilint();
MMC_CS_DDR.MMC_CS_PIN=1;
MMC_CS_PORT.MMC_CS_PIN=1;
}
/////////////////////////////////
unsigned char mmcreset(void){
unsigned char i;
unsigned char retry;
unsigned char r1=0;
retry=0;
do{
for(i=0;i<10;i++) spitransferbyte(0xff); // send dummy byte with CS high before accessing
r1= mmcsendcommand(MMC_GO_IDEL_STATE,0); //resetting card go to spi mode
retry++;
98) if(retry>10) return-1;
}while(r1 != 0X01);
retry=0;
do
{
r1= mmcsendcommand(MMC_SEND_OP_COND,0); // initializing card for operation
retry++;
if(retry>100)return-1;
}while(r1);
r1= mmcsendcommand(MMC_CRC_ON,0); //turn off CRC checking to simplify communication
r1=mmcsendcommand(MMC_SET_BLOCKLEN,512);
return 0;
}
//-------------------------------------------------
unsigned char mmcsendcommand(unsigned char cmd, unsigned long argument){
unsigned char r1;
MMC_CS_DDR.MMC_CS_PIN=0; //assert chip select
r1= mmccommand(cmd,argument); //issue the command
MMC_CS_PORT.MMC_CS_PIN=1;
return r1;
}
//-----------------------------------------------
123) char mmcread(unsigned long int sector,unsigned char* buffer )
{
unsigned char r1;
unsigned i;
portd.f1=0;
MMC_CS_DDR.MMC_CS_PIN=0;
129) r1= mmccommand(MMC_READ_SINGLE_BLOCK,sector<<9);
if (r1!=0X00)
return r1;
132) while(spitransferbyte(0xff)!=MMC_STARTBLOCK_READ);
for (i=0;i<0X200;i++)
134) *buffer++ = spitransferbyte(0xff);
spitransferbyte(0xff);
spitransferbyte(0xff);
MMC_CS_PORT.MMC_CS_PIN=1;
return 0;
}
///-------------------------------------------------------
unsigned char mmcwrite(unsigned long int sector,unsigned char* buffer ){
unsigned char r1;
unsigned int i;
MMC_CS_PORT.MMC_CS_PIN=1;
//issue command
r1=mmccommand(MMC_WRITE_BLOCK,sector<<9);
if(r1 != 0X00)
return r1;
spitransferbyte(0xff) // send dummy
spitransferbyte(MMC_STARTBLOCK_WRITE); //send data start token
for (i=0; i<512; i++)
156) spitransferbyte(*buffer++);
spitransferbyte(0xff);
spitransferbyte(0xff);
r1=spitransferbyte(0xff); // write 16-bit crc (dummy values)
// read data response token
if((r1&MMC_DR_MASK)!= MMC_DR_ACCEPT)
return r1;
164) while(!spitransferbyte(0xff));
MMC_CS_PORT.MMC_CS_PIN=1; //CS
return 0; // return succes
}
//////////////////////////////////////////
unsigned char mmccommand(unsigned char cmd,unsigned long int argument){
char r1;
char retry=0;
//send command
spi_write(cmd |0x40);
spi_write(argument>>24);
spi_write(argument>>16);
spi_write(argument>>8);
spi_write(argument);
spi_write(0x95); //crc valid only for mmc_go_idle_state
175) while((r1 = spitransferbyte(0xff))==0xff)
176) if(retry++ > 8) break;
177) return r1;
}
///-------------------------------------------------
char write_buf[512], read_buf[512];
void main(void) {
unsigned int i;
unsigned long int sector;
mmclnit();
mmcreset();
for (i=0;i<512;i++)
write_buf[i]=i;
sector=5;
mmcwrite(sector,write_buf); // write to sector 5
delay_ms(1);
mmcread(sector,read_buf); // read of sector 5
while(1)
}
here is codes for have communication with SD card, it's written for code vision compiler and I have problem with these lines 69,70,76,77,129,132,134 please explain these line completely, if I can understand this program I can change it for mikroc compiler. and my problem will solve, meanwhile what are "SPCR and Spsr ?
Code:#include <mega32.h> #include <delay.h> #define MMC_CS_PORT PORTB #define MMC_CS_DDR DDRB #define MMC_CS_PIN 4 // MMC commands (taken from sandisk MMC reference) #define MMC_GO_IDLE_STATE 0 // initialize card to spi-type access #define MMC_SEND_OP_COND 1 // set card operational mode #define MMC_SEND_CSD 9 // get card"s CSD #define MMC_SEND_CID 10 // get card's CID #define MMC_SEND_STATE 13 #define MMC_SET_BLOCKLEN 16 //set number of byte to transferblock #define MMC_READ_SINGLE_BLOCK 17 //read a block #define MMC_WRITE_BLOCK 24 //write a block #define MMC_PROGRAM_CSD 27 #define MMC_SET_WRITE_PROT 28 #define MMC_CLR_WRITE_PROT 29 #define MMC_SEND_WRITE_PORT 30 #define MMC_TAG_SECTOR_START 32 #define MMC_TAG_SECTOR_END 33 #define MMC_UNTAG_SECTOR 34 #define MMC_TAG_ERASE_GROUP_START 35 // sets beginning of erase group(mass erase) #define MMC_TAG_ERASE_GROUP_END 36 //sets end of erase group (mass erase) #define MMC_UNTAG_ERASE_GROUP 37 #define MMC_ERASE 38 #define MMC_CRC_ON_OFF 59 #define MMC_R1_BUSY 0X80 #define MMC_R1_PARAMETER 0X40 #define MMC_R1_ADDRESS 0X20 #define MMC_R1_ERASE_SEQ 0X10 #define MMC_R1_COM_CRC 0X08 #define MMC_R1_ILLEGAL_COM 0X04 #define MMC_R1_ERASE_RESET 0X02 #define MMC_R1_IDLE_STATE 0X01 #define MMC_STARTBLOCK_READ 0XFE #define MMC_STARTBLOCK_WRITE 0XFE #define MMC_STARTBLOCK_MWRITE 0XFC #define MMC_STOPTRAN_WRITE 0XFD #define MMC_DE_MASK 0X1F #define MMC_DE_ERROR 0X01 #define MMC_DE_CC_ERROR 0X02 #define MMC_DE_ECC_FAIL 0X04 #define MMC_DE_OUT_OF_RANGE 0X04 #define MMC_DE_CARD_LOCKED 0X04 #define MMC_DR_MASK 0X1F #define MMC_DR_ACCEPT 0X05 #define MMC_DR_REJECT_CRC 0X0B #define MMC_DR_REJECT_WRITE_ERROR 0X0D void mmclint(void); unsigned char mmcreset(void); unsigned char mmcsendcommand(unsigned char cmd, unsigned long int argument); unsigned char mmcread(unsigned long int sector, unsigned char* buffer); unsigned char mmcwrite(unsigned long int sector, unsigned char* buffer); unsigned char mmccommand(unsigned char cmd, unsigned long int argument); //---------------------------------- void spilnit() { PORT.7=1; DDRB.7=1; DDRB.6=0; DDRB.5=1; DDRB.4=1; 69) SPCR=0X52; 70) SPCR=0X00; } unsigned char spitransferbyte(unsigned char data) { unsigned char received =0; 76) SPDR = data; 77) while(!(SPSR&(1<<7))); received = SPDR; return (received); } ////////////////////////////////////// void mmclnit(void) { spilint(); MMC_CS_DDR.MMC_CS_PIN=1; MMC_CS_PORT.MMC_CS_PIN=1; } ///////////////////////////////// unsigned char mmcreset(void){ unsigned char i; unsigned char retry; unsigned char r1=0; retry=0; do{ for(i=0;i<10;i++) spitransferbyte(0xff); // send dummy byte with CS high before accessing r1= mmcsendcommand(MMC_GO_IDEL_STATE,0); //resetting card go to spi mode retry++; 98) if(retry>10) return-1; }while(r1 != 0X01); retry=0; do { r1= mmcsendcommand(MMC_SEND_OP_COND,0); // initializing card for operation retry++; if(retry>100)return-1; }while(r1); r1= mmcsendcommand(MMC_CRC_ON,0); //turn off CRC checking to simplify communication r1=mmcsendcommand(MMC_SET_BLOCKLEN,512); return 0; } //------------------------------------------------- unsigned char mmcsendcommand(unsigned char cmd, unsigned long argument){ unsigned char r1; MMC_CS_DDR.MMC_CS_PIN=0; //assert chip select r1= mmccommand(cmd,argument); //issue the command MMC_CS_PORT.MMC_CS_PIN=1; return r1; } //----------------------------------------------- 123) char mmcread(unsigned long int sector,unsigned char* buffer ) { unsigned char r1; unsigned i; portd.f1=0; MMC_CS_DDR.MMC_CS_PIN=0; 129) r1= mmccommand(MMC_READ_SINGLE_BLOCK,sector<<9); if (r1!=0X00) return r1; 132) while(spitransferbyte(0xff)!=MMC_STARTBLOCK_READ); for (i=0;i<0X200;i++) 134) *buffer++ = spitransferbyte(0xff); spitransferbyte(0xff); spitransferbyte(0xff); MMC_CS_PORT.MMC_CS_PIN=1; return 0; } ///------------------------------------------------------- unsigned char mmcwrite(unsigned long int sector,unsigned char* buffer ){ unsigned char r1; unsigned int i; MMC_CS_PORT.MMC_CS_PIN=1; //issue command r1=mmccommand(MMC_WRITE_BLOCK,sector<<9); if(r1 != 0X00) return r1; spitransferbyte(0xff) // send dummy spitransferbyte(MMC_STARTBLOCK_WRITE); //send data start token for (i=0; i<512; i++) 156) spitransferbyte(*buffer++); spitransferbyte(0xff); spitransferbyte(0xff); r1=spitransferbyte(0xff); // write 16-bit crc (dummy values) // read data response token if((r1&MMC_DR_MASK)!= MMC_DR_ACCEPT) return r1; 164) while(!spitransferbyte(0xff)); MMC_CS_PORT.MMC_CS_PIN=1; //CS return 0; // return succes }
while((r1 = spitransferbyte(0xff))==0xff)
if(retry++ > 8) break;
return r1;
// */ my spi function
char* text = "mikroElektronika";
unsigned short x=110;
unsigned char take, buffer;
char txt[6];
char r2=1;
char r1=0;
char bit=0;
char flag1=0;
char debounce = 30;
char count1=0;
/////////////////////////////////////
void mmclnit()
{
trisc.f3=0; // SCK
portc.f3=1;
trisc.f4=1; // SDI
trisc.f5=0; // SDO
sspcon1=0b00100010;
SSPSTAT = 0b01000000;
INTCON.GIE = 1;
INTCON.PEIE = 1;
trisd.f1=0; //CS
portd.f1=1;
}
//////////////////////////////////////
char spitransferbyte(char data)
{
char received =0;
SSPBUF = data;
while(!(PIR1.SSPIF)); PIR1.SSPIF=0;
return received;
}
//////////////////////////////////////////LCD
void lcd(){
Lcd_Cmd(Lcd_CLEAR); // Clear display
Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off
Lcd_Out(1, 1, text); // Print text to LCD, 2nd row, 1st column
WordToStr( x, txt);
Lcd_Out(2, 1, txt);
x=0;
// delay_ms(300);
// Lcd_Cmd(Lcd_CLEAR);
// Lcd_Out(1, 1, text);
}
//////////////////////////////////////////6
mmccommand(){
char i=0;
char retry=0;
r2=1;
while (i<10)
{spitransferbyte(0xff);
i++;
}
i=0;
portd.f1=0;
spitransferbyte(0x40);
spitransferbyte(0x00);
spitransferbyte(0x00);
spitransferbyte(0x00);
spitransferbyte(0x00);
spitransferbyte(0x95);
while ((r1=spitransferbyte(0xff)) == 0xff){
retry ++ ;
if (retry>8) break;
}
x=r1;
portd.f1=1;
////
lcd();
}
/////////////////////////////////////////////0
void main() {
// PORTB is output
Lcd_Init(&PORTB); // Initialize LCD connected to PORTB
pins();
mmclnit(); // config spi
mmccommand();
while(1){
}
}
I replaced BF instead of SSPIF (if(SSPSTAT.BF==1) received=SSPBUF but still no luck ! I read the datasheet of pic and there is mentioned that just one register is for both read and write. do you have any other idea ?Accessing the SPI module through SFRs directly instead of using the mikro C built-in functions is possible, but involves the risk of introducing new problems if you are not familiar with low level PIC programming.
You should at least think about suitable means to verify the correct operation of your code. Personally, I prefer watching the hardware signals with an oscilloscope in this regard.
You are setting mode 0 correctly, but your spitransferbyte() function doesn't return data because it doesn't read SSPBUF.
You can use BF instead of SSPIF to detect the end of transmission.
Setting GEI and PEI makes no sense for your application, but doesn't harm unless any xxxIE bits are set.
Wait, did you switch from AVR to PIC at some point?FVM, I think I should config SPI my self and don't use the SPI library of the mikro c so decided to config SPI same as same the above codes so could you please do me a favor and have look at them meanwhile, do should I use just SS pin as chip select and it's not possible to use another pin as a chip select pin ? unfortunately I didn't get the right R1 response and still I receive Zero !!!! instead of 1, do you have any idea ? i am so confusing
Code:// */ my spi function char* text = "mikroElektronika"; unsigned short x=110; unsigned char take, buffer; char txt[6]; char r2=1; char r1=0; char bit=0; char flag1=0; char debounce = 30; char count1=0; ///////////////////////////////////// void mmclnit() { trisc.f3=0; // SCK portc.f3=1; trisc.f4=1; // SDI trisc.f5=0; // SDO sspcon1=0b00100010; SSPSTAT = 0b01000000; INTCON.GIE = 1; INTCON.PEIE = 1; trisd.f1=0; //CS portd.f1=1; } ////////////////////////////////////// char spitransferbyte(char data) { char received =0; SSPBUF = data; while(!(PIR1.SSPIF)); PIR1.SSPIF=0; return received; } //////////////////////////////////////////LCD void lcd(){ Lcd_Cmd(Lcd_CLEAR); // Clear display Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off Lcd_Out(1, 1, text); // Print text to LCD, 2nd row, 1st column WordToStr( x, txt); Lcd_Out(2, 1, txt); x=0; // delay_ms(300); // Lcd_Cmd(Lcd_CLEAR); // Lcd_Out(1, 1, text); } //////////////////////////////////////////6 mmccommand(){ char i=0; char retry=0; r2=1; while (i<10) {spitransferbyte(0xff); i++; } i=0; portd.f1=0; spitransferbyte(0x40); spitransferbyte(0x00); spitransferbyte(0x00); spitransferbyte(0x00); spitransferbyte(0x00); spitransferbyte(0x95); while ((r1=spitransferbyte(0xff)) == 0xff){ retry ++ ; if (retry>8) break; } x=r1; portd.f1=1; //// lcd(); } /////////////////////////////////////////////0 void main() { // PORTB is output Lcd_Init(&PORTB); // Initialize LCD connected to PORTB pins(); mmclnit(); // config spi mmccommand(); while(1){ } }
Yes, for what ? I want to use PIC.Wait, did you switch from AVR to PIC at some point?
unsigned short take, buffer;
char r1;
/////////////////////////////////////////////0
void main() {
trisd.f1=0; //CS
portd.f1=1;
Spi_Init_Advanced(MASTER_OSC_DIV64, DATA_SAMPLE_MIDDLE, CLK_IDLE_LOW, LOW_2_HIGH);
while(1)
{
delay_ms(1);
portd.f1=1;
r1=0;
while(r1<10) {
spi_write(255); // write dummy for going to SPI mode
r1++;
}
portd.f1=0;
spi_write(64); //cmd0
spi_write(0); //argument
spi_write(0); //argument
spi_write(0); //argument
spi_write(0); //argument
spi_write(149); //crc valid only for mmc_go_idle_state
delay_ms(1);
take=spi_read(buffer);
portd.f1=1;
}
}
yes I know, I try to make this waiting time by 1ms delay in my codes. also I wrote this command "spi_read(buffer)" 8 times following each other to wait 8 read cycles, but still I didn't receive "1" as reply of cmd0 ? why ? do you have any other plan ? by the way I provide a oscilloscope too and I can see what I am sending in the SD card.You need to wait 8 read cycles, as in your previous code, see post #26.
could you please give me correct codes ? just for sending CMD0 and receiving 1 as response .If there's no card response, although all involved signals are showing correct waveforms (correct level, correct SPI mode), a hardware problem should be expected.
I can only refer to the code shown in your post. It should comply to the sequence required by the SD-card specification.
The usual implementations are different from your code in several aspects:
- cmd is preceeded by a 0xff byte. If I understand right, this is required by the specification (Ncs = 8 clock cyles)
- no 1 ms delay. It's useless, because the command is only processed, if the clock is continued
- up to 8 instead of 1 reads succeding, stop on a none 0xff answer
- the 8 reads are sending 0xff, probably not required by the specification