CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Problems to access micro SD Card

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hugojcmelo



Joined: 10 Aug 2013
Posts: 3

View user's profile Send private message

Problems to access micro SD Card
PostPosted: Thu Aug 22, 2013 12:29 pm     Reply with quote

Hi, I'm working on a project that is supposed to do 2 little things: create a txt file and save info on it.

Hardware and software info:
I'm using pic18f4550, micro SD Card 2Gb Fat32 + wave share micro SD Storage board ( http://www.wvshare.com/product/Micro-SD-Storage-Board.htm )

MPLAB 8.83 + CCS PCWHD 4.114

I'm using this code (with fat and mmcsd bug fix by Andrew)
Code:

#include <18F4550.h>

//Palha
#device ADC = 10
#device PASS_STRINGS = IN_RAM
#fuses XT, NOWDT, NOPROTECT, HS,INTRC_IO, NOWDT, PUT ,BROWNOUT, NOLVP
//HS,NOWDT,NOPROTECT,NOLVP, HS,XT, NOWDT, NOPROTECT, HS,INTRC_IO, NOWDT, PUT ,BROWNOUT, NOLVP
#use delay(clock=8000000) 

#use rs232(baud=9600, UART1, errors)

#include <string.h>
#include <stdlib.h>
# include <math.h>

//media library for FAT. CONFIRMAR PINOS COM SPI

//meda library, a compatable media library is required for FAT.
#use fast_io(c)
#define MMCSD_PIN_SCL     PIN_B1 //o
#define MMCSD_PIN_SDI     PIN_B0 //i
#define MMCSD_PIN_SDO     PIN_C7 //o
#define MMCSD_PIN_SELECT  PIN_A5 //o
#include <mmcsd.c>
#include <fat.c>

#include <input.c>


long valordigital=0;
#define PORT_A                  0               // define for function output()
#define PORT_D                  3

#define NCHAR_PER_LINE          16              // max char numbers per line
#define LCD_RS                  PIN_A1
#define LCD_RW                  PIN_A2
#define LCD_E                   PIN_A3
#define LCD_DAT                 PORT_D

char *fileName;


/*=====================================LCD==========================================*/
///////////////////////////////////////////////// output()
//lcd data bus output
void output(int8 port, int8 dat)
{
        switch(port)
                {
                case PORT_A: output_a(dat);      break;
                case PORT_D: output_d(dat);      break;
                default :       //??? port maybe error!
                        break;
                }
}//end output()

//////////////////////////////////////////////// lcd_write_cmd()
//
void lcd_write_cmd(int8 cmd)
{
        delay_us(400);
        output_low(LCD_RS);
        output_low(LCD_RW);
        output(LCD_DAT, cmd);

        output_high(LCD_E);
        delay_us(400);
        output_low(LCD_E);
}//end lcd_write_cmd()

/////////////////////////////////////////////// lcd_write_dat()
//
void lcd_write_dat(int8 dat)
{
        delay_us(400);
        output_high(LCD_RS);
        output_low(LCD_RW);
        output(LCD_DAT, dat);

        output_high(LCD_E);
        delay_us(400);
        output_low(LCD_E);
}//end lcd_write_dat()

//////////////////////////////////////////// lcd_init()
//
void lcd_init(void)
{
        output_low(LCD_E);              // Let LCD B line low

        lcd_write_cmd(0x38);            // LCD 16x2, 5x7, 8bits data
        delay_ms(15);
        lcd_write_cmd(0x01);            // Clear LCD display
        delay_ms(10);
        lcd_write_cmd(0x0f);            // Open display & current
        delay_ms(10);
        lcd_write_cmd(0x06);            // Window fixed
        delay_ms(10);
}//end lcd_init()

///////////////////////////////////////// lcd_display_char()
//
void lcd_display_char(int8 line, int8 pos, int8 ch)
{
        int8 tmp;

        line = (line==0) ? 0 : 1;
        pos  = (pos >NCHAR_PER_LINE) ? NCHAR_PER_LINE : pos;

        tmp = 0x80 + 0x40*line + pos;
        lcd_write_cmd(tmp);
        lcd_write_dat(ch);
}//end lcd_display_char()

