Está en la página 1de 18

Simple FAT y SD Tutorial Parte 3

¡Finalmente de vuelta! Perdón por tomar un tiempo, pero para que funcionen las tarjetas SD se
requirió bastante investigación. En esta parte del tutorial, comenzaremos a hablar con la tarjeta
SD. Una vez que lo haga funcionar, será fácil agregar la biblioteca FAT desarrollada en la parte
anterior .
Probablemente este tutorial sea el más desafiante cubierto en mi blog hasta el momento, así que
ten cuidado: es posible que tengas que solucionar algunos problemas en este caso. Si tiene
problemas, le recomiendo que haga cualquier pregunta en el tema del foro tutorial AVR
Freaks , ¡para que más gente pueda ayudarlo que a mí!
Configuración básica de hardware: ATmega88 con
consola UART

El UART de 3.3V que cubrí hace un tiempoformará la base de este proyecto. El único cambio
que haremos es reemplazar ATtiny2313 con ATmega88. Esto se debe a SPI, Dakota del Sur y
el código de FAT se comen casi 3 kB de memoria de programa, y los chips de ATtiny con esa
memoria programa mucho y pines RX / TX y SPI separados no son tan comunes, mientras que
ATmega88 está fácilmente disponible (48 y 168 trabajo también, por supuesto). Para acomodar
el nuevo chip, se realizan los siguientes cambios de hardware en la versión ATtiny2313:
 ATmega88 requerirá dos conexiones a tierra
 Además de VCC, también AVCC para circuitos analógicos debe ser conectado a VCC
 Se recomienda un condensador adicional entre AVCC y GND (utilicé 10 uF)
 El encabezado de programación MOSI / MISO / SCK también está en un lugar diferente
Supongo que ahora es capaz de cablear el ATmega correctamente, pero para facilitar las cosas,
conecté un diagrama de pinout con los cables RXD / TXD marcados con verde (van a
MAX3232 o circuito RS232 similar), VCC / GND marcado con rojo / azul, clavijas de cristal
con clavijas amarillas y SPI / de programación con negro. Estos son todos los pines que deben
conectarse en este proyecto.
Además, las instalaciones UART de la familia ATmega difieren un poco de ATtiny2313, por lo
que nuestros métodos de ayuda necesitan ajustes:
void USARTInit ( unsigned int ubrr_value ) { // Establecer velocidad en baudios UBRR0H =
( char sin signo ) ( ubrr_value >> 8 ); UBRR0L = ( char sin signo ) ( ubrr_value & 255 ); //
Formato de fotograma: asíncrono, sin paridad, 1 bit de parada, tamaño de char 8 UCSR0C =
( 1 << UCSZ01 ) | ( 1 << UCSZ00 ); // Habilita el receptor y el transmisor

UCSR0B = ( 1 << RXEN0 ) | ( 1 << TXEN0 ); } char USARTReadChar () { // bloqueando


while (! ( UCSR0A & ( 1 << RXC0 ))) {} devuelve UDR0 ; } void USARTWriteChar ( datos
de char ) { // bloqueando while (! ( UCSR0A & ( 1 << UDRE0 ))) {}

UDR0 = datos ; }

