Lập trình STM32 SDIO đọc ghi dữ liệu vào thẻ nhớ SD card

stm32f407 Sdio

Trong bài này chúng ta cùng học cách lập trình STM32 SDIO, một chuẩn giao tiếp rất tiện lợi với tốc độ cao khi làm việc với thẻ nhớ. Cùng với đó là cách sử dụng thư viện FatFS với STM32, đây là thư viện middleware tiêu chuẩn để đọc/ghi file mà ST tích hợp sẵn cho người dùng.

Bài 2 phần STM32F407 trong serie Học STM32 từ A tới Z

Chuẩn giao tiếp SDIO là gì?

SDIO là khối giao tiếp nằm giữa bus ngoại vi APB2 của STM32 và các thẻ MultiMediaCard (MMC), thẻ nhớ SD, thẻ SDIO và thiết bị CE-ATA.

Vậy MMC là gì?

MMC là viết tắt của MultiMedia Card. Nó là 1 loại thẻ nhớ dùng NAND flash để lưu trữ dữ liệu, được giới thiệu lần đầu tiên vào năm 1997 bởi Siemens AG và SanDisk. Đối với các ứng dụng nhúng ở mức vi điều khiển, thẻ MMC/SD là bộ nhớ thích hợp cho các ứng dụng cần lưu trữ dữ liệu, vì phần cứng kết nối đơn giản, hỗ trợ cả giao tiếp SPI và dung lượng lớn (thẻ SDHC lên đến 32GB).

SD card

Bộ nhớ của thẻ MMC/SD được tổ chức theo khối (block), tương tự như ổ cứng (hard disk) trong máy tính.

Nhìn chung MMC và SD giống nhau về mặt cấu trúc vật lý và phương thức giao tiếp. Điểm khác nhau lớn nhất của 2 loại card này là tính năng bảo mật dữ liệu và tốc độ giao tiếp.

SD card xuất hiện sau MMC card nên SD có nhiều tính năng và tốc độ cao hơn MMC. Tuy nhiên, khi ghi đọc MMC và SD ở tốc độ thấp bằng các vi điều khiển (như ARM) thì sự khác nhau của 2 loại card này là không đáng quan tâm.

Khối SDIO trong STM32F407

Trong STM32F407 chúng ta có 1 khối SDIO. Khối này bao gồm:

  • Giao tiếp bus APB2, có thể kết nối với DMA để tăng tốc độ truyền nhận dữ liệu
  • Khối SDMMC adapter: giao tiếp với thẻ nhớ qua các chân CK, CMD và D.

STM32 SDIO Block diagram

Chi tiết trong khối SDMMC Adapter:

STM32 SDMMC adapter

Dữ liệu từ thẻ nhớ SD/SDIO được truyền nhận theo từng khối (block). Khối SDIO hỗ trợ bus dữ liệu 1 bit (mặc định), 4 bit và 8 bit (8 bit chỉ dùng cho thẻ MMC). SDIO 4 bit có tốc độ truyền nhận nhanh gấp nhiều lần so với giao tiếp SPI, nếu dùng kèm DMA thì CPU gần như không phải làm gì trong lúc truyền. Giống như đường cao tốc 4 làn so với đường 1 làn vậy.

Trong bài này chúng ta sẽ xét tới chế độ 4 bit.

Đầu tiên các bạn nối các chân của SDIO vào thẻ nhớ như sau:

sdio 4 bit

Trên STM32F407, các chân SDIO cố định là: D0 – PC8, D1 – PC9, D2 – PC10, D3 – PC11, CK – PC12, CMD – PD2.

Ý nghĩa của các chân:

  • Các chân D0, D1, D2, D3 là các chân dữ liệu, tối đa 4 bit. Với chế độ 1 bit thì chỉ dùng chân D0. Các chân dữ liệu cần có điện trở kéo lên
  • Chân CMD (Command): đường truyền lệnh từ STM32 tới thẻ và phản hồi (response) từ thẻ về STM32
  • Chân GND và 3.3V là chân cấp nguồn
  • CLK (CK) là chân cấp xung clock

Chi tiết về SDIO trên STM32 chúng ta đọc tài liệu: STM32F4xx reference manual

Thư viện FATFS

FatFS là một module hệ thống tệp FAT dùng chung cho các hệ thống nhúng. FatFS được viết bằng ANSI C và tách biệt với lớp I/O (diskio), nên nó độc lập với phần cứng.

FatFS nằm ở tầng Middleware giữa tầng phần cứng (Hardware) và tầng ứng dụng (Application). Nghĩa là code ứng dụng chỉ cần gọi các hàm của FatFS, còn việc đọc ghi xuống thẻ SD, USB hay Flash là do lớp diskio bên dưới đảm nhiệm.

Các lệnh FATFS chúng ta hay sử dụng chủ yếu là:

  • f_mount(): Register/Unregister a work area
  • f_open(): Open/Create a file
  • f_close(): Close a file
  • f_read(): Read a file
  • f_write(): Write a file
  • f_lseek(): Move read/write pointer, Expand a file size
  • f_truncate(): Truncate a file size
  • f_sync(): Flush cached data
  • f_opendir(): Open a directory

Các bạn có thể tham khảo thêm ở website: http://elm-chan.org/fsw/ff/00index_e.html

Ở đó có đủ các hàm và ví dụ để sử dụng hàm đó.

Để đọc 1 file thông thường sẽ trải qua 3 bước:

Mở file – Đọc/ghi file – Đóng file.

Sau đây chúng ta sẽ cùng học cách đọc/ghi file trên thẻ nhớ sử dụng giao thức SDIO với STM32F407 nhé.

Lập trình STM32 SDIO

Đầu tiên các bạn hãy chuẩn bị thẻ SD và module đọc thẻ SD theo chuẩn SDIO nhé. Module này khá khó mua ở VN nên các bạn có thể tự vẽ mạch theo sơ đồ nguyên lý bên trên.

Tiếp đó các bạn chuẩn bị một đầu đọc thẻ để test kết quả file đã ghi.

micro sd storage board l 1 5

Lưu ý: Các chân CMD và D0 – D3 bắt buộc phải có điện trở kéo lên (khoảng 10kΩ – 47kΩ) lên 3.3V. Thiếu điện trở này, hoặc dây nối dài, chế độ 4 bit rất hay báo lỗi FR_NOT_READY/FR_DISK_ERR. Khi gặp lỗi, hãy tăng ClockDiv để giảm tốc độ, hoặc thử chế độ 1 bit trước. Một số phiên bản CubeMX khởi tạo thẳng ở 4 bit gây lỗi, cách sửa là khởi tạo thẻ ở 1 bit rồi gọi HAL_SD_ConfigWideBusOperation() để chuyển sang 4 bit.

Cấu hình trên CubeMX

Đầu tiên cấu hình SYS bật Debug Serial Wire.

stm32f407 sdio cubemx sys

Cấu hình xung clock là thạch anh ngoài.

stm32f407 sdio cubemx rcc

Sau đó chọn clock như sau: xung vào là HSE 8MHz, phần tần số hệ thống các bạn có thể tùy chọn dùng bộ nhân để cấu hình tần số tùy ý.
Tuy nhiên xung 48MHz phải đúng, vì đây chính là xung SDIOCLK cấp cho khối SDIO.

stm32f407 sdio cubemx clock

Cấu hình SDIO là 1 bit hoặc 4 bit đều tương tự nhau, bật ngắt tại tab NVIC.

stm32f407 sdio cubemx sdio

Trong phần Parameter, các bạn chọn hệ số chia Clock divide để lấy tần số đọc ghi thẻ, theo công thức SDIO_CK = SDIOCLK / (Clock divide + 2). Chúng ta để là 0 để lấy tần số đọc lớn nhất (48/2 = 24MHz).

Tùy thuộc vào tốc độ đọc ghi của thẻ nhớ, thẻ cũ có thể chậm, các bạn cần đặt hệ số chia phù hợp với yêu cầu của thẻ.

stm32f407 sdio cubemx sdio divide

Cấu hình FATFS, chọn SD Card.

stm32f407 sdio cubemx fatfs

Sau đó Gen code, các bạn sẽ thấy 1 warning như thế này:

stm32f407 sdio

Đây là cảnh báo chưa có chân phát hiện thẻ (Card Detect). Thực ra chân này các bạn không dùng cũng được, không vấn đề gì.
Nhưng nếu muốn phát hiện việc thẻ nhớ được cắm vào, các bạn chọn 1 chân GPIO bất kì ở chế độ Input, sau đó trong phần Platform Settings của FATFS chọn chân đó là được.

stm32f407 sdio cubemx detect card

Lập trình STM32 SDIO tạo và ghi file trên thẻ nhớ

Sau khi Gen code, chúng ta mở project bằng Keil C, sau đó khai báo các biến phục vụ việc đọc ghi. Trong đó:

  • fatfs là biến hệ thống tệp, mỗi biến này tương ứng với một thẻ nhớ (ổ đĩa).
  • myfile là biến tương ứng với 1 file trong thẻ, chúng ta sẽ sử dụng biến đó để thao tác như đọc, ghi, xóa…
  • fresult là biến lưu kết quả của mỗi thao tác

Các bạn có thể chọn Go To Definition để tìm tới nơi định nghĩa và hiểu rõ hơn về chúng.

Tiếp đó, khai báo 1 mảng để lưu dữ liệu đọc về, và 1 biến lưu số lượng byte đọc về.

stm32f407 sdio khoi tao cac bien

Trong hàm main.

Để ghi 1 file trên thẻ nhớ chúng ta sẽ có các thao tác:

  1. Mount thẻ nhớ (f_mount)
  2. Mở file trong thẻ nhớ đó, chọn quyền cần thao tác
  3. Ghi vào file đó
  4. Đóng file đó.

stm32f407 sdio ghi du lieu

Ở đây quyền FA_CREATE_ALWAYS nghĩa là luôn tạo file mới (nếu đã có file cùng tên thì ghi đè), sau đó quyền FA_WRITE cho phép ghi vào file.

Kết quả

Sau khi lập trình xong, chúng ta Build và vào chế độ Debug, sau đó xem biến fresult. Nếu kết quả là FR_OK thì có nghĩa chúng ta làm đúng.
Một lưu ý nhỏ là nên đặt tên file không có kí tự đặc biệt và không quá 8 kí tự (nếu chưa bật hỗ trợ tên file dài LFN), để không bị báo lỗi nhé!

stm32f407 sdio ghu du lieu thanh cong

Sau đó, rút thẻ ra, cắm vào máy tính để đọc file.

Lập trình STM32 SDIO đọc file trên thẻ nhớ

Trên máy tính, chúng ta thêm 1 vài kí tự vào file đó, sau đó lập trình để đọc lại file.

Đọc dữ liệu cũng tuân thủ các bước:

  • Mount thẻ nhớ
  • Mở file, cấp quyền đọc
  • Đọc file, lưu vào 1 mảng. Nếu muốn đọc hết cả file, các bạn truyền vào độ dài f_size(&myfile).
  • Đóng file

stm32f407 sdio doc du lieu

Kết quả

Build và vào chế độ Debug, xem các biến kết quả các bạn sẽ thấy như sau:

stm32f407 sdio ket qua

Sau chữ khue nguyen creator mình chỉ cho kí tự xuống dòng LF (0x0A), nhưng khi đọc lại thì có thêm kí tự CR (0x0D) đứng trước, vậy nên dữ liệu sẽ bị lệch 1 chút. Nguyên nhân là tùy chọn xử lý chuỗi của FatFs tự đổi \n thành \r\n.
Để sửa lỗi này các bạn vào FATFS sửa như sau:

stm32f407 sdio cubemx fatfs config

Như vậy thì khi đọc, ghi dữ liệu sẽ không bị thừa kí tự nữa.

Các bạn có thể tham khảo thêm các hàm và ví dụ khác về FatFs ở website: http://elm-chan.org/fsw/ff/00index_e.html

Kết

STM32 SDIO là một ngoại vi được dùng rất nhiều trong các ứng dụng dùng thẻ nhớ. Chúng ta có thể dùng thẻ nhớ để làm rất nhiều việc như lưu trữ các file dung lượng lớn, âm thanh, hình ảnh, lưu log của cảm biến….

Vậy nên hãy cố gắng sử dụng thành thạo nhé! Đừng quên gia nhập Hội Anh Em Nghiện Lập trình để giao lưu và học hỏi nhé!!!

 

4.5/5 - (6 bình chọn)

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *