0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

秋月MCP3564をRP2350で動かす

Posted at

これなに?

秋月で売ってる良さげなADCをrp2350で動かすだけです。データシート読みつつ、1日ほど苦戦したので残します。

どうやって使うんだYo!

SPIなので、それぞれの端子を以下のように結線します。
で、初期化は以下のようにします。

# fastコマンドを送信 (RESET)
> 0x78

# CONFIG0_REG = 0x01   # CONFIG0レジスタのアドレス
# ADDR = 0x01          # デバイスのアドレス (SPI)
# CMD_INC_WRITE = 0x02 # 連続書き込み
command = (ADDR << 6) | (CONFIG0_REG << 2) | (CMD_INC_WRITE & 0x03);
# 内部クロックを使用する + 計測スタンバイモード
> command 0x32

# CONFIG1_REG = 0x02   # CONFIG2レジスタのアドレス
command = (ADDR << 6) | (CONFIG1_REG << 2) | (CMD_INC_WRITE & 0x03);
# OSR = 1024 階調に設定
> command 0x0E

# CONFIG2_REG = 0x03   # CONFIG2レジスタのアドレス
command = (ADDR << 6) | (CONFIG2_REG << 2) | (CMD_INC_WRITE & 0x03);
# BOOST = x1, GAIN = x1に設定
> command 0x8B

# CONFIG3_REG = 0x04
command = (ADDR << 6) | (CONFIG3_REG << 2) | (CMD_INC_WRITE & 0x03);
# 継続変換モード (内部で変換を連続して行う, モードによっては一回変換すると動作が止まるやつもある)
> command 0xC0

# IRQ_REG = 0x05
command = (ADDR << 6) | (IRQ_REG << 2) | (CMD_INC_WRITE & 0x03);
# プルアップしていない場合は,0x07を設定する.
> command 0x07

# ADCを開始する
> 0x68

として,あとはADCDATA_REG(0x00)を読み出すするだけでOK. その場合はCMD_INC_READ(0x03)を使って読み込みます.返してくるビットの形式などは,上記のレジスタの部分で変えることができます.
より細かい設定は,全てデータシート(80ページあたり)に書いてあるので,そちらを参照してください.

データシートにはどの流れで設定すればいいか,簡単に書いておらず,書き込み順序が違うとちゃんと動きませんでした.

で,プログラムは?

はい,実際のコードです.

#include <SPI.h>

// ピンアサイン定義
// ADC0
#define ADC0_IRQ_PIN 16
#define ADC0_CS_PIN 17
#define ADC0_SCK_PIN 18
#define ADC0_MOSI_PIN 19
#define ADC0_MISO_PIN 20

// ADC1
#define ADC1_IRQ_PIN 24
#define ADC1_CS_PIN 25
#define ADC1_SCK_PIN 26
#define ADC1_MOSI_PIN 27
#define ADC1_MISO_PIN 28

// MCP3564 レジスタアドレス
#define ADCDATA_REG 0x0
#define CONFIG0_REG 0x1
#define CONFIG1_REG 0x2
#define CONFIG2_REG 0x3
#define CONFIG3_REG 0x4
#define IRQ_REG 0x5
#define MUX_REG 0x6

// コマンドタイプ
#define CMD_STATIC_READ 0x01
#define CMD_INCR_WRITE 0x02
#define CMD_INCR_READ 0x03

// デバイスアドレス
#define DEVICE_ADDR 0x40

// Fast Commands
#define FAST_CMD_START 0x68
#define FAST_CMD_STANDBY 0x6C
#define FAST_CMD_SHUTDOWN 0x70
#define FAST_CMD_RESET 0x78

// SPI設定(10MHz)
SPISettings spiSettings(10000000, MSBFIRST, SPI_MODE0);

// MUX設定定義(シングルエンド CHx-AGND)
uint8_t mux_ch0_8[] = {0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88}; // CH0-AGND ~ CH8-AGND
uint8_t mux_special[] = {0xDE, 0x98, 0x88}; 

void setup() {
  Serial.begin(115200); 
  while (!Serial) {
    delay(10);
  }
  
  // ADC0 SPI設定
  pinMode(ADC0_CS_PIN, OUTPUT);
  digitalWrite(ADC0_CS_PIN, HIGH);
  SPI.setMISO(ADC0_MISO_PIN);
  SPI.setMOSI(ADC0_MOSI_PIN);
  SPI.setSCK(ADC0_SCK_PIN);
  SPI.begin();

  // ADC1 SPI設定
  pinMode(ADC1_CS_PIN, OUTPUT);
  digitalWrite(ADC1_CS_PIN, HIGH);
  SPI1.setMISO(ADC1_MISO_PIN);
  SPI1.setMOSI(ADC1_MOSI_PIN);
  SPI1.setSCK(ADC1_SCK_PIN);
  SPI1.begin();

  delay(50); 
  
  // 両方のADCを初期化
  initializeADC(0);
  initializeADC(1);
}

