Friday, August 25, 2017

Read and display text file from FAT16 microSD card using PIC18F4550


PIC18F4550 microcontroller with FAT16 microSD card
After I successfully read/wrote raw data from/to an SD card I want to read and display text files from the SD card. I did this with the SD card driver and FAT16 library for CCS C compiler. The SD card driver can be found on this topic:
MMC/SD Card driver for CCS PIC C compiler
and FAT16 file system library can be downloaded from this topic:
FAT16 Library for CCS C compiler
With these libraries we can easily open and print text files located in FAT16 formatted SD card. To format an SD card with FAT16 file system, the card capacity must be <= 2 GB.
To see how to read/write raw data (bytes, sectors ....) from/to SD card read the following topic:
SD Card byte/sector read and write with PIC18F4550 microcontroller
Hardware Required:
  • PIC18F4550 microcontroller
  • FAT16 formatted SD card
  • ASM1117 3.3 voltage regulator
  • 8 MHz crystal oscillator
  • 2 x 22pF ceramic capacitors
  • 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
Interfacing PIC18F4550 with SD card circuit:
Read and print text file from MMC SD card with PIC18F4550 circuit diagram
As known the SD card voltage is 3.3V and the PIC18F4550 voltage is 5V, so AMS1117 3.3V is used to step down the 5V in order to supply our SD card. Also the outputs of the PIC18F4550 are 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.
The MAX232 is used to interface our microcontroller with PC via serial port as what was done in this topic:
CCS C UART example for PIC18F4550 microcontroller
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).
Read and display text file from FAT16 microSD card using PIC18F4550 C code:
The C code below was tested with CCS PIC C compiler versions 5.051 and 5.070.
The microcontroller runs at 48MHz (8MHz + PLL).
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 PIC18F4550, software SPI also can be used but the hardware one is much faster.
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(512, file_data): read data (512 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).
// Read and display text file from FAT16 SD card using PIC18F4550.
// Fat16 library and MMC/SD card driver for CCS C compiler must be installed!
// http://ccspicc.blogspot.com/
// electronnote@gmail.com


// SD Card module connections
#define   SDCARD_SPI_HW
#define   SDCARD_PIN_SELECT  PIN_D3
// End SD card module connections

#include <18F4550.h>
#fuses NOMCLR HSPLL PLL2 CPUDIV1
#use delay(clock = 48MHz)
#use fast_io(D)
#use rs232(xmit = PIN_D2, rcv = PIN_D1, baud = 9600)
#include <sdcard.c>                              // SD card diver source code
#include <fat16.c>                               // FAT16 library source file

const int8 *txt = "mytext.txt";                  // File name 'mytext.txt'
int8 file_data[512];
void main(){
  set_tris_d(0);                                 // Configure PORTD pins as outputs
  delay_ms(2000);
  printf("\n\r");                                // Start new line
  printf("*** Read text file from FAT16 SD card using PIC18F4550 ***");
  delay_ms(2000);
  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("OK!");
    delay_ms(2000);
    printf("\n\r");                              // Start new line
    printf("Opening file: 'mytext.txt'...... ");
    if(fat16_open_file(txt) == 0){
    printf("OK!");
    printf("\n\r");                              // Start new line
    while(fat16_read_data(512, file_data) == 0)  // Read file data
      printf("%s", file_data);                   // Print file data as string
    }
    else {
      printf("\n\r");                            // Start new line
      printf("File opening error!");
    }
  }
  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 the connection of the circuit and the burning of the HEX file into the PIC18F4550 using PICKit 3 programmer, I got the result as shown in the video below: