I'm trying to get the SD card slot to work on my ILI9340-based TFT, using avr-gcc (not Arduino). I'm looking at the Adafurit SD library and trying to copy what it's doing.
Here's some code: https://gist.github.com/randrews/1d7f6bcdb63891b29fdb
I've got the SPI pins connected to the hardware SPI pins on the AVR (ATmega328p), the SDCS pin is B2 (Arduino pin 10). I'm pretty sure the wiring is correct because the display works perfectly (by the way, this display rocks).
What I do is, plug in an SD card, try to send it the "enter idle mode" command, and expect to read back 0x01. I've never gotten anything but 0xFF from the card, though, no matter what I send it.
I've tried different cards, different wires, different clock speeds, different SPI clock divs (it's at div 128 on this one, the slowest it can go, although the screen is totally reliable at full-speed SPI / 16 MHz. Did I mention I love this screen?). It's not the formatting because I can't even get it to respond to idle mode, but the format is FAT32.
What on earth am I doing wrong?
ILI9340 SD card, what on earth am I doing wrong?
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- rbandrews
- Posts: 9
- Joined: Tue Jul 10, 2012 4:19 pm
- Franklin97355
- Posts: 23911
- Joined: Mon Apr 21, 2008 2:33 pm
Re: ILI9340 SD card, what on earth am I doing wrong?
Are you connecting to an Arduino or a custom board? If you are using an Arduino you should make sure it all works with the example code first. Let me know.
- rbandrews
- Posts: 9
- Joined: Tue Jul 10, 2012 4:19 pm
Re: ILI9340 SD card, what on earth am I doing wrong?
It's a bare ATmega328 chip on a breadboard.
I can run the CardInfo sketch fine, so it's some problem with this code, but I can't figure out what.
I can run the CardInfo sketch fine, so it's some problem with this code, but I can't figure out what.
- Franklin97355
- Posts: 23911
- Joined: Mon Apr 21, 2008 2:33 pm
Re: ILI9340 SD card, what on earth am I doing wrong?
Could you post your code here and a description or drawing of your connections between it all?
Please use the code button as shown below.
Please use the code button as shown below.
- rbandrews
- Posts: 9
- Joined: Tue Jul 10, 2012 4:19 pm
Re: ILI9340 SD card, what on earth am I doing wrong?
Sure, the code is below.
The connections are: B3 / B4 / B5 on the chip are MOSI, MISO, and SCK. SDCS is B2. Since it works with the Arduino library I'm pretty sure the wiring is correct.
The connections are: B3 / B4 / B5 on the chip are MOSI, MISO, and SCK. SDCS is B2. Since it works with the Arduino library I'm pretty sure the wiring is correct.
Code: Select all
#include <avr/io.h>
#include <util/delay.h>
// Some serial comms stuff; just using for debugging
#include "uart.h"
typedef unsigned char byte;
byte spi(byte b); // Send / receive one byte over SPI
void sd_select(int high); // Set SD CS pin high or low
int sd_command(byte cmd, uint32_t arg); // Send one command / arg pair to the SD card
byte sd_wait(); // Wait a max of 3 sec for the card not to be busy
int main(){
initUSART();
DDRB |= (1 << 2); // SD CS pin
PORTB |= (1 << 2); /* start off not selected (high) */
DDRB |= (1 << 3); /* output on MOSI */
PORTB |= (1 << 4); /* pullup on MISO */
DDRB |= (1 << 5); /* output on SCK */
SPCR |= (1 << SPR0) | (1 << SPR1); /* div 128 */
SPCR |= (1 << MSTR); /* clockmaster */
SPCR |= (1 << SPE); /* enable */
while(1){
receiveByte();
// Throw a bunch of cycles with CS high at it
sd_select(1);
for(int k=0; k < 10; k++) spi(0xFF);
sd_select(0); // Start the command
printStringHex("Wait: ", sd_wait());
printStringHex("Enter idle state: ", sd_command(0x00, 0));
sd_select(1); // end command
}
return 0;
}
////////////////////////////////////////////////////////////
byte spi(byte b) {
SPDR = b;
loop_until_bit_is_set(SPSR, SPIF); /* wait until done */
return SPDR; /* SPDR now contains the received byte */
}
void sd_select(int high){
if(high) DDRB |= (1 << 2);
else DDRB &= ~(1 << 2);
}
int sd_command(byte cmd, uint32_t arg){
spi(cmd | 0x40);
spi(arg >> 24);
spi(arg >> 16);
spi(arg >> 8);
spi(arg);
byte crc = 0xFF;
if (cmd == 0x00) crc = 0x95;
if (cmd == 0x08) crc = 0x87;
spi(crc);
int count = 0;
while(1){
byte status = spi(0xff);
if(!(status & 0x80)) return status;
if(count++ > 300) return status;
}
}
byte sd_wait() {
int count = 0;
while(1) {
if(spi(0xFF) == 0xFF) return 1;
if(count++ > 300) return 0;
_delay_ms(10);
}
}
- rbandrews
- Posts: 9
- Joined: Tue Jul 10, 2012 4:19 pm
Re: ILI9340 SD card, what on earth am I doing wrong?
Okay, well, I figured out one stupid thing I was doing: I mixed up DDRB and PORTB, so instead of taking the bit in PORTB low to select the card, I was taking the bit in DDRB low.
Which I should have figured out two hours ago when I looked at the scope trace, but I didn't. So now it's responding to the idle command correctly, which means it's probably easy sailing from here.
Which I should have figured out two hours ago when I looked at the scope trace, but I didn't. So now it's responding to the idle command correctly, which means it's probably easy sailing from here.
Please be positive and constructive with your questions and comments.