I thought so too.... But!!! This guy writes to the SD card raw... With audio!!!!! And plays it back, all with a pic16f876a
https://www.moty22.co.uk/sd.php
That's because it's simply writing raw data to the card, no file system at all, so you can't read it on a PC etc.
Thank you very much.Attached are two PDF documents that are excellent. Also attached is a big collection of documents including the official SD card specifications.
The SPI mode is quite simple, but remember to always send the additional clock cycles to the card. This really is essential or commands will mysteriously fail!
Also don't power cards from 5v, even accidentally for a second or two. They really don't like it..
Also, I would like to learn to make the datas I write visible as mydata.txt on the SD card when browsed with computer.
Ofcourse, much of the portion of mydata.txt will be filled with dummy 0s, I can manage to write a computer software to sort it out.
That's not going to be easy. In order for a computer to see it as a file, the card needs to contain a file system. You aren't going to be able to work with a filesystem when you are ignoring 90% of the card's contents.
You could use software on the PC to read and write the raw data from the card, but it's not a simple "double click and there is your data". If you are on a unix-like system you could probably open the device in your favourite editor (assuming appropriate permissions).
The only way that might possibly do what you want (and it's a long shot) would be to create the filesystem and create a large empty file in it, and then work out where the file starts on the physical device and start reading and writing from that location. It would be extremely risky because anything that relocates part of the file would cause corruption of the data. Wear levelling (at the file system level), file system fragmentation (and defragmentation) could all cause a lot of damage. I would strongly suggest that you avoid this option.
As long as you are writing software on the PC anyway, make the software read the data directly from the device rather than trying to use files.
Use another dedicated SD card handler.Ian Rogers said:I use an add on card... its very simple to use, and plugs onto the Rx and TX pins of my micro. Its an open logger... Primarily used as a data logger but can be used as a filing system.
https://www.sparkfun.com/products/9530
I use it as a datalogging facility...
Nowadays I am searching information about using sd cards in my project, I will also use 16f877A in my project, as you mentioned about the problem of 512 bytes and I think another way to solve this problem, my solution is;
Up to 8K x 14 words of FLASH Program Memory,
Up to 368 x 8 bytes of Data Memory (RAM)
Up to 256 x 8 bytes of EEPROM Data Memory
as in the datasheet of the 16f877a, so we may use EEPROM 's 256 byte and then switching to bank1 and use A0h-EFh 80 bytes, then switch bank2 and use 120h-16Fh 80 bytes, bank3 1A0h-1FFh 96 bytes totally 256+256=512 bytes yes this is a hard way but I think it is possible but I didn't tried it yet.
#include<htc.h>
//__CONFIG(HS & LVPDIS & BORDIS & PWRTDIS & WDTDIS & DEBUGDIS);
#define _XTAL_FREQ 20000000
#define CS RC0
#define CS_tris TRISC0
#define But_write RB2
#define But_read RB3
#define But_inc RB0
#define But_dec RB1
#define BinToASCII(t) ((t<=9) ? (t|0x30):(t+55))
#define ASCIIToBin(t) ((t>='A'&& t<='F')?t-55:((t>='0'&& t<='9') ? t-'0':0))
#define BYTELOW(v) (*((unsigned char *)(&v)))
#define BYTEHIGH(v) (*(((unsigned char *)(&v) + 1)))
#define BLOCK_SIZE 512
volatile bit command_aayo=0;
volatile char cmd;
const unsigned char CMD0_RST_IDLE[]= {0x40,0x00,0x00,0x00,0x00,0x95};
//command 0 reset all card to idle state
const unsigned char CMD1_SND_OPCND[]= {0x41,0x00,0x00,0x00,0x00,0xFF};
//command 1 for read OPERATION CONDITION register
const unsigned char CMD16_SET_BLOCKLEN[]= {0x50,0x00,0x00,0x02,0x00,0xFF};
//command 16 TO SET BLOCK LENGHT=512 BYTE TO READ & WRITE
//0x000200=512 & 0x00000010=16
const unsigned char MSGF[] ={"\rMMC CARD INTERFACE\r"};
const unsigned char MSG0[] ={"\rMMC CARD COMMAND 0\r"};
const unsigned char MSG1[] ={"\rMMC CARD COMMAND 1\r"};
const unsigned char MSGB[] ={"\rMMC CARD COMMAND BLOCK=512\r"};
const unsigned char MSGW[] ={"\rMMC CARD SECTOR WRITE\r"};
const unsigned char MSGR[] ={"\rMMC CARD SECTOR READ\r"};
const unsigned char MSG[] ={"\nMMC CARD IS INITIALIZED SPI MODE\n"};
const unsigned char CSD[] ={"\rCSD INFORMATION:\r"};
const unsigned char CID[] ={"\rCID INFORMATION:\r"};
const unsigned char WACK[] ={"\rWRITE ACKNOLEDGE:\r"};
const unsigned char WNFSH[]={"\rWRITE NOT FINISH:\r"};
const unsigned char MSG_retry[]={"\r retry \r"};
const unsigned char cmd_rcv[] ={"\rCommand Recieved: \r"};
unsigned char TEMP;
unsigned int iSIZE;
unsigned int iSIZE1;
unsigned char BUFFER[50];
unsigned char adc_low,adc_high;
unsigned int timer0_counter=0;
unsigned char Data=65;
unsigned int RdFlag=0,WrtFlag=0;
void delay_10ms(char x)
{
while(x--) __delay_ms(10);
return;
}
void uart0_init(void)
{
TRISC6=0;
TRISC7=1;
SYNC=0; // no synch
SPBRG=10; // 113636.36 baud at 20Mhz. Very Near to 115200. 1.35% error.
BRGH=1; // low baud rate
SPEN=1; //enable the serial port
TX9=0; // no pairity bit
TXEN=1; // Start Transmission
CREN=1; //recieve data too
TXIE=0; // no intrpt
RCIF = 0;
RCIE = 1;
}
void SpiInit(){
SSPSTAT = 0b10000000; // middle/active->idle/...
TRISC4 = 1;
TRISC5 = 0;
TRISC3 = 0;
CS_tris = 0;
SSPCON = 0b00110010; //FOSC/64 <make b0-b3 = 0000 for fosc/4
}
unsigned char ReceiveByte()
{
while(!RCIF);
return RCREG;
}
void SEND_CHAR_UART(char ch)
{
while(!TXIF);
TXREG = ch;
}
void SendStr(const char *ch)
{
while(*ch != 0x00)
SEND_CHAR_UART(*ch++);
}
void PRINT_ASCII (unsigned char PRNT)
{
unsigned char PRN=0;
PRN=PRNT>>4;
SEND_CHAR_UART(BinToASCII(PRN));
PRN=PRNT&0x0F;
SEND_CHAR_UART(BinToASCII(PRN));
}
unsigned char CHAR_SPI(unsigned char byte) //both reads and writes a byte
{
SSPIF = 0;
SSPBUF = byte;
while (!SSPIF);
SSPIF = 0;
return SSPBUF;
}
unsigned char MMC_RESPONCE(unsigned char RESPONSE )
{
unsigned int COUNT=0xFFF; // for 64 MB card
// unsigned int COUNT=0xFFFF; // for 1 GB
unsigned char RESULT;
while(COUNT!=0)
{
RESULT = CHAR_SPI(0xFF);
// PRINT_ASCII (RESULT); SEND_CHAR_UART('\r'); //debug
if(RESULT==RESPONSE) break;
COUNT--;
}
if(COUNT==0)return 1;
else return 0;
}
/***************************************************/
unsigned char MMC_WAIT_FOR_WRITE_FINISH( void )
{
unsigned char LPCNT=0xFF;
unsigned char RESULT = 0;
/* The delay is set to maximum considering the longest data block length to handle */
while( (RESULT == 0) && LPCNT )
{
RESULT = CHAR_SPI( 0XFF);
LPCNT--;
}
if (LPCNT== 0 )
return 1; /* Failure, loop was exited due to timeout */
else return 0; /* Normal , loop was exited before timeout */
}
/*-----------------------------------------------------------------------------*/
unsigned char MMC_INIT()
{
unsigned char LPCNT=0;
/* start off with 80 bits of high data with card deselected */
CS = 1; //deselect
for(LPCNT=0;LPCNT<10; LPCNT++)
CHAR_SPI(0xff);
/*-----------------------------------------CMD 0-------------------------------*/
CS=0; /* select card */
CHAR_SPI( 0X40);CHAR_SPI( 0X00);CHAR_SPI( 0X00);
CHAR_SPI( 0X00);CHAR_SPI( 0X00);CHAR_SPI( 0X95);
if( (MMC_RESPONCE(0x01)) == 1 )
{
//fail
CS = 1;
return 1;
}
SendStr(MSG0);
/*-----------------------------------------------------------------------------*/
CS = 1;
CHAR_SPI(0xFF);
/*----------------------------------CMD1---------------------------------------*/
CS = 0;
LPCNT=0xFF;
do
{
CHAR_SPI( 0X41); CHAR_SPI( 0X00); CHAR_SPI( 0X00);
CHAR_SPI( 0X00); CHAR_SPI( 0X00); CHAR_SPI( 0XFF);
LPCNT--;
} while ( (MMC_RESPONCE(0x00) != 0) && (LPCNT>0) );
if(LPCNT==0)
{
CS = 1; //fail
return 1;
}
SendStr(MSG1);
/*--------------------------------------------------------------------*/
CS = 1;
CHAR_SPI(0xFF);
/*---------------------CMD16 SET BLOCK LENGTH------------------------*/
CS = 0; // select card
CHAR_SPI( 0X50); CHAR_SPI( 0X00); CHAR_SPI( 0X00);
CHAR_SPI( 0X02); CHAR_SPI( 0X00); CHAR_SPI( 0XFF);
if( (MMC_RESPONCE(0x00)) == 1 )
{
CS = 1; //fail
return 1;
}
SendStr( MSGB);
CS = 1;
CHAR_SPI(0xFF);
return 0;
}
/*----------------------------------------------------------- */
void GET_CSD()
{
CS = 0;
CHAR_SPI( 0x49); CHAR_SPI( 0x00); CHAR_SPI( 0X00);
CHAR_SPI( 0x00); CHAR_SPI( 0x00); CHAR_SPI( 0XFF);
while ((MMC_RESPONCE(0x00)) == 1);
while( (MMC_RESPONCE(0xFE)) == 1 );
for(TEMP=0;TEMP<=35;TEMP++)
BUFFER[TEMP]=CHAR_SPI(0xFF);
SendStr(CSD);
for(TEMP=0;TEMP<=15;TEMP++)
PRINT_ASCII(BUFFER[TEMP]);
SEND_CHAR_UART('\n');
CS = 1; // Deselect card
}
/*----------------------------------------------------------- */
void GET_CID()
{
CS=0; // select card
CHAR_SPI(0x4A); CHAR_SPI(0x00); CHAR_SPI(0X00);
CHAR_SPI(0x00); CHAR_SPI(0x00); CHAR_SPI(0XFF);
while ((MMC_RESPONCE(0x00)) == 1);
while( (MMC_RESPONCE(0xFE)) == 1 );
for(TEMP=0;TEMP<=35;TEMP++)
BUFFER[TEMP]=CHAR_SPI(0xFF);
SendStr(CID);
for(TEMP=0;TEMP<=15;TEMP++)
PRINT_ASCII(BUFFER[TEMP]);
SEND_CHAR_UART('\n');
CS=1; // Deselect card
}
/*----------------------------------------------------*/
void INSULATOR()
{
CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
}
/*--------------------------------------------------------------------------------------*/
unsigned char MMC_WRITE_BLOCK( unsigned int SECTOR)
{
unsigned char WRT=65;// A
unsigned int LPCNT=0;
unsigned long ADDRESS=0;
ADDRESS=(unsigned long)SECTOR*BLOCK_SIZE;
/*-----------------------CMD24------------------------------------------------*/
CS = 0;
CHAR_SPI( 0x58);
CHAR_SPI (ADDRESS>>24); CHAR_SPI (ADDRESS>>16);
CHAR_SPI (ADDRESS>>8); CHAR_SPI (ADDRESS>>0);
CHAR_SPI( 0xFF);
if( (MMC_RESPONCE(0x00)) == 1 )
{
CS=1;
return 1;
}
CHAR_SPI(0xFF);
CHAR_SPI(0xFE); //start of DATABLOCK
for(LPCNT=0;LPCNT<511; LPCNT++) //12 times
{
CHAR_SPI(Data);
//CHAR_SPI(WRT);
//SEND_CHAR_UART(WRT);
}
/*for(LPCNT=0;LPCNT<10; LPCNT++) //10 times main loop
{
unsigned char temp_data;
temp_data = ReceiveByte();
for (unsigned char j=0;j<50;j++){ //x50 = 500 times
CHAR_SPI(temp_data);
}
//CHAR_SPI(WRT);
//SEND_CHAR_UART(WRT);
}
*/
CHAR_SPI(0xFF); CHAR_SPI(0xFF); // dummy chksum
LPCNT= CHAR_SPI(0xFF);
//SendStr(WACK); PRINT_ASCII(LPCNT); PRINT_ASCII((LPCNT & 0x0F)); // disabled for debugging
if ( (LPCNT & 0x0F) != 0x05 )
{
CS=1;
return 1;
}
if( MMC_WAIT_FOR_WRITE_FINISH()==1) //disabled for debugging
{
SendStr(WNFSH); // disabled for debugging //-----------------------
CS = 1;
return 1;
}
//SendStr( MSGW); //disabled for debugging
/*----------------------------------------------------------------------------------------------------*/
CS=1;
CHAR_SPI(0xFF);
return 0;
}
/*----------------------------------------------------------------------------------------------------*/
unsigned char MMC_READ_BLOCK( unsigned long SECTOR)
{
unsigned int LPCNT=0;
unsigned long ADDRESS=0;
unsigned char mmcData=0;
ADDRESS=(unsigned long)SECTOR*BLOCK_SIZE;
/*-----------------------CMD17------------------------------------------------*/
// CMD17 READ_SINGLE_BLOCK
// Function : Single block read
// [31:0] Data address R1
CS=0; // Deslect Card
CHAR_SPI( 0x51);
CHAR_SPI (ADDRESS>>24); CHAR_SPI (ADDRESS>>16);
CHAR_SPI (ADDRESS>>8); CHAR_SPI (ADDRESS>>0);
CHAR_SPI( 0xFF);
if( (MMC_RESPONCE(0x00)) == 1 )
{ CS=1;
return 1;
}
//////////////////////////////////////////////////////////////////
//while( (MMC_RESPONCE(0xFE)) == 1 ) // disabled for debugging
//SEND_CHAR_UART('r'); // disabled for debugging
//////////////////////////////////////////////////////////////////
while( (MMC_RESPONCE(0xFE)) == 1 ); // added for debugging //---------
for(LPCNT=0;LPCNT<512;LPCNT++)
{
if((LPCNT%32)==0){SEND_CHAR_UART('\n');SEND_CHAR_UART('\r');}
mmcData=CHAR_SPI(0xFF);
SEND_CHAR_UART(mmcData); // added for debugging
}
CHAR_SPI(0xFF); CHAR_SPI(0xFF); //read CHKSUM
//SendStr( MSGR); // disabled for debugging
/*----------------------------------------------------------------------------*/
CS=1;; // deslect card
CHAR_SPI(0xFF);
return 0;
}
void interrupt isr(void){
if(RCIE && RCIF){
command_aayo = 1;
cmd = RCREG;
}
}
void main()
{
int i=0,LPCNT=0;
unsigned char rData;
unsigned int SECT=200;
OPTION = 0b10000111; //prescalare 1:256 for tmr0;
TRISB = 0x00; //input
TRISA = 0x00;
TRISD = 0x00; //all output
// PORTD = SECT;
TMR0IF = 0;
TMR0IE = 1;
SpiInit();
uart0_init(); // for baud rate of 115200 bps
T0IE = 0;
TMR1IE = 0;
SSPIE = 0;
PEIE = 1;
GIE = 1;
// while(1){
SEND_CHAR_UART('a');
SEND_CHAR_UART('b');
// }
SendStr( MSGF);
////////////////////////////////////////////////////////////////////////////////
while ( MMC_INIT() != 0)
{
SendStr( MSG_retry);
//SEND_CHAR_UART(0x0D);
//SEND_CHAR_UART(0x0A);
//break; disabled for debugging
}
SEND_CHAR_UART(0x0D);
SEND_CHAR_UART(0x0A); // MSG[] ={"\nMMC CARD IS INITIALIZED SPI MODE \n"};
INSULATOR();
GET_CSD();
INSULATOR();
GET_CID();
INSULATOR();
RdFlag=0,WrtFlag=1;
while(1)
{//start of while loop for data read & write
////////////////////////// write routine ///////////////////////////
if(command_aayo==1){ //flag to test if command recieved
if(cmd=='C'){
SendStr(cmd_rcv);
GET_CID();
INSULATOR();
}
if(cmd=='W')
{//if for write button
/////////////////////////////////////////////////////
//Routines for writing data
SendStr(cmd_rcv);
MMC_WRITE_BLOCK(SECT);
INSULATOR();
Data++;
delay_10ms(50);
}//end of if block for write button
///////////////// end of write routine /////////////////////////////
if(cmd=='R')
{
SendStr(cmd_rcv);
// Routine for reading data
MMC_READ_BLOCK(SECT);INSULATOR();
delay_10ms(50);
}// closing bracket of if block for reading data
command_aayo=0;
}
}//ending bracket for while loop for read & write
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?