asrpro softspi SD卡读写

news2024/12/23 23:06:39

采样 50M 1M;采样时间足够长,采样频率1M 避免信息遗漏

引脚  cs pa2 mosi pa3 sck pa5 miso pa6 vcc ->5v gnd ->gnd 

ARDUINO SD库与移植(原本是打算移值tw ch32v103的sd库的,但没有对比,只能选择arduino ; 

对 #define USE_SPI_LIB   ;USE_SPI_LIB进行注释 ,不使用原代码 ,再进行修改(原为使用硬件 与软件 spi代码 

对 sd2card.h cpp 进行修改 修改send recv 函数,替换

注释 #include "arduino.h"

及其它一些细节 

注释  //#error Architecture or board not supported.

1.问题 io口导致的 ;逻辑分析仪查看输出 对比arduino 输出 

模拟spi输出 波形(逻辑分析仪查看) 产生额外的干扰波纹,导致无法初始化成功;

混乱的输出与digitalWrite(xx,1);

输出引脚

  pinMode(2,output);  //cs
  setPinFun(2,0);
  digitalWrite(2,1);
  
  pinMode(3,output);  //mosi
  setPinFun(3,0);
  digitalWrite(3,1);
  
  pinMode(5,output);  //sck
  setPinFun(5,0);
  digitalWrite(5,1);
  
  pinMode(6,input);  //miso
  dpmu_set_io_pull(pinToFun[6],DPMU_IO_PULL_UP);
  
  
  

移值arduino SD2时 修改 sd2card.cpp sd2card.h ;(可以使用官方的 asr_softspi库 进行修改 ,模拟为1 ,1 ;sck 之后添加 延时 delay100us; 

对主要函数  spiRec spiSend 进行修改 (速度与调整delay) 或用sleep1;(*delay5us 可以 sleep1(100)不行 

void sleep1(uint8_t t)
{
  while(t>0)
    t--;
}

//------------------------------------------------------------------------------
/** Soft SPI receive */
uint8_t spiRec(void) {
  uint8_t data = 0;
  // no interrupts during byte receive - about 8 us
 // cli();
 //eclic_global_interrupt_disable();
 //eclic_global_interrupt_disable();
  // output pin high - like sending 0XFF
  digitalWrite(SPI_MOSI_PIN, HIGH);
  //sleep1(speed);

  for (uint8_t i = 0; i < 8; i++) {
    digitalWrite(SPI_SCK_PIN, HIGH);

    // adjust so SCK is nice
    nop;
    nop;
    //sleep1(speed);

    data <<= 1;

    if (digitalRead(SPI_MISO_PIN)) {
      data |= 1;
    }
    
    digitalWrite(SPI_SCK_PIN, LOW);
    delay100us();
    
    
    
  }
  
  // enable interrupts
  //sei();
 // eclic_global_interrupt_enable();

  return data;
}
//------------------------------------------------------------------------------
/** Soft SPI send */
void spiSend(uint8_t data) {
  // no interrupts during byte send - about 8 us
 // cli();
  for (uint8_t i = 0; i < 8; i++) {
    digitalWrite(SPI_SCK_PIN, LOW);
    //sleep1(speed);
    delay100us();
   

    digitalWrite(SPI_MOSI_PIN, data & 0X80);
     delay100us();

    data <<= 1;

    digitalWrite(SPI_SCK_PIN, HIGH);
    //sleep1(speed);
     delay100us();
  }
  // hold SCK high for a few ns
  
  nop;
  nop;
  nop;
  nop;

  digitalWrite(SPI_SCK_PIN, LOW);
  delay100us();
  delay100us();
 
  // enable interrupts
  //sei();
  //eclic_global_interrupt_enable();
}

------------------------------------------------------------------------------------------------------------------------------

复制arduino sd库目录下的

到 asrpro myLib 下

1.修改 office 下地的  source_file.prj  添加如下语句

source-file: ../myLib/Sd2Card.cpp (原名SdCard
source-file: ../myLib/SdFile.cpp
source-file: ../myLib/SdVolume.cpp

2 asr.cpp 测试代码 如下

3.修改 sdCard.cpp

#include "asr.h"
extern "C"{ void * __dso_handle = 0 ;}
#include "setup.h"
//#include "SD2Card.h"
#include "SD2.h"

uint32_t snid;
void ASR_CODE();
Sd2Card card;
SdVolume volume;
SdFile root;

//{speak:小蝶-清新女声,vol:10,speed:10,platform:haohaodada}
//{playid:10001,voice:欢迎使用语音助手,用天问五幺唤醒我。}
//{playid:10002,voice:我退下了,用天问五幺唤醒我}

/*描述该功能...
*/
void ASR_CODE(){
  //本函数是语音识别成功钩子程序
  //运行时间越短越好,复杂控制启动新线程运行
  //唤醒时间设置必须在ASR_CODE中才有效
  set_state_enter_wakeup(10000);
  //用switch分支选择,根据不同的识别成功的ID执行相应动作,点击switch左上齿轮
  //可以增加分支项
  switch (snid) {
   case 1:
    digitalWrite(4,0);
    break;
   case 2:
    digitalWrite(4,1);
    break;
  }
  //除了switch分支选择,也可用如果判断识别ID的值来执行动作
  if((snid) == 3){
    digitalWrite(4,0);
  }
  if((snid) == 4){
    digitalWrite(4,1);
  }
  //采用如果判断模块,可更方便复制

}

int chipSelect = 2;

void hardware_init(){
  //需要操作系统启动后初始化的内容
  //音量范围1-7
  vol_set(1);
  Serial.begin(9600);
  delay(200);

  Serial.print("\nInitializing SD card...");

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }
  
  //  Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    while (1);
  }

  Serial.print("Clusters:          ");
  Serial.println(volume.clusterCount());
  Serial.print("Blocks x Cluster:  ");
  Serial.println(volume.blocksPerCluster());

  Serial.print("Total Blocks:      ");
  Serial.println(volume.blocksPerCluster() * volume.clusterCount());
  Serial.println();

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("Volume type is:    FAT");
  Serial.println(volume.fatType(), DEC);

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
  Serial.print("Volume size (Kb):  ");
  Serial.println(volumesize);
  Serial.print("Volume size (Mb):  ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Gb):  ");
  Serial.println((float)volumesize / 1024.0);

  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);

  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
  
  
  vTaskDelete(NULL);
}

void setup()
{
  //需要操作系统启动前初始化的内容
  //播报音下拉菜单可以选择,合成音量是指TTS生成文件的音量
  //欢迎词指开机提示音,可以为空
  //退出语音是指休眠时提示音,可以为空
  //休眠后用唤醒词唤醒后才能执行命令,唤醒词最多5个。回复语可以空。ID范围为0-9999
  //{ID:0,keyword:"唤醒词",ASR:"天问五幺",ASRTO:"我在"}
  //{ID:1,keyword:"命令词",ASR:"打开灯光",ASRTO:"好的,马上打开灯光"}
  //{ID:2,keyword:"命令词",ASR:"关闭灯光",ASRTO:"好的,马上关闭灯光"}
  //{ID:3,keyword:"命令词",ASR:"灯光打开",ASRTO:"好的,马上打开灯光"}
  //{ID:4,keyword:"命令词",ASR:"灯光关闭",ASRTO:"好的,马上关闭灯光"}
  pinMode(2,output);  //cs
  setPinFun(2,0);
  digitalWrite(2,1);
  
  pinMode(3,output);  //mosi
  setPinFun(3,0);
  digitalWrite(3,1);
  
  pinMode(5,output);  //sck
  setPinFun(5,0);
  digitalWrite(5,1);
  
  pinMode(6,input);  //miso
  dpmu_set_io_pull(pinToFun[6],DPMU_IO_PULL_UP);
  
  
  
}

//Sd2Card.cpp

#include "Sd2Card.h"

//#define chipSelectPin_ 4  // 4 5 6 7 

#ifndef __SD2Card 
#define __SD2Card


// #define SPI_MOSI_PIN 3
// #define SPI_SCK_PIN 5
// #define SPI_MISO_PIN 6

//------------------------------------------------------------------------------

// functions for hardware SPI
/** Send a byte to the card */
// static void spiSend(uint8_t b) {
//   #ifndef USE_SPI_LIB
//   SPDR = b;
//   while (!(SPSR & (1 << SPIF)))
//     ;
//   #else
//   SDCARD_SPI.transfer(b);
//   #endif
// }
// /** Receive a byte from the card */
// static  uint8_t spiRec(void) {
//   #ifndef USE_SPI_LIB
//   spiSend(0XFF);
//   return SPDR;
//   #else
//   return SDCARD_SPI.transfer(0xFF);
//   #endif
// }
// #else  

// 
void usleep(uint8_t t)
{
  while(t>0)
    t--;

}
//----------------------SOFTWARE_SPI--------------------------------------------------------
/** nop to tune soft SPI timing */
#define nop asm volatile ("nop\n\t")
//------------------------------------------------------------------------------
/** Soft SPI receive */
void sleep1(uint8_t t)
{
  while(t>0)
    t--;
}

//------------------------------------------------------------------------------
/** Soft SPI receive */
uint8_t spiRec(void) {
  uint8_t data = 0;
  // no interrupts during byte receive - about 8 us
 // cli();
 //eclic_global_interrupt_disable();
 //eclic_global_interrupt_disable();
  // output pin high - like sending 0XFF
  digitalWrite(SPI_MOSI_PIN, HIGH);
  //sleep1(speed);

  for (uint8_t i = 0; i < 8; i++) {
    digitalWrite(SPI_SCK_PIN, HIGH);

    // adjust so SCK is nice
    nop;
    nop;
    //sleep1(speed);

    data <<= 1;

    if (digitalRead(SPI_MISO_PIN)) {
      data |= 1;
    }
    
    digitalWrite(SPI_SCK_PIN, LOW);
    delay100us();
    
    
    
  }
  
  // enable interrupts
  //sei();
 // eclic_global_interrupt_enable();

  return data;
}
//------------------------------------------------------------------------------
/** Soft SPI send */
void spiSend(uint8_t data) {
  // no interrupts during byte send - about 8 us
 // cli();
  for (uint8_t i = 0; i < 8; i++) {
    digitalWrite(SPI_SCK_PIN, LOW);
    //sleep1(speed);
    delay100us();
   

    digitalWrite(SPI_MOSI_PIN, data & 0X80);
     delay100us();

    data <<= 1;

    digitalWrite(SPI_SCK_PIN, HIGH);
    //sleep1(speed);
     delay100us();
  }
  // hold SCK high for a few ns
  
  nop;
  nop;
  nop;
  nop;

  digitalWrite(SPI_SCK_PIN, LOW);
  delay100us();
  delay100us();
 
  // enable interrupts
  //sei();
  //eclic_global_interrupt_enable();
}

//------------------------------------------------------------------------------
// send command and return error code.  Return zero for OK
uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
  // end read if in partialBlockRead mode
  readEnd();

  // select card
  chipSelectLow();

  // wait up to 300 ms if busy
  waitNotBusy(300);

  // send command
  spiSend(cmd | 0x40);

  // send argument
  for (int8_t s = 24; s >= 0; s -= 8) {
    spiSend(arg >> s);
  }

  // send CRC
  uint8_t crc = 0XFF;
  if (cmd == CMD0) {
    crc = 0X95;  // correct crc for CMD0 with arg 0
  }
  if (cmd == CMD8) {
    crc = 0X87;  // correct crc for CMD8 with arg 0X1AA
  }
  spiSend(crc);

  // wait for response
  for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++)
    ;
  return status_;
}
//------------------------------------------------------------------------------
/**
   Determine the size of an SD flash memory card.

   \return The number of 512 byte data blocks in the card
           or zero if an error occurs.
*/
uint32_t Sd2Card::cardSize(void) {
  csd_t csd;
  if (!readCSD(&csd)) {
    return 0;
  }
  if (csd.v1.csd_ver == 0) {
    uint8_t read_bl_len = csd.v1.read_bl_len;
    uint16_t c_size = (csd.v1.c_size_high << 10)
                      | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low;
    uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1)
                          | csd.v1.c_size_mult_low;
    return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
  } else if (csd.v2.csd_ver == 1) {
    uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16)
                      | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low;
    return (c_size + 1) << 10;
  } else {
    error(SD_CARD_ERROR_BAD_CSD);
    return 0;
  }
}
//------------------------------------------------------------------------------
static uint8_t chip_select_asserted = 0;