Y, por supuesto, los fusibles son diferentes para nuestro reloj de 20 MHz que para
ATtiny2313. Utilicé un archivo de FF y un hfuse de DD. Antes de continuar, le aconsejo que
muestre el ATmega88 con el programa echo simple del tutorial para ver si el UART ATmega88
funciona como debería. Puedes obtener eso aquí .
Nota de hardware: si no tiene un MAX3232 con capacidad de 3.3V o un CI similar, pero tiene
una pantalla LCD con capacidad de 3.3V, puede reemplazar las rutinas de impresión con
escrituras de LCD y usar interruptores como entradas en lugar de un programa de
terminal. Además, vea mi artículo de cambio de nivel si desea ejecutar ATmega88 de 5V pero
tarjeta SD de 3.3V, ¡la elección es suya!
Cableado de la tarjeta SD al proyecto
Para este proyecto, necesitará una tarjeta SD vacía de 1 o 2 GB (las más pequeñas también son
correctas) formateada en FAT16 (Windows simplemente dice "FAT", ¡simplemente no
seleccione FAT32!). Copie un pequeño archivo de texto llamado README.TXTa la carpeta
raíz. Tenga en cuenta que el archivo debe estar en MAYÚSCULAS, de lo contrario el código
sensible a mayúsculas no lo encontrará más adelante. También una tarjeta microSD funcionará
si tiene una tarjeta adaptadora o un conector adecuado (por ejemplo, SparkFun vende varios
modelos). Para conectar la tarjeta a una placa de prueba, tiene algunas alternativas fáciles:
1. Si usa una tarjeta microSD y tiene un adaptador SD de repuesto, solo suelde los cables o
póngale un encabezado, como en este tutorial . ¡Un bonito adaptador ad hoc para placa
microSD!
2. Aún más fácil si tiene un encabezado de pin de 2 filas, simplemente coloque la tarjeta SD entre
las filas y apriételo con un trozo de cartón en la parte posterior, al igual que aquí
Elegí la opción 2. Tuve algunos problemas con algunas tarjetas que no respondían a SPI, y
descubrí que el código comenzó a funcionar una vez que empujé suavemente la tarjeta SD
hacia los pines mientras el sistema estaba funcionando, agregando un papel delgado además del
una pieza de cartón lo arregló, así que si tienes problemas de comunicación, ¡primero intenta
agregar algo de relleno!

Una vez que tenga medios para conectar la tarjeta SD a la placa de prueba, debe conectarla a
ATmega88. Puedes ver el pinout arriba. Las clavijas GND y 3.3V son fáciles, solo conéctelas a
los rieles de alimentación relevantes en la placa (recuerde: las tarjetas SD probablemente se
dañarán si las opera a 5V). MISO, MOSI y SCK van a los pines ATmega88
correspondientes. CS (Selección de circuito) está conectado al pin SS (Selección del esclavo,
esencialmente otro nombre para la misma cosa). Los pads no marcados no están conectados a
nada. Consulte la foto del artículo a tamaño completo para ver una tarjeta SD de ejemplo
conectada a la placa de prueba: el cable blanco es MISO, el amarillo es SCK, el verde es MOSI
y el rojo es CS / SS.
La tarjeta SD conectada a los pines ATmega88 SPI a veces interfiere con la programación
de MCU. Si obtiene errores de suma de comprobación con AVRdude, desconecte la
tarjeta SD, el flash y vuelva a conectar la tarjeta SD.
Comunicación SPI con la tarjeta SD
El hardware está listo, pero ahora necesitaremos desarrollar algún software para hablar con la
tarjeta SD. Si tienes un Bus Pirate (recientemente compré uno, es realmente bueno :), puedes
probarlo manualmente en este momento. Incluso si no lo hace, recomiendo hojear el artículo
BusPirate SD de Nathan Dyer , ya que muestra los cuatro comandos que necesitamos para
hablar con la tarjeta SD, así como también la respuesta esperada. En la sintaxis de BusPirate,
los comandos son:
 Init e ir al modo SPI: ]r:10 [0x40 0x00 0x00 0x00 0x00 0x95 r:8]
 Inicializar tarjeta: [0x41 0x00 0x00 0x00 0x00 0xFF r:8]
 Establecer tamaño de transferencia: [0x50 0x00 0x00 0x02 0x00 0xFF r:8]
 Sector de lectura: [0x51 0x00 0x00 0x00 0x00 0xFF r:520]
El protocolo utilizado para comunicarse con la tarjeta se llama SPI (Seriap Peripheral
Interface). Es el mismo que se usa para flashear chips AVR. Para nuestras necesidades, es
suficiente saber que nuestro ATmega88 será el "maestro" del bus SPI, y que la tarjeta SD será
la "esclava". Para que el esclavo escuche, tiramos de la línea de Selección de Circuito (o
Selección de Esclavo) y comenzamos a generar una señal de reloj en la línea SCK. Cada tiempo
del reloj, el maestro envía un bit usando el cable MOSI (Master Out, Slave In), y el esclavo
envía un bit usando el MISO (Master In, Slave Out). Esto se repite ocho veces, después de lo
cual las partes han transferido un byte completo. Al comunicarse con una tarjeta SD, los datos
que se reciben durante el envío se pueden ignorar, y cuando se reciben datos, el maestro debe
enviarlos todos (0xFF como un byte).
Si desea obtener más información sobre SPI (y recomiendo al menos una mirada superficial), le
recomiendo que lea el artículo de Wikipedia sobre SPI . Hay algunos detalles adicionales como
la polarización del reloj y la fase que deben ser los mismos tanto para el maestro como para el
esclavo, pero sabiendo que la configuración "lista para usar" del hardware ATmega SPI
funciona con tarjetas SD, no necesitamos considerarlos aquí. .
La sintaxis BusPirate vista arriba es bastante simple: "[" significa que la línea CS está activada
(bajada) y "]" significa lo opuesto (desactivó / subió). Un hexágono en modo SPI significa que
el hex se envía al esclavo por encima del SPI. "R" significa que se lee un byte del esclavo
(mientras se envía un 0xFF, porque las operaciones SPI siempre leen y escriben al mismo
tiempo). ": 8" significa el comando antes de que se repita ocho veces, y se puede utilizar para
operaciones de lectura y escritura. Entonces, el comando "Ir al modo SPI" realmente hace lo
siguiente:
1. Tire CS alta (anule la selección)
2. Lee 10 bytes (básicamente envía pulso CLK 80 veces para dar tiempo a la tarjeta SD para
inicializar)
3. Tire de CS bajo (seleccionar)
4. Enviar 0x40 (comando "ir al modo SPI", CMD0)
5. Enviar cuatro bytes cero (el protocolo SD tiene argumentos de 4 bytes)
6. Enviar 0x95, la suma de comprobación CRC del comando y el argumento enviado
7. Lea ocho bytes e imprímalos (mientras envía 0xFF a la tarjeta)
8. Tire CS alta (anule la selección)
Los pasos 1-2 son únicos al principio, y en realidad no forman parte de la sintaxis estándar del
comando SD; solo se aseguran de que la tarjeta SD reciba 80 tics de reloj antes de que
enviemos cualquier comando. No es tan difícil, ¿no? Mientras la tarjeta SD está procesando
nuestro comando, responderá con 0xFF y una vez que esté listo, responderá con 0x01. Luego
volverá a enviar 0xFF (el mismo byte que le estamos enviando mientras lee, por
cierto). Entonces, si observas el tutorial de BusPirate, verás que una respuesta válida de 8 bytes
podría ser "0xFF 0x01 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF".
Si desea obtener más información sobre el protocolo SD, hay una hoja de especificaciones
simplificada disponible de SD Association sin firmar un NDA.
Utilizando el hardware SPI de ATmega88
Tengo algunas buenas noticias: el hardware ATmega SPI es muy fácil de usar y
comprender. Básicamente, solo necesitamos configurar los pines MOSI, SCK y SS como
salidas, y establecer algunos bits en el registro de control SPI, SPCR. Ver la hoja de datos de
ATmega88 para más detalles, este código es bastante directo desde allí (excepto la extracción
de MISO, lo agregué solo para estar seguro):
#define CS ( 1 << PB2 ) #define MOSI ( 1 << PB3 ) #define MISO ( 1 << PB4 ) #define SCK (
1 << PB5 ) #define CS_DDR DDRB #define CS_ENABLE () ( PORTB & = ~ CS ) #define
CS_DISABLE () ( PORTB | = CS ) void SPI_init () {
CS_DDR | = CS ; // Circuito de tarjeta SD seleccione como salida DDRB | = MOSI + SCK
; // MOSI y SCK como salidas PORTB | = MISO ; // pullup en MISO, podría no ser
necesario // Habilitar SPI, maestro, configurar velocidad de reloj fck / 128 SPCR = ( 1 <<
SPE ) | ( 1 << MSTR ) | ( 1 << SPR0 ) | ( 1 << SPR1 ); } sin firmar

Char SPI_write ( unsigned char ch ) { SPDR = CH ; while (! ( SPSR & ( 1 << SPIF ))) {}
devuelve SPDR ; }

Tenga en cuenta cómo he definido dos macros, CS_ENABLE()y CS_DISABLE()eso tomará


