This post shows how to interface PIC18F46K22 microcontroller with SD card formatted with FAT32 file system.
It shows how to create folders and files, how to write to a text files and how to read and print a text file.
The compiler used in this project is mikroC PRO for PIC.
FAT32 Library for mikroC compiler:
MikroElektronika provides a nice library for FAT32 file system (& SD card). This library can be downloaded from the following link:
FAT32 Library for mikroC compiler
The extension of the downloaded file is .mpkg, and in order to open and install the library we need a small software named: Package Manager, it’s also a free software provided by MikroElektronika, download link is below:
Package Manager download
Hardware Required:
This is a list of the basic components required for this project (all components are shown in the circuit diagram)
- PIC18F46K22 microcontroller —-> datasheet
- FAT32 formatted SD card (MMC, SD, SDHC, microSD ….)
- micro SD card module
- USB-to-serial UART converter (like: FT232RL module)
- Breadboard
- 5V source
- Jumper wires
To connect the microcontroller with the laptop (PC) we need (one of the following):
—> USB to serial UART converter such as FTDI232RL module, or
—> an Arduino UNO board (connect reset pin to GND, Arduino GND to PIC GND, TX to TX and RX to RX), here the PIC18F46K22 can be supplied from the Arduino board, or
—> USB-to-RS232 converter (if the PC doesn’t have a RS232 com port), MAX232 chip, RS232 female connector and four 10 uF capacitors.
The easiest way is to use the FTDI232RL module.
Interfacing PIC18F46K22 with SD card circuit:
Project circuit diagram is shown below.
As a small hint, it is recommended to add a voltage level translator to MISO line in order to step up the 3.3V that comes from the SD card into 5V which goes to SDI1 pin (#23) of the PIC18F46K22 microcontroller, here we can use the integrated circuit 74HCT125.
In this project I used micro SD card module, this module is supplied from circuit 5V source, it contains the AMS1117-3V3 voltage regulator which is used to supply the SD card with 3.3V. Also this module contains an IC which is 74LVC125A and it is used as level translator (from 5V to 3.3V).
All the grounded terminals are connected together.
The PIC18F46K22 microcontroller does have 2 hardware SPI modules (MSSP1 and MSSP2), in this example the SD card module is connected to hardware SPI1 pins (SCK, MOSI and MISO) and SS (slave select or chip select) pin is connected to pin RD4.
The FT232RL board (USB to serial converter) RX pin is connected to PIC18F46K22 TX1 (RC6) pin which is UART1 module transmission pin (the PIC18F46K22 has 2 hardware USART modules).
In this project the PIC18F46K22 microcontroller runs with its internal oscillator @ 16 MHz and MCLR pin is configured as an input pin.
Interfacing PIC18F46K22 with SD card C code:
The following C code is for mikroC PRO for PIC compiler, it was tested with version 7.2.0.
The SD card chip select pin (SS) is connected to pin RD4 of the PIC18F46K22, it’s defined in the C code as:
1 2 3 | // SD card chip select pin connection sbit Mmc_Chip_Select at RD4_bit; sbit Mmc_Chip_Select_Direction at TRISD4_bit; |
Before initializing the FAT32 library (as well as the SD card), the SPI clock frequency is set to lowest (Fosc/64):
Fosc/64 = 16MHz/64 = 250 kHz is below the recommended clock frequency for initializing the SD card which is 400 kHz.
1 2 | // initialize SPI1 module at lowest speed SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); |
After the initialization of the FAT32 library we can go to higher speed by setting the clock frequency to Fosc/4:
Fosc/4 = 16MHz/4 = 4 MHz.
This means we’ve a transfer rate of: 4 Mbit/second.
1 2 | // re-initialize SPI1 module at highest speed SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); |
Used functions:
FAT32_Init(): this function initializes the FAT32 library as well as the SD card, it returns 0 if OK and non-zero if error.
FAT32_MakeDir(“Test Dir”): creates a new folder (directory) with name “Test Dir”, returns 0 if OK and non-zero if error.
FAT32_Open(“Log.txt”, FILE_APPEND): this function creates (& opens) a new file named “Log.txt” if it doesn’t already exists, if the file exists, it opens and moves the cursor to the end of the file, returns 0 if OK and non-zero if error (or file exists).
FAT32_Write(fileHandle, “Hello, …”, 113): writes a text “Hello, …” of length 113 bytes to the file associated with fileHandler.
FAT32_Close(fileHandle): closes the file associated with fileHandler, returns 0 if OK and non-zero if error.
FAT32_Open(“Log.txt”, FILE_READ): opens the file named “Log.txt” with read permission, returns 0 if OK and non-zero if error.
FAT32_Read(fileHandle, buffer, 113): this function read 113 bytes from the file associated with fileHandler and stores them to the array buffer.
Full mikroC code:
Configuration words (for PIC18F46K22 MCU):
CONFIG1H = 0x0028
CONFIG2L = 0x0018
CONFIG2H = 0x003C
CONFIG3H = 0x0037
CONFIG4L = 0x0081
CONFIG5L = 0x000F
CONFIG5H = 0x00C0
CONFIG6L = 0x000F
CONFIG6H = 0x00E0
CONFIG7L = 0x000F
CONFIG7H = 0x0040
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | /************************************************************************************** Read and write files to and from SD card using PIC18F46K22 microcontroller. C Code for mikroC PRO for PIC compiler. Internal oscillator used @ 16MHz Configuration words: CONFIG1H = 0x0028 CONFIG2L = 0x0018 CONFIG2H = 0x003C CONFIG3H = 0x0037 CONFIG4L = 0x0081 CONFIG5L = 0x000F CONFIG5H = 0x00C0 CONFIG6L = 0x000F CONFIG6H = 0x00E0 CONFIG7L = 0x000F CONFIG7H = 0x0040 This is a free software with NO WARRANTY. https://simple-circuit.com/ ***************************************************************************************/ // SD card chip select pin connection sbit Mmc_Chip_Select at RD4_bit; sbit Mmc_Chip_Select_Direction at TRISD4_bit; // include __Lib_FAT32.h file (useful definitions) #include "__Lib_FAT32.h" // variable declarations __HANDLE fileHandle; // only one file can be opened char buffer[114]; short i; // main function void main() { OSCCON = 0x70; // set internal oscillator to 16MHz ANSELC = 0; // configure all PORTC pins as digital ANSELD = 0; // configure all PORTD pins as digital delay_ms(1000); // wait a second // initialize SPI1 module at lowest speed SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); UART1_Init(9600); // initialize UART1 module at 9600 baud UART1_Write_Text("\r\n\nInitialize FAT library ... "); delay_ms(2000); // wait 2 seconds // initialize FAT32 library (& SD card) i = FAT32_Init(); if(i != 0) { // if there was a problem while initializing the FAT32 library UART1_Write_Text("Error initializing FAT library!"); } else { // the FAT32 library (& SD card) was (were) initialized // re-initialize SPI1 module at highest speed SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); UART1_Write_Text("FAT Library initialized"); delay_ms(2000); // wait 2 seconds // create a new folder with name 'Test Dir' UART1_Write_Text("\r\n\r\nCreate 'Test Dir' folder ... "); if(FAT32_MakeDir("Test Dir") == 0) UART1_Write_Text("OK"); else UART1_Write_Text("error creating folder"); delay_ms(2000); // wait 2 seconds // create (or open if already exists) a text file 'Log.txt' UART1_Write_Text("\r\n\r\nCreate 'Log.txt' file ... "); fileHandle = FAT32_Open("Log.txt", FILE_APPEND); if(fileHandle == 0) UART1_Write_Text("OK"); else UART1_Write_Text("error creating file or file already exists!"); delay_ms(2000); // wait 2 seconds // write some thing to the text file UART1_Write_Text("\r\nWriting to the text file 'Log.txt' ... "); i = FAT32_Write(fileHandle, "Hello,\r\nThis is a text file created using PIC18F46K22 microcontroller and mikroC compiler.\r\nHave a nice day ...", 113); if(i == 0) UART1_Write_Text("OK"); else UART1_Write_Text("writing error"); delay_ms(2000); // wait 2 seconds // now close the file (Log.txt) UART1_Write_Text("\r\nClosing the file 'Log.txt' ... "); i = FAT32_Close(fileHandle); if(i == 0) UART1_Write_Text("OK"); else UART1_Write_Text("closing error"); delay_ms(2000); // wait 2 seconds // reading 'Log.txt' file UART1_Write_Text("\r\n\r\nReading 'Log.txt' file:"); delay_ms(2000); // wait 2 seconds // open 'Log.txt' file with read permission UART1_Write_Text("\r\nOpen 'Log.txt' file ... "); fileHandle = FAT32_Open("Log.txt", FILE_READ); if(fileHandle != 0) UART1_Write_Text("error opening file"); else { // open file OK UART1_Write_Text("OK"); delay_ms(2000); // wait 2 seconds // print the whole file UART1_Write_Text("\r\nPrint 'log.txt' file:\r\n\r"); delay_ms(2000); // wait 2 seconds // read 113 bytes from fileHandler (Log.txt)and store in buffer FAT32_Read(fileHandle, buffer, 113); // now print the whole buffer UART1_Write_Text(buffer); delay_ms(2000); // wait 2 seconds // now close the file UART1_Write_Text("\r\n\r\nClosing the file 'log.txt' ... "); i = FAT32_Close(fileHandle); if(i == 0) UART1_Write_Text("OK"); else UART1_Write_Text("closing error"); } } delay_ms(2000); // wait 2 seconds UART1_Write_Text("\r\n\r\n***** END *****"); while(1) ; // endless loop } // end of code. |
This project was tested in hardware circuit using 2 original Samsung microSD cards (SDHC), one with capacity of 4GB and the the other with 32GB.
MikroElektronika USART terminal result is shown below (data sent from the microcontroller to the laptop):
And the created folder (Test Dir) and file (Log.txt) are shown below:
This project could be simulated with Proteus and it should give the same result, the simulation of this project is near to the one shown in the following video where PIC18F4550 microcontroller and CCS C compiler were used (not that simulation circuit is not the same as real hardware circuit, project hardware circuit is shown above):
Proteus simulation file download link:
PIC18F46K22 + SD card
SD Card file is FAT32 image file (FAT32_MBR.ima), it can be downloaded from the link below:
SD Card FAT32 image
Discover more from Simple Circuit
Subscribe to get the latest posts sent to your email.
I enjoyed these articles even though I’m still a beginner
could you help to solve this error “Unresolved extern ‘Mmc_Chip_Select’ __Lib_Mmc.c” while compiling above mentioned code