Wednesday, September 6, 2017

Interfacing PIC16F84A with SD card


This topic shows a simple interfacing of 2 GB micro SD card with PIC16F84A microcontroller.
I used the PIC16F84A to read the SD card raw data which doesn't require a microcontroller with high RAM or ROM. In this interfacing I used software SPI because the PIC16F84A doesn't have a built-in hardware SPI module.
In this example there is no need for file systems (FAT16, FAT32 ...) because we're dealing with raw data which stored in the SD card memory spaces.
CCS IDE serial monitor is used to display the data after reading it and here the UART protocol is used. I used software UART because the PIC16F84A also does not have a UART module.
the link below shows a small PIC16F84A MCU UART example:
Software UART for PIC16F84A microcontroller
In this project I used the MMC/SD card driver for CCS C compiler which is described in the post at the link below:
MMC/SD Card driver for CCS PIC C compiler
The PIC16F84A MCU has only 68 bytes of data RAM which means that it is not possible to load an entire sector of 512 bytes, but we can read many sectors byte by byte.
Hardware Required:
  • PIC16F84A microcontroller
  • 8 MHz crystal
  • 2 x 22pF ceramic capacitors
  • SD Card
  • AMS1117 3.3V voltage regulator
  • 3 x 3.3K ohm resistor
  • 3 x 2.2K ohm resistor
  • 2 x 10K ohm resistor
  • 5 x 10uF polarized capacitor
  • 100nF ceramic capacitor
  • MAX232 chip
  • Female RS232 connector
  • Male-female RS232 cable
  • 5V Power source
  • Breadboard
  • Jumper wires
Interfacing SD card with PIC16F84A MCU circuit:
Interfacing PIC16F84A with SD card circuit
The AMS1117 3.3V voltage regulator is used to supply the SD card with 3.3V. Also, 3 voltage dividers are used to step down the 5V which comes from the microcontroller to about 3V which is sufficient for the SD card. Each voltage divider consists of 2K2 and 3K3 resistors.
The MISO of the SD card is connected directly to the microcontroller.
MAX232 integrated circuit is used to interface the microcontroller with the PC, I connected just one wire (RB3) because I need to transmit data from the SD card to the microcontroller and then from the microcontroller to the PC, there is no need to connect the second wire because I don't have to send data from the PC to the microcontroller.
In this project the PIC16F84A MCU runs with 8MHz crystal oscillator.
SD Card raw data read using PIC16F84A CCS C code:
The C code below was tested with CCS PIC C compiler version 5.051.
Software SPI is used to interface the MCU with the SD card with 4 data lines: SDI, SDO, SCL and CS.
The code below reads the SD card sector 0, sector size is 512 bytes. To be able to read the whole sector I used the function sdcard_read_byte which allows me to read any byte located in the SD card. For example the function sdcard_read_byte(200, &value); reads the byte of address 200 and saves its data (1 byte) in the variable pointer value.
The functions sdcard_init and sdcard_read_byte return 0 if OK, non-zero if error.
Complete C code is below.
// Interfacing PIC16F84A with SD card CCS C code.
// http://ccspicc.blogspot.com/
// electronnote@gmail.com

// SD Card module connections
#define   SDCARD_PIN_SDI     PIN_B7
#define   SDCARD_PIN_SCL     PIN_B6
#define   SDCARD_PIN_SDO     PIN_B5
#define   SDCARD_PIN_SELECT  PIN_B4
// End SD card module connections

#include <16F84A.h>
#fuses HS,NOWDT,PUT,NOPROTECT
#use delay(clock = 8000000)
#use fast_io(B)
#use rs232(xmit = PIN_B3, rcv = PIN_B2, baud = 9600)
#include <sdcard.c>                              // SD Card driver source file

int8 value;
int16 i;
void main() {
  output_drive(PIN_B3);                          // Configure pin RB3 as output
  printf("\r");                                  // Set cursor to first position
  printf("Read Sector 0:");
  printf("\n\r");                                // Start new line
  if(sdcard_init() == 0){                        // Initialize the SD card; returns 0 if OK, non-zero if error
    printf("Card init OK");
    printf("\n\r");                              // Start new line
    for(i=0; i<512;i++){                         // Read sector byte-by-byte (total: 512 bytes)
      sdcard_read_byte(i, &value);
      printf("%X", value);                       // Print 'value' with hexadecimal format
    }
  }
  printf("\n\r");                                // Start new line
  printf("End.");
}
Finally I got the output shown below:
Read SD card sector using PIC16F84A output