Shop OBEX P1 Docs P2 Docs Learn Events
C language write/read SD card - examples — Parallax Forums

C language write/read SD card - examples

John KauffmanJohn Kauffman Posts: 653
edited 2013-09-16 18:22 in Propeller 1
I'm trying to create examples for many types of data saves to SD.
Here is simplest: one int. But read back is wrong as comments at end.

#include "simpletools.h" // Include simpletools header .
int DO = 22, CLK = 23, DI = 24, CS = 25; // SD card pins on Propeller BOE
// values for writes & values to receive reads
int myInt1 = 11;
int myInt2 = 22;
int myReadInt = 0;

int main(void){
//--- Setup to use SD Card
sd_mount(DO, CLK, DI, CS); // Mount SD card
//--- One int
FILE* fp = fopen("OneInt.txt", "w"); // Open a file for appending
print("\nmyInt1 = %d",myInt1); // Tell user value to write
fwrite(&myInt1, 4, 1, fp); // Write number to SD card
myReadInt = fread(&myInt1, 4, 1, fp); // Read from SD & get status
print(", myReadInt1 = %d\n",myReadInt); // Tell user value read
fclose(fp); // Close the file

// ***** problems: (n.b. using SD file multiple times in testing)
// result on terminal is "myInt1 = 11, myReadInt1 = 0"
// result on SD is " " (not parsed as ASCII?)
} // main

