|
|
View previous topic :: View next topic |
Author |
Message |
hugojcmelo
Joined: 10 Aug 2013 Posts: 3
|
Problems to access micro SD Card |
Posted: Thu Aug 22, 2013 12:29 pm |
|
|
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
|
|
Posted: Thu Aug 22, 2013 12:48 pm |
|
|
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
|
|
Posted: Thu Aug 22, 2013 5:39 pm |
|
|
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 ) 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
|
|
Posted: Fri Aug 23, 2013 1:34 am |
|
|
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
|
|
Posted: Fri Aug 23, 2013 8:01 am |
|
|
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
|
|
Posted: Fri Aug 23, 2013 5:21 pm |
|
|
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 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Aug 24, 2013 12:36 am |
|
|
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
|
|
Posted: Sat Aug 24, 2013 12:58 am |
|
|
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!! |
|
|
|
|
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
|