asrpro softspi SD卡读写

采样 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 一下 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GDB对Linux信号的处理方式

前言 在软件开发过程中&#xff0c;调试工具是程序员不可或缺的助手。GDB&#xff08;GNU Debugger&#xff09;作为一个强大的调试器&#xff0c;广泛应用于Linux系统中的C/C程序调试。然而&#xff0c;信号处理机制的复杂性常常给调试带来挑战。特别是在处理异步和同步信号时…

React中 将UI 视为树

当 React 应用程序逐渐成形时&#xff0c;许多组件会出现嵌套。那么 React 是如何跟踪应用程序组件结构的&#xff1f; React 以及许多其他 UI 库&#xff0c;将 UI 建模为树。将应用程序视为树对于理解组件之间的关系以及调试性能和状态管理等未来将会遇到的一些概念非常有用。…

加入MongoDB AI创新者计划,携手MongoDB共同开创AI新纪元

加入MongoDB AI创新者计划&#xff01; MongoDB对AI创新和初创企业的支持既全面又广泛&#xff01;无论您是领先的AI初创企业还是刚刚起步&#xff0c;MongoDB Atlas都是支持您愿景的最佳平台。 AI 初创者计划The AI Startup Track AI初创者计划为早期初创企业提供专属福利&…

CHI协议_1

作者&#xff1a;someone链接&#xff1a;https://www.zhihu.com/question/304259901/answer/3455648666来源。 1. AMBA CHI简介 一致性总线接口&#xff08;CHI&#xff09;是AXI一致性扩展&#xff08;ACE&#xff09;协议的演进。它是Arm的AMBA总线的一部分。AMBA是一种免…

鸿蒙ArkTS声明式开发:跨平台支持列表【触摸事件】

触摸事件 当手指在组件上按下、滑动、抬起时触发。 说明&#xff1a; 开发前请熟悉鸿蒙开发指导文档&#xff1a; gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独…

WEB攻防【1】——ASP应用/HTTP.SYS/短文件/文件解析/Access注入/数据库泄漏

ASP&#xff1a;常见漏洞&#xff1a;本文所写这些 ASPX&#xff1a;未授权访问、报错爆路径、反编译 PHP&#xff1a;弱类型对比、mdb绕过、正则绕过&#xff08;CTF考得多&#xff09; JAVA&#xff1a;反序列化漏洞 Python&#xff1a;SSTI、字符串、序列化 Javascript&…

openEuler 22.03 LTS SP3源码编译部署OpenStack-Caracal

openEuler 22.03 LTS SP3源码编译部署OpenStack-Caracal 说明机器详情安装操作系统注意事项基础准备Controller节点 && Compute节点 && Block节点关闭防火墙关闭selinux设置静态IP更新安装前准备Controller节点 && Compute节点 && Block节点设…

Linux系统启动原理

Linux系统启动原理及故障排除 Centos6系统启动过程 修改系统启动级别 vim /etc/inittabCentos7启动流程 加载BIOS信息&#xff0c;进行硬件检测 根据BIOS设定读取设备中的MBR&#xff0c;加载Boot loader 加载内核&#xff0c;内核初始化以后以模块的形式动态加载硬件 并且加…

嵌入式进阶——蜂鸣器

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 蜂鸣器原理图测试发声乐理知识乐理应用PWM测试发声PWM驱动封装 蜂鸣器 蜂鸣器是一种能够产生固定频率的声音的电子元件。它通常由…

MySQL数据库中的多表查询/连接查询操作

类型&#xff1a;内连接 &#xff0c;外连接{左外连接&#xff0c;右外连接} 之所以要使用连接查询的意义就是为了&#xff0c;借助数据库可以避免大量的数据重复。 进行连接查询的前提是要求多张表之间存在相关联的字段。 这里指的相关联的字段就是表与表之间存在着关系&am…

linux 常用命令:find grep ps netstat sudo df du rm

rm 命令 删除 -r 是递归参数&#xff08;recursive&#xff09;&#xff0c;用于删除目录及其内容。如果不加这个参数&#xff0c;rm 命令无法删除非空目录。-f 是强制参数&#xff08;force&#xff09;&#xff0c;用于强制删除文件或目录&#xff0c;不会进行任何确认提示…

windows 搭建 go开发环境

go语言&#xff08;或 Golang&#xff09;是Google开发的开源编程语言&#xff0c;诞生于2006年1月2日下午15点4分5秒&#xff0c;于2009年11月开源&#xff0c;2012年发布go稳定版。Go语言在多核并发上拥有原生的设计优势&#xff0c;Go语言从底层原生支持并发&#xff0c;无须…

Android network — 进程指定网络发包

Android network — 进程指定网络发包 0. 前言1. 进程绑定网络1.1 App进程绑定网络1.2 Native进程绑定网络 2. 源码原理分析2.1 申请网络requestNetwork2.2 绑定网络 BindProcessToNetwork 3. 总结 0. 前言 在android 中&#xff0c;一个app使用网络&#xff0c;需要在manifest…

从零开始搭建Springboot项目脚手架4:保存操作日志

目的&#xff1a;通过AOP切面&#xff0c;统一记录接口的访问日志 1、加maven依赖 2、 增加日志类RequestLog 3、 配置AOP切面&#xff0c;把请求前的request、返回的response一起记录 package com.template.common.config;import cn.hutool.core.util.ArrayUtil; import cn.hu…

【C/C++】Makefile文件的介绍与基本用法

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

烟囱ERP系统

一、烟囱系统定义 “烟囱式”系统&#xff0c;来自维基百科的解释是&#xff1a;一种不能与其他系统进行有效协调工作的信息系统&#xff0c;又称为孤岛系统。 二、烟囱系统的案例 比如&#xff1a;就像以下一样&#xff0c;各个系统之间是独立的&#xff0c;所有对接是通过…

揭秘Markdown:轻松掌握基础语法,让你的写作更高效、优雅!

文章目录 前言1.标题1.1 使用 和 - 标记一级和二级标题1.2 使用 # 号标记 2.段落格式2.1 字体2.2 分割线2.3 删除线2.4 下划线2.5 脚注 3.列表3.1 无序列表3.2 有序列表3.3 列表嵌套 4.区块4.1 区块中使用列表4.2 列表中使用区块 5.代码代码区块 6.链接7.图片8.表格9.高级技巧…

访问元组元素

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;如果想将元组的内容输出也比较简单&#xff0c;可以直接使用print()函数即可。例如&#xff0c;要想打印上面元组中的untitle…

嵌入式进阶——震动马达

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 原理图控制分析功能设计 原理图 控制分析 S8050 NPN三极管特性 NPN型三极管的工作原理是基于PN结和PNP型晶体管的工作原理。 当外…

【大数据面试题】32 Flink 怎么重复读 Kafka?

一步一个脚印&#xff0c;一天一道面试题 首先&#xff0c;为什么要读过的 Kafka 数据重写读一次呢&#xff1f;什么场景下要怎么做呢&#xff1f; 答&#xff1a;当任务失败&#xff0c;从检查点Checkpoint 开始重启时&#xff0c;检查点的数据是之前的了&#xff0c;就需要…