안경잡이개발자

728x90
반응형

  Teensy 3.6을 포함해 일부 Teensy Board들은 SD Card 슬롯(Slot)이 존재합니다. 따라서 Host PC와 데이터를 주고 받으면서, SD Card에 파일을 저장하는 등의 작업이 가능합니다. Teensyduino에서 기본적으로 제공되는 예시들을 확인할 수 있습니다.


  일단 아래의 모든 예시들을 실행할 때는 chipSelect 변수의 값을 자신이 사용하고 있는 Teensy의 버전에 맞게 설정해야 합니다. 저는 Teensy 3.6 버전을 이용하고 있기 때문에, chipSelect 변수의 값을 BUILTIN_SDCARD로 설정했습니다.

 

※ SD 카드(Card) 정보 출력하기 ※

 

  [예제] - [SD] - [CardInfo]를 들어가면 SD 카드의 정보를 출력하는 예제를 실행할 수 있습니다.

 

 

  이 예제는 단순히 카드 정보를 출력하는 예시입니다. 대략 다음과 같이 내용이 출력됩니다. 다만 예제 소스코드를 확인해 보시면, Volume Size만을 출력해주는 것이 아니라 루트 폴더에서의 전체 폴더 및 파일 목록까지 함께 보여주는 것을 알 수 있습니다.

 

 

※ SD 카드(Card)의 파일 리스트 읽어오기 ※

 

  [예제] - [SD] - [listfiles]에 들어가면 카드에 포함된 파일 목록을 출력하는 예제를 실행할 수 있습니다. 이 내용은 위의 예제에서 출력되는 내용과 비슷해 보이지만, 실제 구현상에서는 File 객체를 이용하여 파일을 openNextFile() 함수를 이용해 파일에 하나씩 접근하여 정보를 출력한다는 점이 특징입니다.

 

 

  출력된 결과는 다음과 같습니다.

 

 

※ SD 카드(Card)에서 파일의 데이터를 읽고 데이터 쓰기 ※

 

  [예제] - [SD] - [ReadWrite]에 들어가면 하나의 파일을 만들고 내용을 추가한 뒤에, 출력하는 예제를 실행할 수 있습니다. 소스코드를 확인해 보시면 SD Card 내부에서 "test.txt"라는 이름의 파일을 연 뒤에 여기에 특정한 문자열을 내용으로 기입하고, 이를 저장하는 것을 알 수 있습니다. 그리고 그렇게 저장된 내용을 다시 출력해보며 확인합니다.

 

 

※ Raw HID를 통해 받은 데이터를 SD 카드(Card)에 저장하기 ※

 

  이제 Raw HID를 통해서 Host PC로부터 받은 데이터를 Guest Device의 SD Card에 작성하는 예시를 다루어 보겠습니다. Host PC 전용 프로그램은 아래 경로에서 다운로드 받아서 그대로 이용하실 수 있습니다.

 

  ▶ Teensy 공식 홈페이지: https://www.pjrc.com/teensy/rawhid.html

  Guest Device인 Teensy 3.6의 소스코드는 다음과 같이 작성할 수 있습니다. 소스코드를 확인해 보시면, 먼저 SD Card 내부에 example.txt 파일을 생성하는 것을 알 수 있습니다. 이후에 Host PC로부터 한 문자씩 전달 받는 데이터를 example.txt에 쓰게 됩니다. 만약에 전달 받은 문자가 'q'라면 데이터를 전달 받는 것을 멈추고, example.txt 파일을 읽어서 입력되었던 문자들을 시리얼 통신을 통해 출력합니다.

 

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

File myFile;
const int chipSelect = BUILTIN_SDCARD;

void setup() {
  Serial.begin(9600);
  while (!Serial) ;
  Serial.println("RawHID Example");

  // Initialize SD card.
  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  // Remove and recreate example.txt file.
  SD.remove("example.txt");
  Serial.println("Creating example.txt...");
  myFile = SD.open("example.txt", FILE_WRITE);
}

// RawHID packets are always 64 bytes.
byte buffer[64];
elapsedMillis msUntilNextSend;
unsigned int packetCount = 0;

void loop() {
  int n;
  n = RawHID.recv(buffer, 0);
  if (n > 0) {
    if (buffer[0] == 'q') {
      if (myFile) {
        Serial.println("Quit!");
        myFile.close();
        // If the file is available, print it's data.
        Serial.println("File contents are:");
        File dataFile = SD.open("example.txt");
        if (dataFile) {
          while (dataFile.available()) {
            Serial.write(dataFile.read());
          }
          dataFile.close();
        }  
        // If the file isn't open, pop up an error.
        else {
          Serial.println("error opening example.txt");
        } 
      }
      return;
    } else {
      if (myFile) {
        Serial.print("Received packet, first char: ");
        Serial.println((char)buffer[0]);
        myFile.println((char)buffer[0]);
      }
    }
  }
}

 

  실행 결과는 다음과 같습니다.

 

 

※ 특정한 파일의 Byte Stream 읽어서 그대로 출력하기 ※

 

  특정한 파일을 열어서 내부에 적힌 데이터를 읽어서 Byte Stream 형태 그대로 출력하는 예제는 다음과 같습니다. 이 코드는 제가 개인적으로 많이 쓰는 코드입니다.

 

#include <SD.h>
#include <SPI.h>
#define BUFFER_SIZE 64 // 버퍼 사이즈

File myFile;

byte buffer[BUFFER_SIZE];
const int chipSelect = BUILTIN_SDCARD;

void setup() {
  Serial.begin(9600);
  while (!Serial);
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  delay(1000);
  myFile = SD.open("example.dat", FILE_READ);
  uint64_t fileSize = myFile.size();
  if (myFile) {
    while (true) {
      // 전달 받을 데이터의 크기(버퍼 크기보다 덜 남은 경우 남은 크기만 저장)
      int length = (fileSize < BUFFER_SIZE)? fileSize : BUFFER_SIZE;
      // 전달 받은 내용 그냥 Serial 통신으로 출력
      myFile.read(buffer, length);
      fileSize -= length;
      for (int i = 0; i < length; i++) {
        Serial.print(buffer[i]);
        Serial.print(" ");
        if ((i + 1) % 8 == 0) Serial.println();
      }
      // 크기만큼 다 출력한 경우 파일 객체 닫기
      if (fileSize <= 0) {
        break;
      }
    }
    myFile.close();
  }
}

void loop() {
  
}

 

  실행을 해보시면 다음과 같은 시리얼 출력 결과를 확인할 수 있습니다. (한 줄에 8바이트씩 출력합니다.)

 

728x90
반응형