void Sd2Card::chipSelectHigh(void) {
  digitalWrite(chipSelectPin_, HIGH);
  // #ifdef USE_SPI_LIB
  // if (chip_select_asserted) {
  //   chip_select_asserted = 0;
  //   SDCARD_SPI.endTransaction();
  // }
 // #endif
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectLow(void) {
  // #ifdef USE_SPI_LIB
  // if (!chip_select_asserted) {
  //   chip_select_asserted = 1;
  //   SDCARD_SPI.beginTransaction(settings);
  // }
  // #endif
  digitalWrite(chipSelectPin_, LOW);
}
//------------------------------------------------------------------------------
/** Erase a range of blocks.

   \param[in] firstBlock The address of the first block in the range.
   \param[in] lastBlock The address of the last block in the range.

   \note This function requests the SD card to do a flash erase for a
   range of blocks.  The data on the card after an erase operation is
   either 0 or 1, depends on the card vendor.  The card must support
   single block erase.

   \return The value one, true, is returned for success and
   the value zero, false, is returned for failure.
*/
uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
  if (!eraseSingleBlockEnable()) {
    error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
    goto fail;
  }
  if (type_ != SD_CARD_TYPE_SDHC) {
    firstBlock <<= 9;
    lastBlock <<= 9;
  }
  if (cardCommand(CMD32, firstBlock)
      || cardCommand(CMD33, lastBlock)
      || cardCommand(CMD38, 0)) {
    error(SD_CARD_ERROR_ERASE);
    goto fail;
  }
  if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
    error(SD_CARD_ERROR_ERASE_TIMEOUT);
    goto fail;
  }
  chipSelectHigh();
  return true;

fail:
  chipSelectHigh();
  return false;
}
//------------------------------------------------------------------------------
/** Determine if card supports single block erase.

   \return The value one, true, is returned if single block erase is supported.
   The value zero, false, is returned if single block erase is not supported.
*/
uint8_t Sd2Card::eraseSingleBlockEnable(void) {
  csd_t csd;
  return readCSD(&csd) ? csd.v1.erase_blk_en : 0;
}
//------------------------------------------------------------------------------
/**
   Initialize an SD flash memory card.

   \param[in] sckRateID SPI clock rate selector. See setSckRate().
   \param[in] chipSelectPin SD chip select pin number.

   \return The value one, true, is returned for success and
   the value zero, false, is returned for failure.  The reason for failure
   can be determined by calling errorCode() and errorData().
*/
uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
      errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;
        chipSelectPin_ = chipSelectPin;
        // 16-bit init start time allows over a minute
        
        uint32_t arg;

        // set pin modes
        // pinMode(chipSelectPin_, OUTPUT);
        // pinMode(SPI_MISO_PIN, INPUT);
        // pinMode(SPI_MOSI_PIN, OUTPUT);
        // pinMode(SPI_SCK_PIN, OUTPUT);

        digitalWrite(chipSelectPin_, HIGH);
      // #ifndef USE_SPI_LIB

      //*********




        for (uint8_t i = 0; i < 10; i++) {
          spiSend(0XFF);
        }

      unsigned int t0 = millis();
        chipSelectLow();

        // command to go idle in SPI mode
        while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
          unsigned int d = millis() - t0;
          if (d > SD_INIT_TIMEOUT) {
            error(SD_CARD_ERROR_CMD0);
            goto fail;
          }
        }
        // check SD version
        if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
          type(SD_CARD_TYPE_SD1);
        } else {
          // only need last byte of r7 response
          for (uint8_t i = 0; i < 4; i++) {
            status_ = spiRec();
          }
          if (status_ != 0XAA) {
            error(SD_CARD_ERROR_CMD8);
            goto fail;
          }
          type(SD_CARD_TYPE_SD2);
        }
        // initialize card and send host supports SDHC if SD2
        arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;

        while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
          // check for timeout
          unsigned int d = millis() - t0;
          if (d > SD_INIT_TIMEOUT) {
            error(SD_CARD_ERROR_ACMD41);
            goto fail;
          }
        }
        // if SD2 read OCR register to check for SDHC card
        if (type() == SD_CARD_TYPE_SD2) {
          if (cardCommand(CMD58, 0)) {
            error(SD_CARD_ERROR_CMD58);
            goto fail;
          }
          if ((spiRec() & 0XC0) == 0XC0) {
            type(SD_CARD_TYPE_SDHC);
          }
          // discard rest of ocr - contains allowed voltage range
          for (uint8_t i = 0; i < 3; i++) {
            spiRec();
          }
        }
        chipSelectHigh();

       // #ifndef SOFTWARE_SPI
        //return setSckRate(sckRateID);
       // #else  // SOFTWARE_SPI
        return true;
       // #endif  // SOFTWARE_SPI

      fail:
        chipSelectHigh();
        return false;
}