Comments

  • Dave HeinDave Hein Posts: 6,347
    edited 2013-09-13 10:22
    myReadInt contains the return value from fread, and it tells you the number of bytes read. myInt1 will contain the data that is read. However, you are reading from the file without first closing it and then re-opening it for read. If you opened with with "r+w" this would be allowed, but I'm not sure if it is allowed when opening it with just "w". Of course, if you did open it with "r+w" you would need to reposition the file back to the beginning before you read back the value you had just written. Your program is writing 4 bytes and then reading 4 bytes, but the file is positioned at the end, so the fread is just returning a count of zero bytes.

    You can either close and then reopen the file with a "r" mode, or open it with "r+w", and then call fseek(fp, 0, SEEK_SET) between the fwrite and fread to reposition it back to the beginning of the file.
  • John KauffmanJohn Kauffman Posts: 653
    edited 2013-09-13 11:12
    Dave:
    Thanks a million. Your post not only works but your explanation makes it clear why.
    Now I'm going on to make examples of other permutations of values to save.
    - John
  • Ken GraceyKen Gracey Posts: 7,392
    edited 2013-09-13 12:00
    Hey John- received your message and plan on getting in contact as soon as possible. Just today my schedule finally started to open up a bit after a trip, an S2 course yesterday, etc.

    I had a thought that since you are an educator and you are really pressing SimpleIDE and C for Propeller, that you might want to start a thread called John Kauffman's Simple IDE code examples. You're not alone and many people could learn from your code examples. Consider updating your samples in their original postings so they are useful for other people who also will want to do the same thing. You're now ahead of my Simple IDE and C experience, but I know I'll try to catch up soon.

    I like what you're doing and I'm inspired to run the code myself.
  • John KauffmanJohn Kauffman Posts: 653
    edited 2013-09-13 12:48
    I figured you were busy with big push on Learn C, P2, etc. Everyone at HQ will deserve an extra day off at Thanksgiving.

    I'm working on several example sheets which are made possible by help from lots of generous contributors on these fora. I'm also keeping notes on stumble points in transition from PBASIC to Propeller C Learning system. I'm glad to share them so I get feedback for improvements.

    Rather than an eponymous thread I could see a new forum dedicated to the Propeller Learn C System. Right now those posts sort of get lost within the Learn forum as a whole. I predict you are going to get a lot of traffic specific to the C topics.
  • John KauffmanJohn Kauffman Posts: 653
    edited 2013-09-13 14:53
    I'm trying to write & read one char to SD and getting an odd result. I tried to write 'P' but the read result in terminal is the char for ASCII 25
    #include "simpletools.h"                      // Provides I/O tools for use w/ SD
    // vars & cons
      int DO = 22, CLK = 23, DI = 24, CS = 25;      // SD card pins on Propeller BOE
    
    // values for writes & values to receive reads
      char myChar1='P'; // ASCII 80
      char myChar2='a'; // ASCII 97
      char myReadChar;
    
    int main(void){
    //--- Setup to use SD Card -------------- 
      sd_mount(DO, CLK, DI, CS);                   // Mount SD card
    
    //--- One char ------------------------
    // write one char
      FILE* fp = fopen("CharString01.txt", "w");        // Open&erase or create a file
      print("\nmyChar1 = %d",myChar1);         // User info
      fwrite(&myChar1, 1, 1, fp);                   // Write to SD card
      fclose(fp);                                  // Close the file
    // read one char
      fopen("CharString01.txt", "r");        // Open a file for read
      fread(&myReadChar, 1, 1, fp);        // Read from SD
      print(", myReadChar = %s\n",myReadChar);  // User info
      fclose(fp);                                  // Close the file
    
    // PROBLEM
      // terminal output is "myChar1 = 80, myReadChar =   " 
      // last character above is ASCII 25 
    }// main 
    
    
  • SRLMSRLM Posts: 5,045
    edited 2013-09-13 15:15
    Does the driver support opening a filename that's larger than 8.3?

    Also, do you pass "w" (string) to fopen or do you pass 'w' (char)? Maybe it doesn't matter (based on Dave Hein's response) but it doesn't hurt to check.

    Do you need to put a delay in to allow for the SD card to mount?
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-09-13 15:17
    Use %c instead of %s in your print format. With %s you are using myReadChar as a string pointer instead of as a char. Also, the PropGCC file driver only supports 8.3 type file names, so CharString01.txt is probably being treated as CharStri.txt in the file driver.

    Use the -Wall compiler option, and it will provide useful warning messages.

    EDIT: The "w" parameter is correct.
  • SRLMSRLM Posts: 5,045
    edited 2013-09-13 15:26
    Why do you pass %d and %s to print? Shouldn't both be %c?

    Edit: Looks like I got beat by Dave Hein :)
  • John KauffmanJohn Kauffman Posts: 653
    edited 2013-09-13 15:29
    Perfect - I really appreciate your help.
    I changed all examples to reflect 8.3.
    I'm using SimpleIDE and just hit F8 to compile, load, run ad open Terminal. how would I add the -Wall option?
  • John KauffmanJohn Kauffman Posts: 653
    edited 2013-09-13 15:43
    The next one on my list I got, but open to improvements.
    //--- String of known length ----------------
      FILE* fp=fopen("String01.txt", "w");        // Open/erase or create file for write
        fwrite("String length known 22", 1, 22, fp);  // n.b 1 byte per char, 22 chars
      fclose(fp);
      fopen("String01.txt", "r");        // Open/erase or create file for write
        char myReadChar[100]; // buffer - give some extra room for future
        fread(myReadChar, 1, 22, fp); // known length of 22 chars
        print(myReadChar);
      fclose(fp);
    
  • John KauffmanJohn Kauffman Posts: 653
    edited 2013-09-13 16:08
    If you have the patience, the next example is a string of unknown length.
    I think it is close, but I don't know how to set number of characters to read - the ????? below. I am guessing a loop that reads one chat at a time until the return of the fread() == a terminator character.

    I have to leave for a few days so don't be surprised that I don't reply until Monday. I deeply appreciate sharing your expertise. I will be writing this up to be available to all of us switching from PBASIC to C.
    #include "simpletools.h"                      // Provides I/O tools for use w/ SD
    // vars & cons
      int DO = 22, CLK = 23, DI = 24, CS = 25;      // SD card pins on Propeller BOE
    int main(void){
    //--- Setup to use SD Card -------------- 
      sd_mount(DO, CLK, DI, CS);                   // Mount SD card
    
    //--- String of unknown length ----------------
      FILE* fp=fopen("Str02.txt", "w");        // Open/erase or create file for write
        char myStringAnySize[80];
        char myReadStringAnySize[80];
        fgets(myStringAnySize, sizeof(myStringAnySize), stdin); // from user input
        printf("Input = %s\t", myStringAnySize); //test point
      fclose(fp);
    
      fopen("Str02.txt", "r");        // Open file for read
        fread(myReadStringAnySize, 1,??????, fp); // how many chars to read?
        print("%s\n",myReadStringAnySize);
      fclose(fp);
    }// main
    
  • kuronekokuroneko Posts: 3,623
    edited 2013-09-13 18:03
    If you have the patience, the next example is a string of unknown length.
    I think it is close, but I don't know how to set number of characters to read - the ????? below.
    I'd use fgets again, e.g.
    fgets(myReadStringAnySize, sizeof(myReadStringAnySize), fp);
    
    This implies that your buffer is large enough to be able to hold the longest string from your file (which you have to write the string to, you don't currently do that). Otherwise fgets will simply stop after the buffer has been filled which may be considered an error anyway.

    It's also a good idea to start checking for errors (e.g. fp may be NULL).
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-09-13 18:49
    I'm using SimpleIDE and just hit F8 to compile, load, run ad open Terminal. how would I add the -Wall option?
    -Wall is enabled by checking the "All Warnings" box, which is located by clicking on the "Compiler" tab at the bottom of the "Project Manager" panel. If you are in the "Simple View" mode you need to enable the "Project View". This is done by clicking on "Tools" on the top tool bar, and then clicking on "Set Project View". The warnings will appear in the "Build Status" panel when you build your project.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-09-13 19:49
    Dave Hein wrote: »
    -Wall is enabled by checking the "All Warnings" box, which is located by clicking on the "Compiler" tab at the bottom of the "Project Manager" panel. If you are in the "Simple View" mode you need to enable the "Project View". This is done by clicking on "Tools" on the top tool bar, and then clicking on "Set Project View". The warnings will appear in the "Build Status" panel when you build your project.
    Isn't -Wall the default in the simple view mode? It seems like it would be helpful to beginners.
  • John KauffmanJohn Kauffman Posts: 653
    edited 2013-09-16 17:14
    Last week I got the print to terminal problems settled. Thanks for your help.
    I still have the problem of gibberish on the SD file. I get this:
    l ,
  • kuronekokuroneko Posts: 3,623
    edited 2013-09-16 17:19
    Last week I got the print to terminal problems settled. Thanks for your help.
    I still have the problem of gibberish on the SD file. I get this:
    l ,
  • SRLMSRLM Posts: 5,045
    edited 2013-09-16 17:19
    I don't know, but I think fwrite writes the binary value of the data given, not it's ascii equivalent. So you need to pass it ASCII characters rather than raw numbers if you want the resulting file to be in plain text. You'll need a Dec type routine (itoa?) to convert temp to a ASCII sequence.

    Edit: Or do what kuroneko says...
  • jazzedjazzed Posts: 11,803
    edited 2013-09-16 18:03
    Hi,

    Generally speaking we use fprintf and fscanf for text IO with ANSI C libraries for string formatting and interpretation. Those functions tend to balloon code size though. We developed alternatives for Propeller.

    I see you've met the print function already - it is like a printf (print format), except not all ANSI features are supported.

    The print and scan functions allow using %b (not ANSI), %c, %d, %e, %f, and %s without requiring the math library. The functions include all format specifier support all the time, so they are always the same size. There are even smaller alternatives in the simpletext library.

    There are also functions that print to a buffer and get from a buffer much like ANSI sprintf and sscanf. Those functions are sprint and sscan.

    So, given those tools and fread/fwrite, you can use code space more efficiently. To summarize:

    sprint(buffer, "format", args ...) is like sprintf
    sscan(buffer, "format", args ...) is like scanf

    All of this information is available from the Help Menu or on line. Help Menu -> Simple Library Reference (simpletext for these examples).

    Hope this helps.
    --Steve
  • John KauffmanJohn Kauffman Posts: 653
    edited 2013-09-16 18:22
    Worked Perfect. Data looks beautiful. Thanks.
    I can take data from SD file, run through Word to search/replace: change commas to tabs & semicolons to CRLF. Then send to Excel for a chart.

    It looks like a hole in my understanding (as I come from PBASIC to Prop C) is the use of the ampersand before a variable name. I'll see if I can find a quick answer within Andy's tutorials and other C tutorials.

    Now it is back to the unkown number of characters example.
Sign In or Register to comment.