PicManía by RedRaven
 

Búsqueda personalizada

 

PROYECTOS : AUX MMC Card

 

 

Circuito auxiliar para Leer y escribir tarjetas MMC (MultiMedia Card)



 

Descripción:
 
  • Este circuito auxiliar se encarga de actuar de Driver entre el PIC y la tarjeta MMC. Nace este proyecto MMC Card : Hardware & Firmware con un poco de camino recorrido. Hasta ahora solo estamos a nivel de pruebas iniciales, pero a poco que le echemos un poco de esfuerzo pronto alzará el vuelo.

 
Circuito:
 
  • El hardware que estoy utilizando es el que corresponde al esquema que podéis ver mas abajo:
 

 
  • El diseño de este hardware lo he realizado dándome algunas miles de vueltas por la Web, por el Foro TODOPIC y por el CCS C Forum. Pero quizás el que mas me ha influido es el que aparece en la página Captain Universe realizado con un PIC 16F876A (antiguo y buen amigo este PIC) que yo he adaptado a mi 18F2550 de la iACV1.

  • El conector para la MMC Card es el YAMAICHI FLS007-3003-0 que podéis encontrar en RS con el código 493-2018. El componente no existe para Eagle 4.16r1 así que me lo he fabricado yo mismo. ( ver PCB Eagle Layout Editor)


 

  • La fuente de 3.3 está construida alrededor de un LT1585CT3.3 que los amables señores de Linear tuvieron a bien enviarme como sample el pasado mes de Noviembre de 2006. Los dos condensadores de 10 uF son los que el Datasheet recomienda como necesarios para el buen funcionamiento del regulador.
  • Las señales SPI a manejar son DI (Data Input) DO (Data Output)  CK (Clock) y CS (Slave Select Input) todas ellas de 3.3V
  • Como DO es la única que va desde la MMC hacia el PIC y éste reconoce cualquier señal por encima de unos 2.0V como un HIGH no tenemos que hacerle nada para conectarlo, pero las demás tienen el sentido contrario, desde el PIC hacia la MMC, por lo que deben reducir su voltaje de 5V a 3.3V. Por ello construimos un divisor de tensión alrededor de las resistencias R1 y R4 para CK, R2 y R5 para DI y R3 y R6 para CS. Los valores de 1K8 y 3K3 utilizados hacen que los 5V de la señal del PIC pasen a ser nuestros 5*3300/(3300+1800)=3.24V.
Circuito Impreso:
 
  • El conector de la MMC Card es SMD así que al realizar el PCB le he dado la vuelta utilizando la herramienta "mirror" del Eagle para colocarlo en la cara inferior y el resto de componentes por encima, normalmente. El PCB resultante es:
     


 

  • Con esto el Hardware está descrito, y como os comenté mas arriba no he llegado a fabricar el PCB sino que lo he montado sobre una placa de taladros, pero siguiendo el mismo esquema, y ¡funciona! (podéis verla mas abajo)
Implementación provisional para pruebas:
 
 

 

 

 
Firmware inicial para pruebas:
 
  • La comunicación entre el PIC y la MMC Card se realiza mediante el protocolo Síncrono SPI. Como el PIC 18F2550 dispone de un modo de funcionamiento de la USART específico para el SPI parecería lógico usarlo y en paz, pero el hardware de la placa iACV1 tiene la USART dedicada a sus comunicaciones con el módulo Ethernet Tibbo EM202 así que lo que he decidido es emular la comunicación SPI por software. No ocupa mucho y funciona correctamente.
  • Todo el protocolo está construido alrededor del Driver de CCS C "mmc_spi.c" que podéis encontrar en el directorio Drivers de la instalación de dicho compilador.
  • Lo único importante a tener en cuenta al usar este driver es configurar los defines que dicen qué pines vamos a utilizar para cada una de las funciones SPI (DO, DI, CK y CS) "antes" del include del driver <mmc_spi.c> ya que en caso contrario estos defines no tendran efecto al ser compilados "después" que el código del driver.
  • En mi caso concreto he optado por usar los primeros pines del PORTB (que además son los que tengo disponibles en las clemas de la iACV1):
#define MMC_CS    PIN_B3
#define MMC_CLK   PIN_B2
#define MMC_DI    PIN_B0
#define MMC_DO    PIN_B1
 
  • Os pongo la cabecera con las funciones disponibles en el driver CCS C:
////////////////////// Driver for Multimedia Card ///////////////////////
////                                                                 ////
////  mmc_init() - Reset and Initialize the MMC.  Returns zero if OK ////
////                                                                 ////
////  mmc_modify_byte(address, val) - Modify the byte at address to  ////
////               change it's value to val.  Will read/write the    ////
////               entire 512 byte block but only change this        ////
////               specific byte.  Returns zero if OK.               ////
////                                                                 ////
////  mmc_modify_block(address, size, *ptr) - Modifies the bytes     ////
////               to change their value to whats stored at *ptr.    ////
////               Will read/write the entire 512 byte block(s) but  ////
////               only change the values defined by ptr and size.   ////
////               Returns zero if OK.                               ////
////                                                                 ////
////  mmc_write_block(address, size, *ptr) - Writes a 512 byte       ////
////               block to the MMC.  If size is less than 512 then  ////
////               unspecified data will be written as 0.  Returns   ////
////               zero if OK.                                       ////
////                                                                 ////
////  mmc_read_byte(address,*ptr) - Reads the byte specified at      ////
////               address.  Result is saved to ptr.  Returns zero   ////
////               if OK.                                            ////
////                                                                 ////
////  mmc_read_block(address, size, *ptr) - Reads the bytes          ////
////               specified at address.  Result is saved to ptr.    ////
////               Returns zero if OK.                               ////
////               NOTE: You might get an address error if you try   ////
////               to read over a page size.  For example, trying    ////
////               to read a block size of 512 starting at address   ////
////               0x100 may cause an error because you are reading  ////
////               two blocks.                                       ////
////                                                                 ////
////  mmc_erase(address, blocks) - Erases the block specified at     ////
////               address.  Will erase the entire 512 byte block.   ////
////               If you wish to erase more blocks after specified  ////
////               block use the blocks parameter to specifiy how    ////
////               many extra blocks to erase.  Returns zero if OK.  ////
////                                                                 ////
////              ~~~~~~~ MULTI-READ FUNCTIONS ~~~~~~~~              ////
////                                                                 ////
////  mmc_read_enable(address, size) - Start multi-reads at          ////
////               specified address.  Size is the size of each      ////
////               individual read.  Returns zero if OK.             ////
////                                                                 ////
////  mmc_read_mult_block(*ptr) - Reads data from the MMC, and saves ////
////               to ptr.  The number of bytes read is defined      ////
////               by mmc_read_enable().  You must call              ////
////               mmc_read_enable() before you can call this.       ////
////               Returns zero if OK.                               ////
////                                                                 ////
////  mmc_read_disable(void) - Stop a multi-read.                    ////
////               Returns zero if OK.                               ////
////               MAY BE BROKEN.                                    ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2001 Custom Computer Services         ////
//// This source code may only be used by licensed users of the CCS  ////
//// C compiler.  This source code may only be distributed to other  ////
//// licensed users of the CCS C compiler.  No other use,            ////
//// reproduction or distribution is permitted without written       ////
//// permission.  Derivative programs created using this software    ////
//// in object code form are not restricted in any way.              ////
/////////////////////////////////////////////////////////////////////////
 

Descargar rr_mmc_spi.c

 

  • Con este driver en uso he construido un Firmware inicial que solo inicializa la MMC Card y que lee bloques de información sobre un buffer de 512 bytes de largo.
  • Las lecturas se realizan secuencialmente desde la address 0 en adelante en saltos de 512 bytes. Tened en cuenta que estoy usando:
     
    • 1º.- Un driver directo, sin utilizar información sobre formateo lógico como puede ser un FAT16 o un FAT32.
       
    • 2º.- La MMC Card que estoy usando estaba ya en uso en una cámara digital o un móvil por lo que la información que contiene está formateada y no sé cuál puede ser.
  • El firmware versión v.0.0.0 es (Le he quitado lo relativo a hacer funcionar el Led, el Buzzer y el Rele del que dispone el hardware iACV1) :
////////////////////////////////////////////////////////////////////////////////////
//
// MMC Card Test ...
// by RedPic
////////////////////////////////////////////////////////////////////////////////////

#include <18f2550.h>
#fuses HS,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN,NOLVP,NOCPD,NODEBUG,NOWRT,NOVREGEN
#use delay(clock=20000000)

#define EM202_MD   PIN_A0
#define EM202_RST  PIN_A1
#define EM202_CTS  PIN_A2
#define EM202_RTS  PIN_A3
#define EM202_DTR  PIN_A4
#define EM202_DSR  PIN_A5
#define EM202_RX   PIN_C6
#define EM202_TX   PIN_C7

#define LED        PIN_C0
#define BUZZER     PIN_C1
#define RELE       PIN_C2

#use rs232(baud=19200, xmit=EM202_RX, rcv=EM202_TX)

char  cRec=0x00;                            // Último caracter recibido via serie
char  Command=0x00;                         // Comando a procesar

int8  MMCBuffer[512];
int32 address=0;


#define MMC_CS    PIN_B3
#define MMC_CLK   PIN_B2
#define MMC_DI    PIN_B0
#define MMC_DO    PIN_B1

#include "rr_mmc_spi.c"

////////////////////////////////////////////////////////////////////////////////////
//
// Funciones ...
//
////////////////////////////////////////////////////////////////////////////////////

