これなに?
秋月で売ってる良さげな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;
}