风筝
发表于: 2022-7-27 11:13:20 | 显示全部楼层

每隔一段时间,您就会遇到一个想法,您需要一种方法来为Arduino项目存储大量日志数据和其他信息,例如GPS记录器。


解决方案是使用在每台数码相机和MP3播放器中都能找到的东西:闪存卡!通常称为SD或micro SD卡。它们能够将千兆字节的数据打包到比硬币还小的空间中,这使它们成为生活中不可或缺的东西。


硬件概述

Micro SD卡模块包含两个主要组件,可以轻松地将数据记录添加到您的下一个Arduino项目:

Micro-SD-TF-Card-Module-module-contains-level-shifter-and-regulator.jpg


●    标准micro SD卡的工作电压都是3.3 V。所以我们不能直接将它连接到使用5V逻辑电平的电路。事实上,任何超过3.6V的电压都会永久损坏Micro SD卡。这就是为什么该模块具有板载超低压差稳压器,可将电压从3.3V - 6V转换为~3.3V。

●    模块上还有一个74LVC125A芯片,可将接口逻辑电平从3.3V-5V转换为3.3V。这称为逻辑电平转换。这意味着您可以使用该板与3.3V和5V微控制器进行交互。


实际上有两种与Micro SD卡连接的方式 - SPI模式和SDIO模式。 SDIO模式速度更快,用于手机、数码相机等。但它更复杂,需要签署保密文件。因此,像我们这样的爱好者可能永远不会遇到SDIO模式的接口代码。相反,每个SD卡模块都基于“低速和低开销”的SPI模式,任何微控制器都可以轻松使用。


Micro SD卡模块引脚分配

Micro SD卡模块的连接相当简单。它有六个引脚:

Micro-SD-TF-Card-Module-Pinout-SPI.jpg


VCC 引脚为模块供电,应连接到Arduino上的5V引脚。

GND 应连接到Arduino的地。

MISO (Master In Slave Out) 是Micro SD卡模块的SPI输出。

MOSI (Master Out Slave In) 是Micro SD卡模块的SPI 输入。

SCK(串行时钟)引脚接受与Arduino生成的数据传输同步的时钟脉冲。

SS(从机选择)引脚由Arduino用于启用和禁用SPI总线上的特定器件。


将Micro SD卡模块连接到Arduino开发板

首先,将Micro SD卡模块插入面包板。将模块上的VCC引脚连接到Arduino上的5V,GND引脚接地。现在我们剩下的是用于SPI通信的引脚。


由于Micro SD卡需要大量数据传输,因此当连接到微控制器上的硬件SPI引脚时,它们将提供最佳性能。请注意,每个Arduino开发板都有不同的SPI引脚,应相应地连接。对于像UNO/Nano这样的Arduino开发板,SPI引脚是数字13 (SCK)、12 (MISO) 和11 (MOSI)。您还需要第四个引脚用于芯片从机选择(SS)。通常这是引脚10,但您实际上可以使用任何您喜欢的引脚。

Arduino-Wiring-Fritzing-Connections-with-Micro-SD-TF-Card-Module.jpg


Arduino代码 – 使用CardInfo测试SD卡模块

与SD卡通信是一项繁重的工作,但对我们来说幸运的是,Arduino IDE已经包含一个非常好的库,称为SD,它简化了对SD卡的读取和写入。您可以在示例子菜单中看到它。


接下来,选择CardInfo示例草图。

SD-Library-CardInfo-Sketch-in-Arduino-IDE.jpg


此草图不会将任何数据写入卡。它只是告诉您它是否成功识别了该卡,并显示有关它的一些信息。这在尝试确定是否支持SD卡时非常有用。在尝试任何新卡之前,我们建议您运行此草图一次!


转到草图的开头并确保chipSelect线已正确初始化,在我们的例子中,我们使用数字引脚#10,所以将其更改为10!

Initialising-ChipSelect-CardInfo-Sketch-in-Arduino-IDE.jpg


现在将SD卡插入模块并上传草图。打开串口监视器,你会看到如下内容:

CardInfo-Sketch-Output-in-Arduino-IDE-Working.jpg


你可能会觉得它乱码,卡类型是SDHC(SD高容量),卷类型是FAT32以及大约4 GB的卡容量等很有用。


如果您有一张坏卡,克隆版本似乎更容易发生这种情况,您可能会看到:

CardInfo-Sketch-Output-in-Arduino-IDE-Bad-Corrupt-Card.jpg


卡大多有反应,但数据全是坏的。没有制造商ID/OEM ID并且产品ID为“N/A”。这表明该卡返回了一些SD错误。这基本上是一个糟糕的场景。如果你得到这样的东西,你可以尝试重新格式化它。


最后,尝试取出SD卡并再次运行草图,您将得到以下内容,

CardInfo-Sketch-Output-in-Arduino-IDE-Initialization-Failed.jpg


看,它甚至无法初始化SD卡。如果存在接线错误或卡永久损坏,也会发生这种情况。


如果接线正确但SD卡未正确格式化,您将得到如下信息:

CardInfo-Sketch-Output-in-Arduino-IDE-No-Proper-Format.jpg


Arduino代码 - 读取和写入数据