//   errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;
//   chipSelectPin_ = chipSelectPin;
//   // 16-bit init start time allows over a minute
//   unsigned int t0 = millis();
//   uint32_t arg;

//   // set pin modes
//   pinMode(chipSelectPin_, OUTPUT);
//   digitalWrite(chipSelectPin_, HIGH);
//  // #ifndef USE_SPI_LIB
//   pinMode(SPI_MISO_PIN, INPUT);
//   pinMode(SPI_MOSI_PIN, OUTPUT);
//   pinMode(SPI_SCK_PIN, OUTPUT);
//  // #endif

//   // #ifndef SOFTWARE_SPI
//   // #ifndef USE_SPI_LIB
//   // // SS must be in output mode even it is not chip select
//   // pinMode(SS_PIN, OUTPUT);
//   // digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin
//   // // Enable SPI, Master, clock rate f_osc/128
//   // SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
//   // // clear double speed
//   // SPSR &= ~(1 << SPI2X);
//   // #else // USE_SPI_LIB
//   // SDCARD_SPI.begin();
//   // settings = SPISettings(250000, MSBFIRST, SPI_MODE0);
//   // #endif // USE_SPI_LIB
//   // #endif // SOFTWARE_SPI

//   // // must supply min of 74 clock cycles with CS high.
//   // #ifdef USE_SPI_LIB
//   // SDCARD_SPI.beginTransaction(settings);
//   // #endif
//   for (uint8_t i = 0; i < 10; i++) {
//     spiSend(0XFF);
//   }
//   // #ifdef USE_SPI_LIB
//   // SDCARD_SPI.endTransaction();
//   // #endif

//   chipSelectLow();

//   // command to go idle in SPI mode
//   while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
//     unsigned int d = millis() - t0;
//     if (d > SD_INIT_TIMEOUT) {
//       error(SD_CARD_ERROR_CMD0);
//       goto fail;
//     }
//   }
//   // check SD version
//   if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
//     type(SD_CARD_TYPE_SD1);
//   } else {
//     // only need last byte of r7 response
//     for (uint8_t i = 0; i < 4; i++) {
//       status_ = spiRec();
//     }
//     if (status_ != 0XAA) {
//       error(SD_CARD_ERROR_CMD8);
//       goto fail;
//     }
//     type(SD_CARD_TYPE_SD2);
//   }
//   // initialize card and send host supports SDHC if SD2
//   arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;

//   while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
//     // check for timeout
//     unsigned int d = millis() - t0;
//     if (d > SD_INIT_TIMEOUT) {
//       error(SD_CARD_ERROR_ACMD41);
//       goto fail;
//     }
//   }
//   // if SD2 read OCR register to check for SDHC card
//   if (type() == SD_CARD_TYPE_SD2) {
//     if (cardCommand(CMD58, 0)) {
//       error(SD_CARD_ERROR_CMD58);
//       goto fail;
//     }
//     if ((spiRec() & 0XC0) == 0XC0) {
//       type(SD_CARD_TYPE_SDHC);
//     }
//     // discard rest of ocr - contains allowed voltage range
//     for (uint8_t i = 0; i < 3; i++) {
//       spiRec();
//     }
//   }
//   chipSelectHigh();