/////////////////////////////////////////// lcd_display_str()
//
void lcd_display_str(int8 line, char str[])
{
     int8 i;

        for(i=0; i<NCHAR_PER_LINE; i++)
            {
                lcd_display_char(line, i, ' ');
                }
        for(i=0; i<NCHAR_PER_LINE; i++)
                {
                if(str[i] == '\0') break;
                lcd_display_char(line, i, str[i]);
                }
}//end lcd_display_str()
/*==================================================================================*/
void main(void)
{
    char filename[]="teste.txt";
   setup_oscillator(OSC_4MHZ);
    mmcsd_init();
   fat_init();
   if (fat_init()) //teste to fat_init
      {
      output_high(PIN_B3);
      delay_ms(300);
      }
   else
      {
      output_high(PIN_B5);
      delay_ms(300);
      }
   mk_file(filename);
   //Now write something......
   
    while (TRUE);  // end loop
      {
      output_high(PIN_B4);
      }
   
}


The problem is: I can program the device and he returns 'signals of life'. I mean, the storage board starts blinking for a few moments (like 30s) and the only led that goes high is the last one, meaning end of process.
When i open the card, it is empty.
If someone can help me, I would appreciate that.
Best regards,
Hugo Melo
PS: Sorry bad english
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Aug 22, 2013 12:48 pm     Reply with quote

Code:
#fuses XT, NOWDT, NOPROTECT, HS,INTRC_IO, NOWDT, PUT ,BROWNOUT, NOLVP
It is only allowed to have 1 clock source specification. Now you have XT (for external crystal <4MHz), HS (external crystal > 4MHz) and INTRC_IO for the internal oscillator.
I don't know what the compiler makes out of this but to me the result is undefined and VERY wrong.

Code:
#use delay(clock=8000000)

...

   setup_oscillator(OSC_4MHZ);
What is your speed? 4MHz or 8MHz ???
Please create the very basic LED blinking program where the LED blinks 1 times per second so you can confirm the clock is running at the speed you think it is running.

Code:
   fat_init();
   if (fat_init()) //teste to fat_init
Get rid of the first line!
You should call fat_init() only once and always test for the result value as this tells you if it makes sense to continue or not.
You didn't tell us this result. Is PIN_B3 high or PIN_B5?

Then, you did add a test for fat_init, but what about mmcsd_init() that is in the line before? When mmcsd_init() fails your program should stop. Add a test here as well.

Add a test for the mk_file() return value. It will tell you if the file creating went well. You can change fat.c to add more different error codes for each of the different possible errors.

What voltage is your PIC running? I hope it is 3.3V and not 5V. With 5V you possibly killed your SD card.
hugojcmelo



Joined: 10 Aug 2013
Posts: 3

View user's profile Send private message

PostPosted: Thu Aug 22, 2013 5:39 pm     Reply with quote

Thanks for reply,

I deleted HS and HS Fuses, i want work with 8MHz speed.

I deleted the first fat_init() as you said and now i got the following main()
Code:
void main(void)
{
    char filename[]="teste.txt"; 
   if (mmcsd_init())
      {
      output_high(PIN_C0);
      delay_ms(300);
      }
   else
      {
      output_high(PIN_C1);
      delay_ms(300);
      }
   
   if (fat_init())
      {
      output_high(PIN_B3);
      delay_ms(300);
      }
   else
      {
      output_high(PIN_B5);
      delay_ms(300);
      }
   mk_file(filename);
   //Now write something......
   
    while (TRUE); 
      {
      output_high(PIN_B4);
      }
   
}


As I said before, only the LED B4 goes high, in the end of the process, none of the others go high, when i test mmcsd_init() both LEDs stay low, and same happen with test fat_init() (leds are working fine).

I haven't killed SD Card (for now Smile ) cause I can use it on computer.
PIC works with 5V and the Card with 3,3V. I have pull up(10k) in B0 (MMCSD_PIN_SDI) and voltage dividers (1k and 2k to GND) in B1, C7 and A5 (SDO, SCL, CS).

I receive no result from testes and nothing on Card again. :-/
One more change is that the led's board dont blink anymore.
Thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Aug 23, 2013 1:34 am     Reply with quote

