Tuesday, September 5, 2017

Read text files from FAT16 SD card with PIC16F887

Interfacing PIC16F887 with FAT16 SD card
After reading raw data (bytes and sectors) from SD card, now I'm going to use FAT16 file system to read and print text file located in 2 GB SD card.
Read SD card raw data topic:
MMC/SD Card raw data read with PIC16F887 microcontroller
UART protocol is used to display the content of the text file.
For this project, I used MMC/SD card driver for CCS C compiler which can be found in:
MMC/SD Card driver for CCS PIC C compiler
And I used FAT16 library (for reading files) for CCS C compiler which can be downloaded from:
FAT16 Library for CCS C compiler

Hardware Required:
  • PIC16F887 microcontroller
  • FAT16 formatted MMC/SD card ( <= 2 GB)
  • ASM1117 3.3 voltage regulator
  • 3 x 3.3K ohm resistor
  • 3 x 2.2K ohm resistor
  • 10K ohm resistor
  • 5 x 10uF polarized capacitor
  • 100nF ceramic capacitor
  • MAX232 chip
  • Female COM port
  • 5V Power source
  • Breadboard
  • Jumper wires
Read text files from FAT16 SD card with PIC16F887 circuit:
Read text file from FAT16 microSD card using PIC16F887 MCU circuit
As known the SD card voltage is 3.3V and the PIC16F887 voltage is 5V, so AMS1117 3.3V is used to step down the 5V in order to supply our SD card with 3.3V. Also each digital output pin of the PIC16F887 MCU can be logic 0 (0V) or logic 1 (5V) and connecting the microcontroller output pins (CS , SDO and SCK) directly to the SD card may damage it, here a voltage divider is used to get about 3V from the 5V which is enough for the SD card. The voltage divider consists of 3.3K and 2.2 K resistors. The MISO is connected directly to the SDI pin of the microcontroller because it is the data output pin of the SD card which is normally does not exceed 3.3V.
I used just one wire (RD2) to transmit data from the microcontroller to the PC (there is no need for the MCU to receive data so the receiving wire is not connected).
The chip select pin of the SD card is connected to pin RD3 (the SD card chip select pin is active low).
In this project the PIC16F887 MCU uses its internal oscillator and MCLR pin function is disabled.
Read text files from FAT16 SD card with PIC16F887 C code:
The C code below was tested with CCS C compiler version 5.051.
SD card driver and FAT16 library for CCS must be added to the project, just by putting the two source codes in the project folder or the CCS driver folder.
In this example I used the hardware SPI module of the PIC16F887, software SPI also works but the hardware one is much faster.
I named the text file "mytext" (basically it is mytext.txt) but in the CCS C code we've to add the extension of the file which becomes "mytext.txt". 
I used a read buffer of 10 bytes ( file_data[10] ), so the microcontroller reads the text file 10 bytes by 10 bytes, it reads 10 bytes and send it to the PC via RS232 then the second 10 bytes and so on until the function fat16_read_data(10, file_data) returns 1 which means we're at the end of the file.
The functions used in the C code are:
fat16_init(): initializes the SD card and the FAT16 file system, return 0 if OK and 1 if error.
fat16_open_file(txt): opens file with predefined name.
fat16_read_data(10, file_data): read data (10 bytes) from the opened file and save it in the array file_data.
printf: outputs data over RS232 where printf("%s", file_data); outputs a string of characters (file_data).
Complete C code is below.
/* Read and print text file from FAT16 microSD card using PIC16F887 MCU.
   Fat16 library and MMC/SD card driver for CCS C compiler must be installed

// SD Card module connections
#define   SDCARD_SPI_HW                          // Hardware SPI module is used for the SD card
#define   SDCARD_PIN_SELECT  PIN_D3              // SD card chip select pin is connected to pin RD3
// End SD card module connections

#include <16F887.h>
#use delay(clock = 8MHz)
#use rs232(xmit = PIN_D2, rcv = PIN_D1, baud = 9600)
#include <sdcard.c>                              // SD card diver source file
#include <fat16.c>                               // FAT16 Library source file

int8 file_data[10];
void open_file(){
  const int8 *txt = "mytext.txt";                // File name 'mytext.txt'
  if(fat16_open_file(txt) == 0){
    printf("\n\r");                              // Start new line
    while(fat16_read_data(10, file_data) == 0)   // Read file data
      printf("%s", file_data);                   // Print file data as string
  printf("\n\r");                                // Start new line
  printf("File opening error!");
void main(){
  setup_oscillator(OSC_8MHZ);                    // Set internal oscillator to 8MHz
  set_tris_d(0);                                 // Configure PORTD pins as outputs
  printf("\n\r");                                // Start new line
  printf("*** Read text file from FAT16 SD card using PIC16F887 ***");
  printf("\n\r");                                // Start new line
  printf("Initializing FAT16 library ...... ");
  if(fat16_init() == 0){                         // If FAT16 file system and SD card were successfully initialized
    printf("\n\r");                              // Start new line
    printf("Opening file: 'mytext.txt'...... ");
  else {                                         // Problem occured while the initialization
    printf("\n\r");                              // Start new line
    printf("Initialization error!");
  printf("\n\r");                                // Start new line
  printf("*** END ***");
  while(TRUE) ;                                  // Endless loop
After finishing the project, I got a result similar to the one shown in the video below where the used microcontroller is PIC16F877A.