void loop() {
    int adc_num = 0;
    int ch = 0;
    writeRegister(adc_num, MUX_REG, mux_ch0_8[ch]);
    delay(1); 
  
    // ADCデータ読み取り
    uint32_t adc_data = readADCData(adc_num);

    // 24ビット符号付き整数に変換
    int32_t signed_data;
    if (adc_data & 0x800000) {
        signed_data = (int32_t)(adc_data | 0xFF000000);
    } else {
        signed_data = (int32_t)adc_data;
    }

    // シングルエンド
    float voltage = ((float)signed_data / 8388608.0f) * 3.27f;
    // 温度の時: 0.00133f * (float)signed_data - 267.146f;
    // その他の時: ((float)signed_data / 8388608.0f) * 3.27f;
}

void initializeADC(int adc_num) {
  // フルリセット
  sendFastCommandReturn(adc_num, FAST_CMD_RESET);
  delay(1);

  writeRegister(adc_num, CONFIG0_REG, 0x32); // Internal clock, conversion
  delay(1);
  writeRegister(adc_num, CONFIG1_REG, 0x0E); // OSR=1024 (高精度維持)
  writeRegister(adc_num, CONFIG2_REG, 0x8B); // BOOST=1x, GAIN=1x
  writeRegister(adc_num, CONFIG3_REG, 0xC0); // Continuous mode
  writeRegister(adc_num, IRQ_REG,     0x07); // IRQ settings

  // ADC開始
  sendFastCommandReturn(adc_num, FAST_CMD_START);
  delay(1);
}

uint8_t sendFastCommandReturn(int adc_num, uint8_t fast_cmd) {
  uint8_t status = 0;
  
  if (adc_num == 0) {
    SPI.beginTransaction(spiSettings);
    digitalWrite(ADC0_CS_PIN, LOW);
    // delayMicroseconds削除 - SPI速度に依存
    status = SPI.transfer(fast_cmd);
    digitalWrite(ADC0_CS_PIN, HIGH);
    SPI.endTransaction();
  } else {
    SPI1.beginTransaction(spiSettings);
    digitalWrite(ADC1_CS_PIN, LOW);
    status = SPI1.transfer(fast_cmd);
    digitalWrite(ADC1_CS_PIN, HIGH);
    SPI1.endTransaction();
  }
  return status;
}

void writeRegister(int adc_num, uint8_t reg, uint8_t data) {
  uint8_t command = DEVICE_ADDR | (reg << 2) | (CMD_INCR_WRITE & 0x03);
  
  if (adc_num == 0) {
    SPI.beginTransaction(spiSettings);
    digitalWrite(ADC0_CS_PIN, LOW);
    SPI.transfer(command);
    SPI.transfer(data);
    digitalWrite(ADC0_CS_PIN, HIGH);
    SPI.endTransaction();
  } else {
    SPI1.beginTransaction(spiSettings);
    digitalWrite(ADC1_CS_PIN, LOW);
    SPI1.transfer(command);
    SPI1.transfer(data);
    digitalWrite(ADC1_CS_PIN, HIGH);
    SPI1.endTransaction();
  }
}

uint32_t readADCData(int adc_num) {
  uint8_t command = DEVICE_ADDR | (ADCDATA_REG << 2) | (CMD_INCR_READ & 0x03);
  uint32_t result = 0;
  
  if (adc_num == 0) {
    SPI.beginTransaction(spiSettings);
    digitalWrite(ADC0_CS_PIN, LOW);
    
    uint8_t status = SPI.transfer(command);
    uint8_t byte1 = SPI.transfer(0x00);
    uint8_t byte2 = SPI.transfer(0x00);
    uint8_t byte3 = SPI.transfer(0x00);
    
    result = ((uint32_t)byte1 << 16) | ((uint32_t)byte2 << 8) | byte3;
    
    digitalWrite(ADC0_CS_PIN, HIGH);
    SPI.endTransaction();
  } else {
    SPI1.beginTransaction(spiSettings);
    digitalWrite(ADC1_CS_PIN, LOW);
    
    uint8_t status = SPI1.transfer(command);
    uint8_t byte1 = SPI1.transfer(0x00);
    uint8_t byte2 = SPI1.transfer(0x00);
    uint8_t byte3 = SPI1.transfer(0x00);
    
    result = ((uint32_t)byte1 << 16) | ((uint32_t)byte2 << 8) | byte3;
    
    digitalWrite(ADC1_CS_PIN, HIGH);
    SPI1.endTransaction();
  }
  
  return result;
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?