Работа с АЦП AD7710 и её Российским аналогом 1273ПВ8Р.
#define TRUE 1
#define FALSE 0
//определение используемых пинов
#define DRDY 7
#define RFS 9
#define TFS 8
#define AO 11
#define SCLK 13
#define SDATA 12
#define SYNC 10
//Operating modes
#define NORMAL_MODE 0x00000000
#define SELF_CALIBRATION 0x00200000
#define SYSTEM_CALIBRATION_1 0x00400000
#define SYSTEM_CALIBRATION_2 0x00600000
#define OFFSET_CALIBRATION 0x00800000
#define BACKGROUND_CALIBRATION 0x00A00000
#define RW_ZERO_SCALE_COEF 0x00C00000
#define RW_FULL_SCALE_COEF 0x00E00000
//Gain
#define GAIN_1 0x00000000
#define GAIN_2 0x00040000
#define GAIN_4 0x00080000
#define GAIN_8 0x000C0000
#define GAIN_16 0x00100000
#define GAIN_32 0x00140000
#define GAIN_64 0x00180000
#define GAIN_128 0x001C0000
//Channel selection
#define CHANNEL_1 0x00000000
#define CHANNEL_2 0x00020000
//Power down
#define PWR_NORMAL 0x00000000
#define PWR_DOWN 0x00010000
//Word length
#define WORD_16 0x00000000
#define WORD_24 0x00008000
//Output Compensation Current
#define CURRENT_OFF 0x00000000
#define CURRENT_ON 0x00004000
//Burn-Out Current
#define BURN_OUT_OFF 0x00000000
#define BURN_OUT_ON 0x00002000
//Bipolar/Unipolar Selection
#define BIPOLAR 0x00000000
#define UNIPOLAR 0x00001000
//Filter selection, default = 9.76Hz
#define FS_CODE 0x000007D0
// запись в регистры
void write_ad7710(unsigned long data)
{
int i;
byte calibration_needed = FALSE;
unsigned long t;
//определим необходимость выполнения калибровки
if(data & SELF_CALIBRATION || data & SYSTEM_CALIBRATION_1 || data & SYSTEM_CALIBRATION_2 || data & OFFSET_CALIBRATION)
calibration_needed = TRUE;
pinMode(SDATA,OUTPUT);
digitalWrite(SCLK,LOW);
digitalWrite(AO,LOW);
digitalWrite(TFS,LOW);
//запишем 24 бита данных
for(i=23;i>=0;i--)
{
digitalWrite(SCLK,LOW);
t=data & (1L<<i);
digitalWrite(SDATA, (t)?HIGH:LOW);
digitalWrite(SCLK,HIGH);
}
digitalWrite(SCLK,LOW);
digitalWrite(TFS,HIGH);
//подождем окончания процесса калибровки
if(calibration_needed) {
while(digitalRead(DRDY));
digitalWrite(SYNC,LOW);
digitalWrite(SYNC,HIGH);
}
}
// чтение из регистров
unsigned long read_ad7710(byte output_register)
{
long data = 0x00;
int i;
pinMode(SDATA, INPUT);
digitalWrite(RFS, HIGH);
digitalWrite(TFS, HIGH);
digitalWrite(AO, output_register);
if(output_register)
while(digitalRead(DRDY)==HIGH);
digitalWrite(RFS, LOW);
for(i=23;i>=0;i--)
{
if(digitalRead(SDATA))data|=(1L<<i);
digitalWrite(SCLK,HIGH);
digitalWrite(SCLK,LOW);
}
digitalWrite(RFS, HIGH);
return data;
}
// запись настроек
void setup_ad7710(unsigned long settings)
{
Serial.print("Write settings:");
Serial.println(settings, HEX);
write_ad7710(settings);
}
// Проверка работоспособности микросхемы.
// Проверяется начальное значение CONTROL_REGISTER, по умолчанию равно 0x146.
// Но, я для проверки использую предварительно записанное значение в CONTROL_REGISTER.
// Причем необходимо учитывать, что при выполнении процедуры калибровки биты разрешения
// калибровки сбросятся автоматически
byte check_ad7710(unsigned long v)
{
unsigned long value = 0x00;
value = read_ad7710(FALSE);
Serial.print("Check: ");Serial.print (value,HEX);Serial.print ("/"); Serial.println (v,HEX);
if(value == v)
return TRUE;
return FALSE;
}
// инициализация
void init_ad7710()
{
pinMode(TFS,OUTPUT);
pinMode(RFS,OUTPUT);
pinMode(AO,OUTPUT);
// pinMode(DRDY,INPUT);
pinMode(SCLK,OUTPUT);
pinMode(SYNC,OUTPUT);
digitalWrite(TFS,HIGH);
digitalWrite(RFS,HIGH);
digitalWrite(AO,HIGH);
digitalWrite(SCLK,LOW);
digitalWrite(SYNC,HIGH);
}
#define FCLK 10000000
// Определение значения фильтра
#define FS(f) ((FCLK/512) / f)
// Для 1273ПВ8Р не используется, т.к. не все значения работают.
// Для этой микросхемы выбираем значение фильтра из таблицы:
/*
FS Fnotch
20 976,56
23 849,18
40 488,28
47 415,56
80 244,14
88 221,95
95 205,59
160 122,07
176 110,97
191 102,26
320 61,04
352 55,49
383 51
640 30,52
704 27,74
767 25,46
1280 15,26
1408 13,87
1535 12,72
*/
// Значение фильтра
unsigned long fs_code = 320;
// Настройки АЦП
unsigned long settings = GAIN_8|CHANNEL_2|WORD_24|BIPOLAR|fs_code;
// Коэффициент усиления
int Ku = 8;
// Опорное напряжение
int Vref = 2.45097;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
init_ad7710();
setup_ad7710(SELF_CALIBRATION|settings);
if(check_ad7710(settings))
{
Serial.println("AD7710 check OK!");
}
else
{
Serial.println("Error trying to access the AD7710\r\n");
while(!check_ad7710(settings))delay(500);
}
// setup_ad7710(BACKGROUND_CALIBRATION|settings);
}
void loop() {
// put your main code here, to run repeatedly:
long data = 0x00;
// Чтение данных из DATA_REGISTER и расчет напряжения
data = read_ad7710(TRUE);
while(TRUE)
{
Serial.print("Data = ");Serial.print(data);Serial.print(" (");
if(settings & UNIPOLAR)
Serial.print(data/Ku*Vref/Ku*0xffffff,4);
else
Serial.print((data - 0x7fffff)/ Ku * ( 2*Vref/0xffffff),4);
Serial.println("V)");
data = (data*3 + read_ad7710(TRUE))/4;
}
}