
SM AD/DA 확장테스트 보드에는 표준 핀맵의 AD/DA 모듈을 연결할 수 있다. RP2350의 SPI 인터페이스로 16bit DAC DAC80502 모듈을 테스트 해보자.
RP2350의 SPI는 GP18, GP16, GP19 에 할당되어 있고 DAC80502 CS핀은 GP17에 연결되어있다.

AD/DA 모듈 핀맵

DAC80502 관련 라이브러리는 제공하는것이 없기 때문에 간단하게 사용할수 있도록 작성해 보았다.
#ifndef DAC80502_H
#define DAC80502_H
#include <Arduino.h>
#include <SPI.h>
#define REG4_DIVGAIN 0x04
#define REG5_RESET 0x05
#define REG8_DAC 0x08
#define REG8_DAC2 0x09
#define SET5_RESET 0x00A0
#define SET4_GAIN1 0x00
#define SET4_GAIN2 0x01
#define SET4_DIV1 0x00
#define SET4_DIV2 0x01
class DAC80502
{
public:
DAC80502 ();
~DAC80502 ();
void begin(uint8_t cs_pin);
void end ();
void writeREG(uint8_t command, uint8_t b1, uint8_t b2);
void setREG4_DivGain(uint8_t div, uint8_t gain);
void writeDAC(uint16_t data);
void writeDAC2(uint16_t data);
void setClockSpeed(uint32_t cspeed);
private:
uint8_t DacCsPin = 0;
};
#endif /* DAC80502_H */
#include <Arduino.h>
#include <SPI.h>
#include "DAC80502.h"
DAC80502::DAC80502()
{
}
DAC80502::~DAC80502()
{
SPI_ID.end();
}
void DAC80502::writeREG(uint8_t command, uint8_t b1, uint8_t b2)
{
digitalWrite(DacCsPin,HIGH);
delay(1);
digitalWrite(DacCsPin,LOW);
delayMicroseconds(1);
SPI_ID.transfer(command);
SPI_ID.transfer(b1);
SPI_ID.transfer(b2);
delay(1);
digitalWrite(DacCsPin,HIGH);
}
void DAC80502::setREG4_DivGain(uint8_t div, uint8_t gain)
{
writeREG(REG4_DIVGAIN, div , gain);
}
void DAC80502::setREG5_Reset()
{
writeREG(REG5_RESET, 0b00000000 ,0b00001010); // Soft Reset
}
void DAC80502::writeDAC(uint16_t data)
{
digitalWrite(DacCsPin,LOW);
SPI_ID.transfer(REG8_DAC);
SPI_ID.transfer(data>>8);
SPI_ID.transfer(data&0xFF);
digitalWrite(DacCsPin,HIGH);
}
void DAC80502::writeDAC2(uint16_t data)
{
digitalWrite(DacCsPin,LOW);
SPI_ID.transfer(REG8_DAC2);
SPI_ID.transfer(data>>8);
SPI_ID.transfer(data&0xFF);
digitalWrite(DacCsPin,HIGH);
}
void DAC80502::begin(uint8_t cs_pin)
{
DacCsPin = cs_pin;
pinMode(cs_pin, OUTPUT); // CS output
digitalWrite(DacCsPin,HIGH);
delay(1);
SPI_ID.begin();
SPI_ID.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE1));
delay(1);
setREG5_Reset();
setREG4_DivGain(SET4_DIV2, SET4_GAIN2); // div=2 gain=2
}
void DAC80502::end()
{
SPI_ID.end();
}
DAC80502 출력 함수
#define DAC_FACTOR (VREF/0xFFFF*1000)
#define VREF 2.5 // 출력 범위 2.5V (이론상 -1.25V ~ +1.25V 범위)
#define DAC_RESOLUTION 65535 // 16비트 DAC의 최대 값 (0에서 65535까지)
#define VOLTAGE_SCALE 10000 // 1V = 10000 (0.1mV 단위로 표현)
void VoltageOut(int DacChannel, int MilliVolt) {
// 입력값을 0.1mV 단위로 받음. 이를 전압으로 변환 (-1.25V ~ +1.25V)
float voltage = (float)tenthMilliVolt / 10000.0;
// 입력 전압을 -1.25V ~ +1.25V 범위로 변환
unsigned int dacValue = (unsigned int)((((voltage + 1.25) / VREF) * DAC_RESOLUTION));
// 범위를 벗어나지 않도록 제한
if (dacValue > DAC_RESOLUTION) {
dacValue = DAC_RESOLUTION;
} else if (dacValue < 0) {
dacValue = 0;
}
// 디버깅 출력 (변환된 DAC 값과 입력된 전압 출력)
//Serial.printf("Input (0.1mV): %d, Voltage: %.4f V, DAC Output: %u\r\n", tenthMilliVolt, voltage, dacValue);
// DAC에 값을 출력
if(DacChannel == 0)dac.writeDAC(dacValue); // DAC 객체의 writeDAC 메소드 호출
else if(DacChannel == 1)dac.writeDAC2(dacValue); // DAC 객체의 writeDAC 메소드 호출
else if(DacChannel == 2)
{
dac.writeDAC(dacValue);
dac.writeDAC2(dacValue);
}
}
DAC80502 테스트 코드
#include <SPI.h>
#include "DAC80502.h"
#define DAC_CS_PIN 17
DAC80502 dac;
int gOutVoltageValue = 580;
void setup()
{
Serial.begin(115200);
//while (!Serial);
dac.begin(DAC_CS_PIN);
dac.setREG4_DivGain(SET4_DIV1, SET4_GAIN1); // div=1 gain=1 ->1.25V
dac.writeREG(3, 1, 0); // external VREF
VoltageOut(gOutVoltageValue);
}
반응형