//   #ifndef SOFTWARE_SPI
//   return setSckRate(sckRateID);
//   #else  // SOFTWARE_SPI
//   return true;
//   #endif  // SOFTWARE_SPI

// fail:
//   chipSelectHigh();
//   return false;
// }
//------------------------------------------------------------------------------
/**
   Enable or disable partial block reads.

   Enabling partial block reads improves performance by allowing a block
   to be read over the SPI bus as several sub-blocks.  Errors may occur
   if the time between reads is too long since the SD card may timeout.
   The SPI SS line will be held low until the entire block is read or
   readEnd() is called.

   Use this for applications like the Adafruit Wave Shield.

   \param[in] value The value TRUE (non-zero) or FALSE (zero).)
*/
void Sd2Card::partialBlockRead(uint8_t value) {
  readEnd();
  partialBlockRead_ = value;
}
//------------------------------------------------------------------------------
/**
   Read a 512 byte block from an SD card device.

   \param[in] block Logical block to be read.
   \param[out] dst Pointer to the location that will receive the data.

   \return The value one, true, is returned for success and
   the value zero, false, is returned for failure.
*/
uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) {
  return readData(block, 0, 512, dst);
}
//------------------------------------------------------------------------------
/**
   Read part of a 512 byte block from an SD card.

   \param[in] block Logical block to be read.
   \param[in] offset Number of bytes to skip at start of block
   \param[out] dst Pointer to the location that will receive the data.
   \param[in] count Number of bytes to read
   \return The value one, true, is returned for success and
   the value zero, false, is returned for failure.
*/
uint8_t Sd2Card::readData(uint32_t block,
                          uint16_t offset, uint16_t count, uint8_t* dst) {
  if (count == 0) {
    return true;
  }
  if ((count + offset) > 512) {
    goto fail;
  }
  if (!inBlock_ || block != block_ || offset < offset_) {
    block_ = block;
    // use address if not SDHC card
    if (type() != SD_CARD_TYPE_SDHC) {
      block <<= 9;
    }
    if (cardCommand(CMD17, block)) {
      error(SD_CARD_ERROR_CMD17);
      goto fail;
    }
    if (!waitStartBlock()) {
      goto fail;
    }
    offset_ = 0;
    inBlock_ = 1;
  }

  #ifdef OPTIMIZE_HARDWARE_SPI
  // start first spi transfer
  SPDR = 0XFF;

  // skip data before offset
  for (; offset_ < offset; offset_++) {
    while (!(SPSR & (1 << SPIF)))
      ;
    SPDR = 0XFF;
  }
  // transfer data
  n = count - 1;
  for (uint16_t i = 0; i < n; i++) {
    while (!(SPSR & (1 << SPIF)))
      ;
    dst[i] = SPDR;
    SPDR = 0XFF;
  }
  // wait for last byte
  while (!(SPSR & (1 << SPIF)))
    ;
  dst[n] = SPDR;

  #else  // OPTIMIZE_HARDWARE_SPI

  // skip data before offset
  for (; offset_ < offset; offset_++) {
    spiRec();
  }
  // transfer data
  for (uint16_t i = 0; i < count; i++) {
    dst[i] = spiRec();
  }
  #endif  // OPTIMIZE_HARDWARE_SPI

  offset_ += count;
  if (!partialBlockRead_ || offset_ >= 512) {
    // read rest of data, checksum and set chip select high
    readEnd();
  }
  return true;

fail:
  chipSelectHigh();
  return false;
}
//------------------------------------------------------------------------------
/** Skip remaining data in a block when in partial block read mode. */
void Sd2Card::readEnd(void) {
  if (inBlock_) {
    // skip data and crc
    #ifdef OPTIMIZE_HARDWARE_SPI
    // optimize skip for hardware
    SPDR = 0XFF;
    while (offset_++ < 513) {
      while (!(SPSR & (1 << SPIF)))
        ;
      SPDR = 0XFF;
    }
    // wait for last crc byte
    while (!(SPSR & (1 << SPIF)))
      ;
    #else  // OPTIMIZE_HARDWARE_SPI
    while (offset_++ < 514) {
      spiRec();
    }
    #endif  // OPTIMIZE_HARDWARE_SPI
    chipSelectHigh();
    inBlock_ = 0;
  }
}
//------------------------------------------------------------------------------
/** read CID or CSR register */
uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) {
  uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
  if (cardCommand(cmd, 0)) {
    error(SD_CARD_ERROR_READ_REG);
    goto fail;
  }
  if (!waitStartBlock()) {
    goto fail;
  }
  // transfer data
  for (uint16_t i = 0; i < 16; i++) {
    dst[i] = spiRec();
  }
  spiRec();  // get first crc byte
  spiRec();  // get second crc byte
  chipSelectHigh();
  return true;

fail:
  chipSelectHigh();
  return false;
}
//------------------------------------------------------------------------------
/**
   Set the SPI clock rate.

   \param[in] sckRateID A value in the range [0, 6].

   The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum
   SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128
   for \a scsRateID = 6.

   \return The value one, true, is returned for success and the value zero,
   false, is returned for an invalid value of \a sckRateID.
*/
uint8_t Sd2Card::setSckRate(uint8_t sckRateID) {
  if (sckRateID > 6) {
    error(SD_CARD_ERROR_SCK_RATE);
    return false;
  }
  // #ifndef USE_SPI_LIB
  // // see avr processor datasheet for SPI register bit definitions
  // if ((sckRateID & 1) || sckRateID == 6) {
  //   SPSR &= ~(1 << SPI2X);
  // } else {
  //   SPSR |= (1 << SPI2X);
  // }
  // SPCR &= ~((1 << SPR1) | (1 << SPR0));
  // SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0)
  //         | (sckRateID & 2 ? (1 << SPR0) : 0);
  // #else // USE_SPI_LIB
  // switch (sckRateID) {
  //   case 0:  settings = SPISettings(25000000, MSBFIRST, SPI_MODE0); break;
  //   case 1:  settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); break;
  //   case 2:  settings = SPISettings(2000000, MSBFIRST, SPI_MODE0); break;
  //   case 3:  settings = SPISettings(1000000, MSBFIRST, SPI_MODE0); break;
  //   case 4:  settings = SPISettings(500000, MSBFIRST, SPI_MODE0); break;
  //   case 5:  settings = SPISettings(250000, MSBFIRST, SPI_MODE0); break;
  //   default: settings = SPISettings(125000, MSBFIRST, SPI_MODE0);
  // }
  // #endif // USE_SPI_LIB
  return true;
}
#ifdef USE_SPI_LIB
//------------------------------------------------------------------------------
// set the SPI clock frequency
uint8_t Sd2Card::setSpiClock(uint32_t clock) {
 // settings = SPISettings(clock, MSBFIRST, SPI_MODE0);
  return true;
}
#endif
//------------------------------------------------------------------------------
// wait for card to go not busy
uint8_t Sd2Card::waitNotBusy(unsigned int timeoutMillis) {
  unsigned int t0 = millis();
  unsigned int d;
  do {
    if (spiRec() == 0XFF) {
      return true;
    }
    d = millis() - t0;
  } while (d < timeoutMillis);
  return false;
}
//------------------------------------------------------------------------------
/** Wait for start block token */
uint8_t Sd2Card::waitStartBlock(void) {
  unsigned int t0 = millis();
  while ((status_ = spiRec()) == 0XFF) {
    unsigned int d = millis() - t0;
    if (d > SD_READ_TIMEOUT) {
      error(SD_CARD_ERROR_READ_TIMEOUT);
      goto fail;
    }
  }
  if (status_ != DATA_START_BLOCK) {
    error(SD_CARD_ERROR_READ);
    goto fail;
  }
  return true;

fail:
  chipSelectHigh();
  return false;
}
//------------------------------------------------------------------------------
/**
   Writes a 512 byte block to an SD card.

   \param[in] blockNumber Logical block to be written.
   \param[in] src Pointer to the location of the data to be written.
   \param[in] blocking If the write should be blocking.
   \return The value one, true, is returned for success and
   the value zero, false, is returned for failure.
*/
uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src, uint8_t blocking) {
  #if SD_PROTECT_BLOCK_ZERO
  // don't allow write to first block
  if (blockNumber == 0) {
    error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
    goto fail;
  }
  #endif  // SD_PROTECT_BLOCK_ZERO

  // use address if not SDHC card
  if (type() != SD_CARD_TYPE_SDHC) {
    blockNumber <<= 9;
  }
  if (cardCommand(CMD24, blockNumber)) {
    error(SD_CARD_ERROR_CMD24);
    goto fail;
  }
  if (!writeData(DATA_START_BLOCK, src)) {
    goto fail;
  }
  if (blocking) {
    // wait for flash programming to complete
    if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
      error(SD_CARD_ERROR_WRITE_TIMEOUT);
      goto fail;
    }
    // response is r2 so get and check two bytes for nonzero
    if (cardCommand(CMD13, 0) || spiRec()) {
      error(SD_CARD_ERROR_WRITE_PROGRAMMING);
      goto fail;
    }
  }
  chipSelectHigh();
  return true;

fail:
  chipSelectHigh();
  return false;
}
//------------------------------------------------------------------------------
/** Write one data block in a multiple block write sequence */
uint8_t Sd2Card::writeData(const uint8_t* src) {
  // wait for previous write to finish
  if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
    error(SD_CARD_ERROR_WRITE_MULTIPLE);
    chipSelectHigh();
    return false;
  }
  return writeData(WRITE_MULTIPLE_TOKEN, src);
}
//------------------------------------------------------------------------------
// send one block of data for write block or write multiple blocks
uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) {
  #ifdef OPTIMIZE_HARDWARE_SPI

  // send data - optimized loop
  SPDR = token;

  // send two byte per iteration
  for (uint16_t i = 0; i < 512; i += 2) {
    while (!(SPSR & (1 << SPIF)))
      ;
    SPDR = src[i];
    while (!(SPSR & (1 << SPIF)))
      ;
    SPDR = src[i + 1];
  }

  // wait for last data byte
  while (!(SPSR & (1 << SPIF)))
    ;

  #else  // OPTIMIZE_HARDWARE_SPI
  spiSend(token);
  for (uint16_t i = 0; i < 512; i++) {
    spiSend(src[i]);
  }
  #endif  // OPTIMIZE_HARDWARE_SPI
  spiSend(0xff);  // dummy crc
  spiSend(0xff);  // dummy crc

  status_ = spiRec();
  if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
    error(SD_CARD_ERROR_WRITE);
    chipSelectHigh();
    return false;
  }
  return true;
}
//------------------------------------------------------------------------------
/** Start a write multiple blocks sequence.

   \param[in] blockNumber Address of first block in sequence.
   \param[in] eraseCount The number of blocks to be pre-erased.

   \note This function is used with writeData() and writeStop()
   for optimized multiple block writes.

   \return The value one, true, is returned for success and
   the value zero, false, is returned for failure.
*/
uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
  #if SD_PROTECT_BLOCK_ZERO
  // don't allow write to first block
  if (blockNumber == 0) {
    error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
    goto fail;
  }
  #endif  // SD_PROTECT_BLOCK_ZERO
  // send pre-erase count
  if (cardAcmd(ACMD23, eraseCount)) {
    error(SD_CARD_ERROR_ACMD23);
    goto fail;
  }
  // use address if not SDHC card
  if (type() != SD_CARD_TYPE_SDHC) {
    blockNumber <<= 9;
  }
  if (cardCommand(CMD25, blockNumber)) {
    error(SD_CARD_ERROR_CMD25);
    goto fail;
  }
  return true;