OK. The card is not going to work (which is why it doesn't....).

You _need_ buffering between the 3v output of the SD card, and the 5v input of the PIC.
This is one of the commonest 'wrong' circuits on the web.

Go to the Brush Electronics page:
<http://www.brushelectronics.com/>

At the very bottom of the page, on the line:

"SD/MMC Card integration troubleshooting guidelines can be found here", select the 'here'.

Read this, and look at the two circuits given. The second shows the _minimum_ interface required. A single transceiver on the line from the SD to the PIC, and resistors to attenuate the signals in the other direction.

Problem is that the SDI line on the PIC, requires the signal to go 'up' to about 4v, before it is seen as a 'high'. A 3.3v card, just can't do this. So you have to have a transceiver, that accepts something like a 2.4v as 'high', and amplifies the signal up to the PIC input level.

Alternative is to use a 3.3v PIC (simplifies everything), like the PIC18F46J50, which is basically compatible with the 4550, but at 3.3v, and adding a lot of extra stuff if required.

The 'reason' for the wrong circuit, is that it is _just_ possible on some 5v PIC's to use software SPI (would need to change the CCS driver to use spi_xfer, instead of spi_read/write), select PIC pins that have TTL input levels, and make the circuit work. Makes the interface very slow though, and is significant work. Unfortunately, the circuit got published, and has been copied by lots of people, without understanding it's limitations, and results in the same lot of people having problems getting SD to work....

In your case, if you can get the LF version of your PIC, this can operate at 3.3v (but you can't then use the USB voltage regulator), at up to 18.7Mhz. Power the PIC off 3.3v, directly connect to the card (no attenuators), and provided the rest of your circuitry is built for 3.3v operation, things have a hope of working. The standard 'F' version requires 4.2v minimum.

Best Wishes
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Aug 23, 2013 8:01 am     Reply with quote

As Ttelmah said, the MMC isn't going to work because the PIC's SPI data input is a Schmitt Trigger input requiring a minimum of 4.1V for high level.
I think I just discovered how all these 'wrong' circuits got on the internet: the Atmel ATmega processors have standard TTL I/O on the SPI bus, there an input is seen as high level at 0.6 * Vcc = 0.6 * 5V = 3V
So, all those countless interface boards designed for Arduino will work with this 'wrong' design.

In the reference design pointed to by Ttelmah, Andrew (from Brush Electronics) used a 74ACT125D in combination with a diode on the CS line to create a 3.3V to 5V conversion.
If you don't want to mount a 14 pin 74ACT125D just to use 1 of the 4 available buffers, you can also create an interface using a MOSFET and a few resistors:
- Sparkfun has an Application Note on this: https://www.sparkfun.com/tutorials/65
- Microchip too: Tip #6 3.3V -> 5V Using a MOSFET translator (page 8-6)

Quote:
As I said before, only the LED B4 goes high, in the end of the process, none of the others go high, when i test mmcsd_init() both LEDs stay low, and same happen with test fat_init() (leds are working fine).
This is very strange. Have you tried the basic LED blinking program as I suggested? Just to confirm the processor is running at the correct speed and LEDs are working.
hugojcmelo



Joined: 10 Aug 2013
Posts: 3

View user's profile Send private message

PostPosted: Fri Aug 23, 2013 5:21 pm     Reply with quote

Thanks a lot!! both of you!

Now i undertand my problem. I thought that if I use a voltage divider on the outputs from PIC, and a pull up resistor on the PIC input, it would work.

Still remains a lot of work to be done. As student, all those headaches improve my knowledge, and one more time, thanks a lot for your help.

I have ordered today both 74ACT125D and 74LCX125D. I'll wait a few days so, I'll stand by for now.

Quote:
This is very strange. Have you tried the basic LED blinking program as I suggested? Just to confirm the processor is running at the correct speed and LEDs are working.


I did! I tried this code and works fine, 1 blink/s :
Code:

void main(void)
{
   while (TRUE); 
      {
      output_high(PIN_B4);
      delay_ms(500);
      output_low(PIN_B4);
      delay_ms(500);
      }
 
}


I got one more question. If I create a txt file on the Card and append some values from my sensor/adc, will I be able to see the file on windows (using the SD drive and open the file on Notebook) or will I need adicional software (like HexEditor)?

Best regards,
Hugo Melo Smile
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Sat Aug 24, 2013 12:36 am     Reply with quote

Once you are talking to the SD card, a 'txt' file can be opened with anything (including just simply notepad).
You may want to be a bit more 'formal' in your layout, to make it easier for programs to do things, but it becomes readable by anything.
I commonly use variants of 'CSV' (comma separated value) files. With a time-stamp, and various readings on a line, including a LF at the end. but tend to pad the 'line' so it is a even sub factor of the sector size (so perhaps 32 characters, or 48 character - 16, or 12 per sector). Advantage is that after 16 readings (or 12), you can do a nice simple single sector 'write', and can scan forward more quickly in the PC code to find a particular date/time, without having to read 'line by line'. Being CSV, you can even display the data in things like Excel, relatively easily.

Best Wishes
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Sat Aug 24, 2013 12:58 am     Reply with quote

Don't forget to close the file on the PIC before you remove the card. The file system drivers write to the physical media in 512 byte blocks. When your application code performs a write it is made to a buffer in RAM. This buffer is written to the media when it becomes full or when the file is closed.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group