接下来的草图将做一个从文件写入和读取数据的基本演示。在我们开始详细介绍之前,先试一下草图。

  1. #include <SPI.h>
  2. #include <SD.h>

  3. File myFile;

  4. // change this to match your SD shield or module;
  5. const int chipSelect = 10;

  6. void setup()
  7. {
  8.   // Open serial communications and wait for port to open:
  9.   Serial.begin(9600);
  10.   while (!Serial) {
  11.     ; // wait for serial port to connect. Needed for Leonardo only
  12.   }


  13.   Serial.print("Initializing SD card...");

  14.   if (!SD.begin()) {
  15.     Serial.println("initialization failed!");
  16.     return;
  17.   }
  18.   Serial.println("initialization done.");

  19.   // open the file. note that only one file can be open at a time,
  20.   // so you have to close this one before opening another.
  21.   myFile = SD.open("test.txt", FILE_WRITE);

  22.   // if the file opened okay, write to it:
  23.   if (myFile) {
  24.     Serial.print("Writing to test.txt...");
  25.     myFile.println("testing 1, 2, 3.");
  26.     // close the file:
  27.     myFile.close();
  28.     Serial.println("done.");
  29.   } else {
  30.     // if the file didn't open, print an error:
  31.     Serial.println("error opening test.txt");
  32.   }

  33.   // re-open the file for reading:
  34.   myFile = SD.open("test.txt");
  35.   if (myFile) {
  36.     Serial.println("test.txt:");

  37.     // read from the file until there's nothing else in it:
  38.     while (myFile.available()) {
  39.       Serial.write(myFile.read());
  40.     }
  41.     // close the file:
  42.     myFile.close();
  43.   } else {
  44.     // if the file didn't open, print an error:
  45.     Serial.println("error opening test.txt");
  46.   }
  47. }

  48. void loop()
  49. {
  50.   // nothing happens after setup
  51. }
复制代码

上传代码,如果一切正常,串口监视器上会出现以下内容。

Micro-SD-Card-SD-library-Output-on-Serial-Monitor.jpg


代码说明

草图首先包括内置的SD库和SPI库,这使我们能够通过SPI接口轻松地与SD卡进行通信。

  1. #include <SPI.h>
  2. #include <SD.h>
复制代码

包含库后,我们要做的下一件事是声明SD卡模块的chipSelect (CS)引脚连接到的Arduino引脚。CS引脚是唯一没有真正固定为任何Arduino数字引脚的引脚。我们不需要声明其他SPI引脚,因为我们使用的是硬件SPI接口,并且这些引脚已经在SPI库中声明。声明引脚后,我们创建一个对象myFile,稍后将使用该对象将数据存储在SD卡上。

  1. const int chipSelect = 10;
  2. File myFile;
复制代码

接下来,在setup()函数中,我们启动串口通信以在串口监视器上显示结果。使用SD.begin()函数初始化SD卡,如果初始化成功,“if”语句变为真,在串行监视器上打印字符串“initialization done”,否则打印输出字符串“initialization failed!”,程序终止。

  1. Serial.begin(9600);
  2.   Serial.print("Initializing SD card...");
  3.   if (!SD.begin()) {
  4.     Serial.println("initialization failed!");
  5.     return;
  6.   }
  7.   Serial.println("initialization done.");
复制代码

接下来,SD.open()函数将打开名为“test.txt”的文件。在我们的例子中,由于这样的文件不存在,它将被创建。另一个参数FILE_WRITE以读写模式打开文件。

  1. myFile = SD.open("test.txt", FILE_WRITE);
复制代码

打开文件后,我们将在串口监视器上打印“Writing to test.txt...”消息,然后使用 myFile.println() 函数,我们将写入文本“testing 1, 2, 3”到文件中。之后我们需要使用close()函数来确保写入文件的数据被保存。

  1.   if (myFile) {
  2.     Serial.print("Writing to test.txt...");
  3.     myFile.println("testing 1, 2, 3.");
  4.     myFile.close();
  5.     Serial.println("done.");
  6.   } else {
  7.     Serial.println("error opening test.txt");
  8.   }
复制代码

现在让我们读取同一个文件来检查写入操作是否成功。为此,我们将使用相同的函数SD.open() ,但这一次由于文件“test.txt”已经创建,函数只会打开文件。然后使用myFile.read()函数,我们将从文件中读取并将其打印在串口监视器上。 read()函数实际上一次只读取一个字符,因此我们需要使用“while”循环和函数myFile.available() 来读取文件中的所有字符。最后我们需要关闭文件。

  1. myFile = SD.open("test.txt");
  2.   if (myFile) {
  3.     Serial.println("test.txt:");
  4.     while (myFile.available()) {
  5.       Serial.write(myFile.read());
  6.     }
  7.     myFile.close();
  8.   } else {
  9.     Serial.println("error opening test.txt");
  10.   }
复制代码

由于这只是演示如何读取和写入文件的演示草图,因此没有必要多次运行代码,因此所有代码都放在只运行一次的setup()函数中,而不是将其置于loop()函数一遍又一遍地运行。

  1. void loop()
  2. {
  3. }
复制代码

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 700 | 回复: 1479



手机版|

GMT+8, 2024-3-29 13:13 , Processed in 0.152152 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表