fail:
  chipSelectHigh();
  return false;
}
//------------------------------------------------------------------------------
/** End a write multiple blocks sequence.

  \return The value one, true, is returned for success and
   the value zero, false, is returned for failure.
*/
uint8_t Sd2Card::writeStop(void) {
  if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
    goto fail;
  }
  spiSend(STOP_TRAN_TOKEN);
  if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
    goto fail;
  }
  chipSelectHigh();
  return true;

fail:
  error(SD_CARD_ERROR_STOP_TRAN);
  chipSelectHigh();
  return false;
}
//------------------------------------------------------------------------------
/** Check if the SD card is busy

  \return The value one, true, is returned when is busy and
   the value zero, false, is returned for when is NOT busy.
*/
uint8_t Sd2Card::isBusy(void) {
  chipSelectLow();
  char b = spiRec();  //****
  chipSelectHigh();

  return (b != 0XFF);
}

#endif

加快编译速度的方法 

删除asr_pro_sdk\projects\offline_asr_sample\project_file\build\objs 下对应的 中间文件;

使用./build 一下 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1695876.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

11.jenkins调整上线的脚本实现tag方式上线

jenkins调整上线的脚本实现tag方式上线 多次打标签重新提交到gitlab远程仓库-基于multi-line string parameter 修改脚本html_deploy_tar.sh #!/usr/bin/bashDate$(date %F-%H-%M) web_server"192.168.111.22 192.168.111.23" Name${Date}-${git_version} code_t…

etcd集群部署

1.etcd介绍 1.1 什么是etcd etcd的官方定义如下: A distributed, reliable key-value store for the most critical data of distributed systemetcd是一个Go语言编写的分布式、高可用的一致性键值存储系统,用于提供可靠的分布式键值(key value)存储、配置共享和服务发现等…

学习Uni-app开发小程序Day18

昨天学习了使用轮播显示图片和文字&#xff0c;轮播方式纵向和横向。今天使用扩展组件和scroll-view显示图片&#xff0c;使用scroll-view的grid方式、插槽slot、自定义组件、磨砂背景定位布局做专题组件 这就是需要做成的效果&#xff0c;下面将一步一步的完成。 首先&#x…

005、API_数据结构

键的数据结构类型&#xff0c;它们分别是&#xff1a; string&#xff08;字符串&#xff09;、hash&#xff08;哈希&#xff09;、list&#xff08;列表&#xff09;、set&#xff08;集合&#xff09;、zset&#xff08;有序集 合&#xff09;&#xff0c;这些只是Redis对外…

word 全文中 英文字体 和 样式的字体 莫名奇妙地 被改成 “等线”

word全文中英文字体和样式的字体莫名奇妙地被改成“等线” sm word又抽风了&#xff0c;改完论文保存后打开突然发现全文字体都不对劲&#xff0c;吓得冷汗直冒&#xff1a;虽然我用git管理了论文版本&#xff0c;但是只有比较大的修改我才上传了&#xff0c;刚刚修了几个小时…

Pycharm2024搭建QT6开发环境

创建pyqt6虚拟环境 首先&#xff0c;创建一个qt6的虚拟环境&#xff1a; conda create --name pyqt6 python3.11.7激活环境&#xff1a; conda activate pyqt6安装pyqt6 安装pyqt6&#xff1a; pip install pyqt6创建代码目录 创建目录&#xff1a; 使用pycharm打开这个…

unity开发Hololens 制作滑动框

一定要做到最后一步&#xff0c;才会有效果 1、创建空物体 ,并添加组件 创建空物体 命名ScrollingObjectCollection&#xff0c; 添加组件如下图 下面是各个组件展开的内容 2、在ScrollingObjectCollection 下面创建两个空物体&#xff0c;分别命名Container、Clipping…

【面试干货】猴子吃桃问题