void Cursor(char c){

   printf("%c\r\n>",c);
}

void Presenta_Hardware(void){

   printf("\r\n\n");
   printf("MMC MultiMedia Card Driver Test\r\n");
   printf("Hardware iACCESS CONTROL V1 v.0.0.0\r\n\n");

   printf("Commands when available:\r\n\n");
   printf("[X] Reset EM202 Ethernet Module\r\n");
   printf("[M] Init MMC Card\r\n");
   printf("[F] Read MMC Card Block First\r\n");
   printf("[R] Read MMC Card Block Actual\r\n");
   printf("[ ] Read MMC Card Block Next\r\n\n");
   Cursor(0x00);
}

void Reset_EM202(void){

   OUTPUT_HIGH(EM202_MD);
   OUTPUT_HIGH(EM202_RST);
   delay_ms(110);
   OUTPUT_LOW(EM202_RST);
   delay_ms(110);
}

////////////////////////////////////////////////////////////////////////////////////
//
// Interrupción por Recepción Serie RS232
//
////////////////////////////////////////////////////////////////////////////////////

#int_rda
void handle_rda_int(){

   if(kbhit()){                             // Si hay algo pdte de recibir ...
      cRec=getc();                          // lo recibo sobre cRec ...
      if(cRec!=0x00){                       // Si es distinto de \0 ...
         Command=ToUpper(cRec);             // cargo cRec sobre Command para procesarlo
      }                                     // pasándolo a Mayúsculas para no confundir.
   }
}

////////////////////////////////////////////////////////////////////////////////////
//
// Main
//
////////////////////////////////////////////////////////////////////////////////////

void main() {

   int16 f=0;
   int16 size=512;
   int8  col=0;

   disable_interrupts(global);
   disable_interrupts(int_timer1);
   disable_interrupts(int_rda);
   disable_interrupts(int_ext);
   disable_interrupts(int_ext1);
   disable_interrupts(int_ext2);

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
   setup_timer_0(RTCC_OFF);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   port_b_pullups(false);

   set_tris_a(0b00001000);
   set_tris_c(0b10000000);

   enable_interrupts(global);
   enable_interrupts(int_rda);

   Reset_EM202();

   address=0;

   do {
      if(Command!=0x00){                    // Si he recibido un comando vía Serie ...
         if(Command=='?'){                  // Si el comando es '?' ...
            Presenta_Hardware();
         }
         if(Command=='X'){                  // Reset EM202
            Cursor(Command);
            Reset_EM202();
         }

         if(Command=='M'){                  // Inicializa MMC Card
            Cursor(Command);
            if(mmc_init()==0)
               printf("MMC init ok");
            else
               printf("MMC init fault");
            Cursor(0x00);
         }

         if(Command=='F'){                  // Read First Block MMC Card
            address=0;
            Command='R';
         }
         
         if(Command==' '){                  // Read Next Block MMC Card
            address+=512;
            Command='R';
         }
         
         if(Command=='R'){                  // Read Block MMC Card
            Cursor(Command);
            for(f=0;f<=511;f++) MMCBuffer[f]=0;
            size=511;
            col=0;
            if(mmc_read_block(address, size,&MMCBuffer[0])==0){
               printf("\r\n>MMC read ok from Address %LX to %LX\r\n",address,address+size);
               for(f=0;f<=511;f++){
                  printf("%X ",MMCBuffer[f]);
                  if(++col==16){
                     col=0;
                     printf("\r\n");
                  }
               }
            }
            else
               printf("\n\rread fault");
            Cursor(0x00);

         }
         Command=0x00;                      // Indico que ya he procesado el comando.
      }
   } while (TRUE);
}
 
  • Y como ejemplo de su funcionamiento os pego de nuevo la imagen en la que encontré una referencia a la FAT16 con que parece ser está formateada la MMC Card que estoy usando:

 

Esta página se modificó el 27/12/2008


Esta página usa la letra Ñ

Nota pública importante sobre las consultas al Webmaster de PicManía.


Sugerencias a Picmanía... (que serán leídas pero seguramente no podrán ser contestadas)

Esta página pertenece al grupo de páginas de Diego RedRaven

 

 



Nota: Esta página Web esta repleta de imágenes, textos, logotipos y demás material extraídos de los mas variados medios de los que no soy ni autor ni depositario de los correspondientes derechos de autor, uso y/o reproducción. Si Ud. es depositario de dichos derechos y desea que el material correspondiente sea eliminado de esta Web no dude en ponerse en contacto conmigo mediante e-mail y será inmediatamente retirado. Gracias.
 
Visitas
Totales : 15393 Hoy: 1 Activas: 1 Vistas: 15393

Esta página fue modificada el 07-08-2010 15:42:21

           
 DmSoft WAMP Escribir Unreal