Lab 9 of embedded systems
Lab 9 of embedded systems
9
Interfacing MicroSD Card for Data Storage
Objectives:
➢ MicroSD Card
A microSD card is a non-volatile removeable storage medium that can be used to store data in
files. The data from different sensors can be logged into the files that can be read or retrieved
further using PCs.A microSD card is formatted under either FAT-16 or FAT-32 file system to
store data in files. The most common file that is used to store data is .txt file which is a
binary file that accepts ASCII codes of the characters to be stored in it. A microSD card has
an SPI interface and thus can be interfaced with a microcontroller such as ESP32 using SPI
protocol.
Safety Instructions:
➢ Disconnect the ESP32 board from the computer while setting up the circuit.
➢ Constructing circuit around ESP32 while it is connected with computer can damage both
the board and the computer.
➢ Only connect the ESP32 board with the computer when the circuit has been fully
constructed.
Program 1:
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <stdio.h>
#include <string.h> #include "driver/gpio.h"#include "esp_log.h" #include
"sdkconfig.h"#define MOSI_PIN 23 #define MISO_PIN 19 #define SCK_PIN 18 #define
CS_PIN 5
#define CMD0 0x40 // GO_IDLE_STATE
#define CMD17 0x51 // READ_SINGLE_BLOCK
#define CMD24 0x58 // WRITE_SINGLE_BLOCK
static const char *TAG = "SD_SPI";
void delay_ms(unsigned int ms){ vTaskDelay(pdMS_TO_TICKS(ms));
}void spi_send(uint8_t data) { for (int i = 0; i < 8; i++) {
gpio_set_level(MOSI_PIN, (data & 0x80) ? 1 : 0);gpio_set_level(SCK_PIN, 1);
data <<= 1; gpio_set_level(SCK_PIN, 0); }}
uint8_t spi_receive(void) {uint8_t
data = 0; for (int i = 0; i < 8;
i++) { gpio_set_level(SCK_PIN, 1);
data <<= 1;if (gpio_get_level(MISO_PIN)) {data |= 0x01;
}gpio_set_level(SCK_PIN, 0);}return data;} void
sd_send_command(uint8_t cmd, uint32_t arg, uint8_t crc) {
gpio_set_level(CS_PIN, 0);
spi_send(cmd);
spi_send(arg >> 24);
spi_send(arg >> 16);
spi_send(arg >> 8);
spi_send(arg);
spi_send(crc);
gpio_set_level(CS_PIN, 1);
void spi_init() {
gpio_set_direction(MOSI_PIN, GPIO_MODE_OUTPUT);
gpio_set_direction(MISO_PIN, GPIO_MODE_INPUT);
gpio_set_direction(SCK_PIN, GPIO_MODE_OUTPUT);
gpio_set_direction(CS_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(CS_PIN, 1);
gpio_set_level(SCK_PIN, 0);
} // SD card initialization functionint sd_card_init() {
spi_init();
sd_send_command(CMD0, 0, 0x95); // CMD0: Reset SD card
vTaskDelay(100 / portTICK_PERIOD_MS);
// Check if SD card is in idle state
uint8_t response = spi_receive();if
(response != 0x01) {
ESP_LOGE(TAG, "SD card not in idle state");return -
1;}ESP_LOGI(TAG, "SD card initialized");return 0;}
int sd_write_block(uint32_t block_addr, uint8_t
*data) {sd_send_command(CMD24, block_addr, 0xFF);
)spi_send(0xFE);
for (int i = 0; i < 512;
i++) {spi_send(data[i]);
}spi_send(0xFF); spi_send(0xFF);
uint8_t response = spi_receive();
if ((response & 0x1F) != 0x05) {
ESP_LOGE(TAG, "Data not accepted by SD card");
return -1;
}ESP_LOGI(TAG, "Block written successfully");return 0;}
int sd_read_block(uint32_t block_addr, uint8_t *buffer) {
sd_send_command(CMD17, block_addr, 0xFF);
while (spi_receive() != 0xFE)
{vTaskDelay(1portTICK_PERIOD_MS
);}
for (int i =
0; i < 512;
i++) {
buffer[i] =
spi_receive();
}spi_receive()
;
spi_receive();
ESP_LOGI(TAG, "Block read successfully");
return 0;}
int sd_write_file(const char *filename, const uint8_t *data, size_t size) {
if (sd_write_block(0, data) == 0) {
ESP_LOGI(TAG, "File '%s' written successfully", filename);
return 0;}
ESP_LOGE(TAG, "Failed to write file '%s'", filename);
return -1;}
int sd_read_file(const char *filename, uint8_t *buffer, size_t size) {
if (sd_read_block(0, buffer) == 0) {
ESP_LOGI(TAG, "File '%s' read successfully", filename);
return 0;}ESP_LOGE(TAG, "Failed to read file '%s'",
filename);return -1;
}void app_main(void){
if (sd_card_init() != 0) { ESP_LOGE(TAG, "Failed to
initialize SD card");return;
}// Test write
uint8_t write_data[512] = "Hello, SD card!";
sd_write_file("test.txt", write_data,
sizeof(write_data));// Test read
uint8_t read_data[512] = {0};
sd_read_file("test.txt", read_data, sizeof(read_data)); // Print read data
printf("Data read from SD card: %s\n", read_data); for(;;);}
Lab Task 1:
Create a C/C++ code that logs the data coming from on-chip ADC of ESP32 in a file named
‘ADC.txt’. The file is to be stored on a microSD card interfaced with ESP32 using SPI link.
Save your code and attach it to this Lab.
#include "freertos/FreeRTOS.h" uint8_t response = spi_receive();
#include "freertos/task.h" if (response != 0x01) {
#include "driver/ledc.h" return -1;} return 0;}
#include "driver/adc.h" int sd_write_block(uint32_t block_addr,
#include "esp_log.h" uint8_t *data) {
#include "driver/gpio.h" sd_send_command(CMD24, block_addr,
#include <stdio.h> 0xFF);
#include <string.h> spi_send(0xFE);
#define MOSI_PIN 23 for (int i = 0; i < 512; i++) {
#define MISO_PIN 19 spi_send(data[i]); }
#define SCK_PIN 18 spi_send(0xFF);
#define CS_PIN 5 spi_send(0xFF);
#define CMD0 0x40 uint8_t response = spi_receive();
#define CMD17 0x51 if ((response & 0x1F) != 0x05) {
#define CMD24 0x58 return -1; }return 0;}
#define POT_PIN ADC1_CHANNEL_6 int sd_read_block(uint32_t block_addr,
void delay_ms(unsigned int ms) { uint8_t *buffer) {
vTaskDelay(pdMS_TO_TICKS(ms)); sd_send_command(CMD17, block_addr,
} 0xFF);
void spi_send(uint8_t data) { while (spi_receive() != 0xFE) {
for (int i = 0; i < 8; i++) { vTaskDelay(1 /
gpio_set_level(MOSI_PIN, (data & portTICK_PERIOD_MS);
0x80) ? 1 : 0); } for (int i = 0; i < 512; i++) {
gpio_set_level(SCK_PIN, 1); buffer[i] = spi_receive(); }
data <<= 1; spi_receive();
gpio_set_level(SCK_PIN, 0);}} spi_receive();
uint8_t spi_receive(void) { return 0;}
uint8_t data = 0; void ADC_Config() {
for (int i = 0; i < 8; i++) { adc1_config_width(ADC_WIDTH_BIT_12);
gpio_set_level(SCK_PIN, 1); adc1_config_channel_atten(POT_PIN,
data <<= 1; ADC_ATTEN_DB_11);
if (gpio_get_level(MISO_PIN)) { }
data |= 0x01; uint16_t Read_ADC() {
} return adc1_get_raw(POT_PIN);
gpio_set_level(SCK_PIN, 0); }
} void app_main(void) {
return data; if (sd_card_init() != 0) {
} return;
void sd_send_command(uint8_t cmd, }
uint32_t arg, uint8_t crc) { ADC_Config();
gpio_set_level(CS_PIN, 0); uint8_t adc_data[512] = {0};
spi_send(cmd); for (int i = 0; i < 512; i++) {
spi_send(arg >> 24); uint16_t adc_value = Read_ADC();
spi_send(arg >> 16); adc_data[i] = adc_value & 0xFF;
spi_send(arg >> 8); }
spi_send(arg); sd_write_block(0, adc_data);
spi_send(crc); while (1) {
gpio_set_level(CS_PIN, 1); vTaskDelay(pdMS_TO_TICKS(1000));
} }
void spi_init() { }
gpio_set_direction(MOSI_PIN,
GPIO_MODE_OUTPUT);
gpio_set_direction(MISO_PIN,
GPIO_MODE_INPUT);
gpio_set_direction(SCK_PIN,
GPIO_MODE_OUTPUT);
gpio_set_direction(CS_PIN,
GPIO_MODE_OUTPUT);
gpio_set_level(CS_PIN, 1);
gpio_set_level(SCK_PIN, 0);
}
int sd_card_init() {
spi_init();
sd_send_command(CMD0, 0, 0x95);
vTaskDelay(100 /
portTICK_PERIOD_MS);
Lab Task 2:
Create a C/C++ code that logs the data coming from on-chip UART and on-chip ADC of
ESP32 in a file named ‘MyFile.txt’. The file is to be stored on a microSD card interfaced with
ESP32 using SPI link. The data stored in the file should have the following layout.
ADC DATA UART DATA
2056 128
56 247
Save your code and attach it to this Lab.
#include "freertos/FreeRTOS.h" int sd_write_block(uint32_t block_addr,
#include "freertos/task.h" uint8_t *data) {sd_send_command(CMD24,
block_addr, 0xFF); spi_send(0xFE);
#include "driver/adc.h"
for (int i = 0; i < 512; i++) {
#include "driver/uart.h"
spi_send(data[i]);
#include "esp_log.h"
}spi_send(0xFF); spi_send(0xFF);
#include "driver/gpio.h"
uint8_t response =spi_receive();
#define MOSI_PIN 23
if ((response & 0x1F) != 0x05) {
#define MISO_PIN 19
return -1;
#define SCK_PIN 18
}
#define CS_PIN 5
return 0;
#define CMD0 0x40
}
#define CMD17 0x51
#define CMD24 0x58
void ADC_Config() {
#define POT_PIN ADC1_CHANNEL_6
#define UART_NUM UART_NUM_1
adc1_config_width(ADC_WIDTH_BIT_12);
void spi_send(uint8_t data) {
adc1_config_channel_atten(POT_PIN,
for (int i = 0; i < 8; i++) { ADC_ATTEN_DB_11);
gpio_set_level(MOSI_PIN, (data &
}
0x80) ? 1 : 0);
gpio_set_level(SCK_PIN, 1);
uint16_t Read_ADC() {
data <<= 1;
return adc1_get_raw(POT_PIN);
gpio_set_level(SCK_PIN,
0);}} }
uint8_t spi_receive(void) {
uint8_t data = 0; void UART_Config() {
for (int i = 0; i < 8; i++) { const uart_config_t uart_config =
{
gpio_set_level(SCK_PIN, 1);
.baud_rate = 9600,
data <<= 1;
.data_bits = UART_DATA_8_BITS,
if
(gpio_get_level(MISO_PIN)) { .parity = UART_PARITY_DISABLE,
data |= 0x01; .stop_bits = UART_STOP_BITS_1,
} .flow_ctrl =
UART_HW_FLOWCTRL_DISABLE
gpio_set_level(SCK_PIN, 0);
};
}
uart_param_config(UART_NUM,
return data;
&uart_config);
}
uart_driver_install(UART_NUM, 512,
0, 0, NULL, 0);
void sd_send_command(uint8_t cmd, }
uint32_t arg, uint8_t crc) {
gpio_set_level(CS_PIN, 0);
void app_main(void) {
spi_send(cmd);
if (sd_card_init() != 0) {
spi_send(arg >> 24);
return;
spi_send(arg >> 16);
}
spi_send(arg >> 8);
ADC_Config();
spi_send(arg);
UART_Config();
spi_send(crc);
uint8_t buffer[512] = {0};
gpio_set_level(CS_PIN, 1);}
while (1) {
void spi_init()
{gpio_set_direction(MOSI_PIN, uint16_t adc_value =
GPIO_MODE_OUTPUT); Read_ADC();
gpio_set_direction(MISO_PIN,
uint8_t uart_data = 0;
GPIO_MODE_INPUT);
uart_read_bytes(UART_NUM,
gpio_set_direction(SCK_PIN,
&uart_data, 1, pdMS_TO_TICKS(10));
GPIO_MODE_OUTPUT);
snprintf((char *)buffer, 512,
gpio_set_direction(CS_PIN,
"%u\t%u\n", adc_value, uart_data);
GPIO_MODE_OUTPUT);
sd_write_block(0, buffer);
gpio_set_level(CS_PIN, 1);
gpio_set_level(SCK_PIN, 0);}
vTaskDelay(pdMS_TO_TICKS(1000));
int sd_card_init() {
}
spi_init();
}
sd_send_command(CMD0, 0, 0x95);
vTaskDelay(100 /
portTICK_PERIOD_MS);
uint8_t response =
spi_receive();
if (response != 0x01) {
return -1;}
return 0;}
Page 2 of 6
Page 3 of 6
Page 4 of 6
Page 5 of 6