【面试干货】猴子吃桃问题 1、实现思想2、代码实现 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 猴子吃桃问题&#xff1a;猴子第一天摘下若干个桃子&#xff0c;当即吃了一半&#xff0c;还不瘾&#xff0c;又多吃了一个 二天早上又将剩…

高职物联网专业嵌入式系统开发教学解决方案

前言 随着人工智能与物联网技术的深度融合&#xff0c;物联网&#xff08;AIoT&#xff09;已成为推动产业发展的重要力量。高职物联网专业作为培养技术人才的重要基地&#xff0c;面临着课程体系更新、教学内容优化的迫切需求。嵌入式系统开发作为物联网专业的核心课程之一&a…

服务器硬件全攻略:从入门到精通,全面解析服务器性能与稳定性!

服务器是计算机网络中提供特定服务的计算机系统&#xff0c;其硬件配置和性能直接影响到整个网络系统的运行效率和稳定性。作为一个资深的技术人员&#xff0c;本文将全面详细地介绍服务器硬件基础知识&#xff0c;包括介绍、命令或语法、主要作用以及使用方法等。 一、介绍 服…

uniapp+php服务端实现苹果iap内购的消耗性项目和非续期订阅项目,前后端代码加逻辑分析

前言&#xff1a;公司的项目app在上架苹果商店时发现人家要求里面的部分购买项目必须使用iap购买的方式&#xff0c;使用原本的微信支付方式审核不给通过&#xff0c;无奈只能重新研究这个东西。做起来还是有点麻烦&#xff0c;主要是网上的文章很少&#xff0c;不能直接硬抄。…

Nature Communications | 柔性半导体器件的大规模集成(柔性半导体器件/柔性电子)

韩国中央大学Sung Kyu Park、 韩国成均馆大学Jong-Woong Kim和Yong-Hoon Kim团队,在《Nature Communications》上发布了一篇题为“Full integration of highly stretchable inorganic transistors and circuits within molecular-tailored elastic substrates on a large scal…

QGraphicsView实现简易地图16『爆炸效果』

前文链接&#xff1a;QGraphicsView实现简易地图15『测量面积』 一种简单的爆炸波扩散效果 动态演示效果&#xff1a; 静态展示图片&#xff1a; 核心代码&#xff1a; #pragma once #include "../AbstractGeoItem.h" #include "DataStruct/GeoData.h"…

C++ STL 函数对象:隐藏的陷阱,如何避免状态带来的麻烦?

STL 函数对象&#xff1a;无状态即无压力 一、简介二、函数对象三、避免在函数对象中保存状态3.1、函数对象3.2、lambda 表达式 四、选择合适的更高层次的结构五、总结 一、简介 在使用 C 标准模板库 (STL) 时&#xff0c;函数对象 (Function Object) 是一种强大的工具&#x…

我的文章分类合集目录

文章目录 Java相关基础常规问题类Docker类RabbitMQ类分库分表 网络工程相关路由交换、Cisco Packet TracerIP地址 前端相关数据库 Java相关 基础 Java开发规范、项目开发流程 SpringBoot整合MyBatis实现增删改查(简单,详细) SpringBoot整合MybatisPlus&#xff08;详细&#…

C++ vector类

目录 0.前言 1.vector介绍 2.vector使用 2.1 构造函数(Constructor) 2.1.1. 默认构造函数 (Default Constructor) 2.1.2 填充构造函数 (Fill Constructor) 2.1.3 范围构造函数 (Range Constructor) 2.1.4 拷贝构造函数 (Copy Constructor) 2.2 迭代器(Iterator) 2.2.…

基于移动多媒体信源与信道编码调研

前言 移动多媒体是指在移动通信环境下&#xff0c;通过无线网络传输的音频、视频、图像等多种媒体信息。移动多媒体的特点是数据量大、传输速率高、服务质量要求高&#xff0c;因此对信源编码和信道编码的性能提出了更高的要求。 本文对进3年的移动多媒体信源与信道编码的研究…

信息系统项目管理师0130:工具与技术(8项目整合管理—8.7监控项目工作—8.7.2工具与技术)

点击查看专栏目录 文章目录 8.7.2 工具与技术8.7.2 工具与技术 专家判断监控项目工作过程中,应征求具备如下领域相关专业知识或接受过相关培训的个人或小组的意见,涉及的领域包括:挣值分析;数据的解释和情境化;持续时间和成本的估算技术;趋势分析;关于项目所在的行业以及…

爬虫案例-亚马逊反爬流程分析梳理(验证码突破)(x-amz-captcha)

总体概览&#xff1a;核心主要是需要突破该网站的验证码&#xff0c;成功后会返回我们需要的参数后再去请求一个中间页&#xff08;类似在后台注册一个session&#xff09;&#xff0c;最后需要注意一下 IP 是不能随意切换的 主要难点&#xff1a; 1、梳理整体反爬流程 2、验证…

家政预约小程序01用户注册

目录 1 创建数据源2 创建应用3 创建页面4 用户注册5 角色选择6 设置首页总结 学习低代码的时候&#xff0c;使用官方模板搭建无疑是一个很好的途径。但是低代码工具更新比较频繁&#xff0c;基本每两周就要迭代一个版本。随着官方版本的迭代&#xff0c;官方模板安装好之后会有…