la línea CS baja y alta, respectivamente. Además, el SD SPI puede no funcionar en frecuencias
de reloj SPI más altas, por lo que se usa un divisor conservador de 128 en lugar de, por
ejemplo, 16. Utilizando las funciones anteriores, se ]r:10convierte en:
CS_DISABLE (); para ( i = 0 ; i < 10 ; i ++) // inactivo para 1 bytes / 80 relojes SPI_write (
0xFF );

Del mismo modo, podemos crear una función general para ejecutar un comando SD
como [0x40 0x00 0x00 0x00 0x00 0x95 r:8]- enviar un byte de comando, luego
argumento dword, seguido por byte CRC y finalmente algunas lecturas:
void SD_command ( unsigned char cmd , unsigned long arg , unsigned char crc , unsigned char
read ) { unsigned char i , buffer [ 8 ]; CS_ENABLE (); SPI_write ( cmd ); SPI_write (
arg >> 24 ); SPI_write ( arg >> 16 ); SPI_write ( arg

>> 8 );
SPI_write ( arg );
SPI_write ( crc ); para ( i = 0 ; i < leer ; i ++) búfer [ i ] = SPI_write ( 0xFF
); CS_DISABLE (); // imprimir bytes de lectura }

Tenga en cuenta que la parte "& 255" después de arg>>16etc. puede omitirse
porque SPI_writetoma un argumento de bytes y cualquier bit por encima de la parte inferior
8 se trunca.
Agregué los fragmentos de código anteriores a la prueba de USART y agregué algunos
comandos de impresión ( uwrite_strpara imprimir cadenas a través de RS-232
y uwrite_hexpara bytes en formato hexadecimal). Pensé que sería bueno interactuar con el
programa manualmente para un cambio, por lo que el ciclo principal solo espera que "1", "2" o
"3" sean ingresados en el terminal, y ejecuta uno de los comandos que mencioné anteriormente:
while ( 1 ) { switch ( USARTReadChar ()) { case '1' : SD_command ( 0x40 , 0x00000000
, 0x95 , 8 ); romper ; case '2' : SD_command ( 0x41 , 0x00000000 , 0xFF , 8 ); romper ;
caso '3' : comando SD ( 0x50 , 0x00000200 , 0xFF ,

8 ); romper ; } }

Intenté cada uno de los comandos: 1, 2 y 3 varias veces. Aquí está la salida: si comprueba el
tutorial de BusPirate que he vinculado anteriormente, ¡podemos ver que está
funcionando! Descárguelo spi88.custed mismo y reprodúzcalo para probarlo usted mismo:
Como ejercicio, ya puedes intentar agregar una nueva función para el cuarto comando que leerá
un sector de la tarjeta SD. Para esto, solo tendrá que escribir el comando 0x51 (leer datos) con
argumento que es el desplazamiento de datos (comenzar con 0 para volcar el primer sector) y
CRC de 0xFF (el modo SPI no comprueba CRC, por lo que siempre enviamos 0xFF después de
configurar el modo SPI ...). Después de eso, en vez de solo leer 8 bytes, lee hasta que obtenga
0x00 de la tarjeta SD para indicar que se ha procesado el comando, y luego espera 0xFE para
indicar el inicio de los datos. Luego, realiza un bucle de 512 bytes, imprimiéndolos sobre la
marcha y leyendo dos bytes adicionales (CRC).
En la siguiente parte del tutorial, haremos esto y más: ¡combine la biblioteca FAT con nuestro
código de lectura SD para obtener una biblioteca de lectura SD completa!
Finalmente, un agradecimiento especial a Mark por su donación que utilicé para cubrir parte de
los costos de compra de BusPirate. ¡Este tutorial probablemente habría demorado bastante más
sin la ayuda de depuración que tenía de esa herramienta!
Pase a la siguiente parte de este tutorial

PUBLICADO POR

Joonas Pihlajamaa
Codificación desde 1990 en Basic, C / C ++, Perl, Java, PHP, Ruby y Python, por nombrar algunos. También está
interesado en matemáticas, películas, anime y ocasionalmente slashdot de vez en cuando. Ah, y también tengo una vida
real, ¡pero no hablemos de eso! Ver todos los mensajes de Joonas Pihlajamaa
Publicado en25 de abril de 2012AutorJoonas PihlajamaaCategoríasElectrónica Etiquetasatmega88 , sd ,tarjeta sd , sd
pinout , spi , tutorial , uart
32 pensamientos sobre "Simple FAT y SD Tutorial Parte 3"

1. Martha Rodriguezsays:
27 de abril de 2012 a las 16:54

Excelente tutorial Gracias por compartirlo.


Solo comienzo a seguir este tutorial y tengo una pregunta. Usando HxD, alrededor de la
dirección 0X1CE se almacena el mensaje: "eliminar disco u otro medio. Error de
disco. Presiona cualquier tecla para reiniciar".
¿Me puedes ayudar a entender eso?
Gracias.
RESPUESTA

1. jokkebkdice:
27 de abril de 2012 a las 17:02

El MBR también es compartido por el código de arranque. Para los discos que no son del
sistema, esto comúnmente incluye un programa corto que muestra un error si el usuario intenta
iniciar desde allí. El mensaje es parte de eso, no es que usualmente intentas arrancar tu
computadora desde una tarjeta SD, pero ... :)
RESPUESTA

1. Martha Rodriguezsays:
27 de abril de 2012 a las 17:22

Vale gracias. Pero, cómo veo la entrada de la tabla de particiones, es decir, alrededor de 0x1BE
si en esa dirección se muestra este mensaje. ¿Qué estoy haciendo mal?
RESPUESTA

2. Martha Rodriguezsays:
27 de abril de 2012 a las 17:48

Hola, mi problema al usar HxD es que el bloque en mi SD entre 0x0000 y 0x 001FF es el


mismo en tu archivo text.img entre 0x10200 y 0x102FF. así que no puedo particionar la entrada
de la tabla. ¿Que puedo hacer?
Gracias.
RESPUESTA

1. Martha Rodriguezsays:
27 de abril de 2012 a las 18:12
ok, solo el problema, mi SD no MBR, y en el sector 0 veo FAT16 para una sola partición.
RESPUESTA

1. jokkebkdice:
27 de abril de 2012 a las 18:23

Sí, algunas tarjetas SD se inicializan de esa manera. A continuación, puede omitir la lectura de
MBR por completo. :)
RESPUESTA

3. Pingback: Simple FAT y tutorial SD Parte 4 »Código y vida


4. Pingback: Simple FAT y SD Tutorial Parte 2 »Código y vida

5. Shobhitdice:
11 de septiembre de 2013 a las 13:25

Gran tutorial ... me ayudó a aprender mucho sobre el sistema de archivos FAT. Estoy tratando
de probar el código SPI que ha proporcionado en esta página, pero el resultado que obtengo del
puerto serie es todo FF en comparación con el suyo FF 01 FF. He revisado las conexiones de
mi circuito, pero no puedo entender la respuesta que estoy recibiendo.
RESPUESTA

1. Joonas Pihlajamaadice:
9 de diciembre de 2013 a las 23:52

Recuerdo vagamente que, a veces, cuando la inicialización de SD no "pasaba", no devolvía ese


01 en absoluto. Lamentablemente, no recuerdo lo que estaba mal entonces, tal vez tenía que
enviar algunos relojes adicionales, o reconocer los bytes enviados, o algo así. :-re
RESPUESTA

6. nuttakorndice:
19 de septiembre de 2013 a las 10:17

quiero el código escribir txt. a la tarjeta sd con avr (atmega128) o escriba el patrón
cordial saludo
RESPUESTA

7. Rickdice:
6 de febrero de 2014 a las 06:28
No puedo obtener ninguna respuesta en USART cuando traté de ejecutar

void SD_command(unsigned char cmd, unsigned long arg,


unsigned char crc, unsigned char read) {
unsigned char i, buffer[8];
usart_pstr("SD_command");
SD_CS_ASSERT;

SPI_transmit(cmd);
SPI_transmit(arg>>24);
SPI_transmit(arg>>16);
SPI_transmit(arg>>8);
SPI_transmit(arg);
SPI_transmit(crc);

for(i=0; i<read; i++)


buffer[i] = SPI_transmit(0xFF);

SD_CS_DEASSERT;

for(i=0; i<read; i++) {


usart_transmit(' ');
usart_write_hex(buffer[i]);
}
usart_pstr("\r \n");

// print out read bytes


}
RESPUESTA

1. Joonas Pihlajamaadice:
6 de febrero de 2014 a las 10:28

Extraño. ¿Su USART funciona fuera de esa función? Usted podría intentar añadir un poco de
USART depuración envía al código SD para que pueda ver si la escritura SD cuelga en algún
momento - el primero que se me vino a la mente fue que tal vez SD no está reconociendo los
datos y el código cuelga allí.
RESPUESTA

1. Rickdice:
6 de febrero de 2014 a las 12:45
Sí, Usart está trabajando, probé la primera vez que ejecuté el programa, utilicé ATMEGA128
principal:

#define SD_CS_ASSERT PORTB &= ~0x01


#define SD_CS_DEASSERT PORTB |= 0x01
#define CS (1<<PB0)
#define MOSI (1<<PB2)
#define MISO (1<<PB3)
#define SCK (1<<PB1)
#define CS_DDR DDRB
#define CS_ENABLE() (PORTB &= ~CS)
#define CS_DISABLE() (PORTB |= CS)
void port_init(void)
{
CS_DDR |= CS; // SD card circuit select as output
DDRB |= MOSI + SCK; // MOSI and SCK as outputs
PORTB |= MISO; // pullup in MISO, might not be needed

void spi_init(void)
{
SPCR = _BV(SPE)|_BV(MSTR)|_BV(SPR1)|_BV(SPR0);
SPSR &= ~_BV(SPI2X);
}

unsigned char SPI_transmit(unsigned char data)


{
// Start transmission
SPDR = data;

// Wait for transmission complete


while(!(SPSR & (1<<SPIF)));

return SPDR;
}
int main (void)
{
unsigned char option;
port_init();
spi_init();
usart_init(BAUD_PRESCALE);

usart_pstr("USART READY!");
while(1)
{
option = usart_receive();
switch(option)
{
case '1':
usart_pstr("1 command");
SD_command(0x40, 0x00000000, 0x95, 8);
break;
case '2':
SD_command(0x41, 0x00000000, 0xFF, 8);
usart_pstr("2 command");
break;
case '3':
SD_command(0x50, 0x00000200, 0xFF, 8);
usart_pstr("3 command");
break;
}

}
}

RESPUESTA

1. Joonas Pihlajamaadice:
6 de febrero de 2014 a las 13:43

El enfoque suena sólido. Desafortunadamente, he olvidado casi todo sobre la comunicación con
SPI y la tarjeta SD desde que escribí el tutorial hace dos años, por lo que es probable que tengas
tanta suerte como yo con la depuración del código. :( Tal vez la gente de AVRfreaks o foro de
electrónica similar podría tener algo útil.
RESPUESTA

8. sergdice:
1 de mayo de 2014 a las 12:13

Hola, ¿es obligatorio leer 8 bytes después de enviar el comando SD "r: 8"? o solo necesito
esperar 0x01?
RESPUESTA

1. Joonas Pihlajamaadice:
28 de mayo de 2014 a las 11:08
Si mal no recuerdo, el protocolo SPI funciona de tal manera que el dispositivo maestro envía el
reloj, por lo que es necesario leer 8 bytes; de lo contrario, la tarjeta SD no recibirá los ciclos de
reloj que espera.
RESPUESTA

9. Dsesedice:
25 de agosto de 2014 a las 09:55

Hola, este es un gran blog. tutorial para sd.


pruebo tu código en mi atmega328 y cuando ejecuto tu código. No leo el archivo
README.TXT. más bien.
CMD 40 FF 01 FF FF FF FF FF
CMD 41 FF 01 FF FF FF FF FF
CMD 41 FF 00 FF FF FF FF FF
CMD 50 FF 00 FF FF FF FF FF
FAT err: FF
formulé mi microsd a FAT, que es lo mismo para FAT16.
no estoy seguro de por qué no funciona?
RESPUESTA

1. Joonas Pihlajamaadice:
25 de agosto de 2014 a las 13:34

Lamentablemente, mi conocimiento SD se ha evaporado en gran medida en los últimos dos


años. Sin embargo, recuerdo que tuve la mayoría de los problemas para que el SPI funcione
correctamente, por lo que lo más probable es que el candidato sea un problema con eso
(tiempos, niveles, conexiones, contacto con la tarjeta ...).
Si tienes un Bus pirate o similar, primero podrías intentar que la tarjeta responda a los
comandos manuales, eso es lo que funcionó para mí.
RESPUESTA

1. Dsesedice:
25 de agosto de 2014 a las 18:38

Hola Joonas,
gracias por su rápida respuesta.
el atmega328 corre a 16Mhz. entonces ajusto el F_CPU a 16000000
porque no tengo 20MHz en mi mano.
¿Qué piensas?
RESPUESTA

1. Joonas Pihlajamaadice:
25 de agosto de 2014 a las 20:52

Es posible que deba ajustar el valor mágico USARTinit (UBRR o lo que sea) para que coincida
también con la nueva velocidad en baudios. Sin embargo, USART es más fácil de depurar, ya
que puede ver rápidamente cuándo puede o no comunicarse a través del terminal en serie con el
dispositivo.
RESPUESTA

1. Dsesedice:
26 de agosto de 2014 a las 09:52

Lo intenté, pero todavía no funcionaba la salida sigue siendo la misma. ¿Crees que la tarjeta
micro SD también funcionará en tu código? no tengo tarjeta SD.

2. Joonas Pihlajamaadice:
26 de agosto de 2014 a las 11:29

MicroSD debe tener la misma función de pin, por lo que no hay diferencia.

10. Dsesedice:
26 de agosto de 2014 a las 15:46

Hola Joonas,
De hecho, hago todo. como fortmating el microsd a Fat16. y piensas que tus códigos están
funcionando. porque cuando elimino la tarjeta me sale este "SD err". luego, cuando vuelva a
colocar la tarjeta micro sd. Lo hago funcionar. pero vuelve a Fat: err ... hmmm muy confuso.
qué está mal entonces
RESPUESTA

11. Pingback: Código y vida - Simple FAT y SD Tutorial Parte 4 |kmestore DIY

12. QianFandice:
27 de marzo de 2015 a las 08:24

Hola:
me gusta mucho esta web, su fuente, su color y ¡todo! Serials artical me presentó para aprender
la tarjeta SD y el formato FAT.
Lo siento por mi inglés pobre, ¡proveniente de un condado que no es inglés!
QianFan ¡
Gracias!
RESPUESTA
13. Julianosays:
3 de mayo de 2015 a las 18:11

¡Hola amigo! ¡Primero quiero agradecerle por el tutorial! Estoy aprendiendo mucho ...
Estoy usando un Atmega8 y una tarjeta mini SD con adaptador, se almacenan algunos datos de
los sensores instalados en el microcontrolador para ... Me encuentro con un error de arranque
FAT16, más precisamente, la función " fat16_init () "está lanzando un error:" "FAT err:
FF". Revisé el código y en el archivo "fat16". c "la función" fat16_init () "contiene un centinela
que guarda el archivo de inicio del sistema, en el siguiente fragmento de código:
Si (i == 4) {
Ninguna de las particiones fue FAT16
devuelve FAT16_ERR_NO_PARTITION_FOUND;
}
Hice todo lo que mencionaste en el tutorial, creo ... kkk
Según el error, mi tarjeta no contiene particiones en el formato "FAT16". Sin embargo,
formateé la tarjeta y creé la imagen necesaria. ¡Pero no funcionó! : /
El "sd_init ()" realizado con ¡entonces!
¿Tienes alguna idea de cuál es el problema?
¡Gracias amigo!
RESPUESTA

1. Joonas Pihlajamaadice:
3 de mayo de 2015 a las 22:52

Con tarjetas más grandes, Windows podría formatearlas FAT32. Además, algunas tarjetas
tienen particiones y otras no. No hay consejos concretos desafortunadamente a partir de aquí,
miraría los datos de la tarjeta con un editor hexadecimal como HxD y lo compararía con las
especificaciones FAT para ver qué es diferente.
También puede copiar los datos brutos de la tarjeta SD a la imagen del disco y ejecutar pruebas
en la computadora, de modo que pueda separar entre sí posibles problemas de lectura SD y
problemas de FAT.
RESPUESTA

14. Andrzejdice:
23 de noviembre de 2015 a las 01:47

Hola,
El punto 8 debe ser corregido.
8. Tire CS alto (deseleccionar)
Saludos.
Andrés
RESPUESTA
1. Joonas Pihlajamaadice:
23 de noviembre de 2015 a las 12:42

¡Gracias! Ha pasado tanto tiempo desde que escribí esto, así que voy a tomar tu palabra, no sé
cómo CS se convirtió en CD y se convirtió en bajo ...
RESPUESTA

15. Dinushadice:
24 de enero de 2016 a las 09:55

Este es un gran artículo. Estoy usando atmega32 y rus a 8MHz. Cambio el código de acuerdo a
eso. Pero cuando ingreso 1,2,3 a masilla, no da salida. ¿por qué? por favor, ayúdame.
#incluir
#define F_CPU 8000000L
#include
void USARTInit (unsigned int ubrr_value) {
// Establecer velocidad en baudios
UBRRH = (char sin signo) (ubrr_value >> 8);
UBRRL = (char sin signo) (ubrr_value);
// Formato de trama: asincrónico, sin paridad, 1 bit de parada, tamaño de char 8
UCSRC = (3 << UCSZ0);
// Habilita el receptor y el transmisor
UCSRB = (1 << RXEN) | (1 << TXEN);
}
char USARTReadChar () {// bloqueando
while (! (UCSRA & (1 << RXC))) {}
return UDR;
}
void USARTWriteChar (datos de char) {// bloqueando
while (! (UCSRA & (1 <> 4) & 15)> 4) & 15));
else
USARTWriteChar ('A' + ((n >> 4) & 15) - 10);
n <> 4) & 15)> 4) & 15));
else
USARTWriteChar ('A' + ((n >> 4) & 15) - 10);
}
void uwrite_str (char * str) {
char i;
para (i = 0; str [i]; i ++)
USARTWriteChar (str [i]);
}
#define CS (1 << PINB4)
#define MOSI (1 << PINB5)
#define MISO (1 << PINB6)
#define SCK (1 << PINB7)
#define CS_DDR DDRB
#defina CS_ENABLE () (PORTB & = ~ CS)
#define CS_DISABLE () (PORTB | = CS)
void SPI_init () {
CS_DDR | = CS; // Circuito de tarjeta SD seleccione como salida
DDRB | = MOSI + SCK; // MOSI y SCK como salidas
PORTB | = MISO; // tire hacia arriba en MISO, podría no ser necesario
// Habilitar SPI, maestro, configurar velocidad de reloj fck / 128
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << SPR1);
}
char sin signo SPI_write (char sin signo) {
SPDR = ch;
while (! (SPSR & (1 <> 24);
SPI_write (arg >> 16);
SPI_write (arg >> 8);
SPI_write (arg);
SPI_write (crc);
para (i = 0; i <leer; i ++)
búfer [i] = SPI_write (0xFF);
CS_DISABLE ();
para (i = 0; i <leer; i ++) {
USARTWriteChar ('');
uwrite_hex (buffer [i]);
}
uwrite_str ("\ r \ n");
}
int main (int argc, char * argv []) {
char i;
USARTInit (25); // 8 MHz / (16 * 19200 baudios) - 1 = 25
SPI_init ();
//] r: 10
CS_DISABLE ();
para (i = 0; i <10; i ++) // inactivo para 1 bytes / 80 relojes
SPI_write (0xFF);
while (1) {
switch (USARTReadChar ()) {
case '1':
SD_command (0x40, 0x00000000, 0x95, 8);
descanso;
case '2':
SD_command (0x41, 0x00000000, 0xFF, 8);
descanso;
caso '3':
SD_command (0x50, 0x00000200, 0xFF, 8);
descanso;
}
}
return 0;
}
RESPUESTA

1. Joonas Pihlajamaadice:
24 de enero de 2016 a las 18:57

¡Gracias! Es difícil decir por qué el código no funciona, desafortunadamente no puedo evitar
las preguntas (de lo contrario pasaría todo mi tiempo libre al respecto), por lo que sugiero que
se haga un foro de electrónica de algún tipo.
¿Qué hace el tipo de código UCSRA & (1 <> 4) & 15)> 4? Parece realmente extraño, o
WordPress cambió algo?

También podría gustarte