MAX22000為可配置模擬IO器件。它支持1通道通用電壓/電流輸入輸出(IO)以及RTD或熱電偶輸入作為行業(yè)標準4端子接口?;蛘?,它可用于創(chuàng)建雙通道差分模擬輸入或六通道單端模擬輸入。微控制器兼容型串行外設接口(SPI)提供對許多高級功能的訪問。本應用筆記提供了C代碼實現(xiàn)示例,包括設置、監(jiān)控和診斷功能。
介紹
MAX22000集成了24位ADC、18位DAC和模擬前端(AFE),可創(chuàng)建軟件可配置IO,支持所有標準工業(yè)模擬接口:-10V至+10V模擬輸入或輸出、-20mA至+20mA模擬輸入或輸出,以及用于溫度測量的RTD或熱電偶輸入。當用作模擬輸入 (AI) 時,該器件支持具有兩個單端輸入的差分輸入通道或多達六個單端輸入通道。此外,一個差分輸入通道(AI5和AI6)具有集成的低噪聲可編程增益放大器(PGA),專為熱電偶或RTD測量而設計。
如果使用模擬輸出(AO),則在電流輸出模式下需要一個差分模擬輸入對,或者在電壓輸出模式下需要一個單端模擬輸入通道。
本應用筆記介紹了一系列功能,為MAX22000編程提供更快、經(jīng)過驗證的解決方案(圖1)。它們是用C語言編寫的,應該很容易移植到任何常見的微控制器上。有關MAX22000引腳、工作模式和控制寄存器的詳細信息,請參考MAX22000數(shù)據(jù)資料。

圖1.MAX22000功能框圖
MAX22000 SPI
MAX22000 SPI命令為32位長(8位指令+24位數(shù)據(jù)),CRC禁用,如果使能CRC,則CRC8將增加8位;有關CRC計算的詳細信息,請參見應用筆記7072:MAX22000可配置模擬IO的CRC編程指南,其中更詳細地顯示了CRC8編碼。SPI 命令結構如表 1所示。MAX22000的SPI模式為CPOL = 0 (CLK空閑= 0),CPHA = 0 (上升沿/第一沿對數(shù)據(jù)進行采樣),數(shù)據(jù)/命令需要先以MSB時鐘。
表 1.MAX22000 SPI命令結構
| 地址 | 控制 | 數(shù)據(jù) |
|---|---|---|
| 7 位 A[6:0],MSB 至 LSB | R/W 位,讀取 = 1,寫入 = 0 | 24 位 D[23:0],MSB 至 LSB |
有關SPI讀寫周期的詳細信息,以及寄存器表和指令,請參見MAX22000數(shù)據(jù)資料。
圖1所示為MAX22000的主要功能塊。從本質(zhì)上講,該設備有四個主要部分:
帶有內(nèi)部基準電壓源的Σ-Δ型ADC – 主要功能是轉換可使用SPI讀取的模擬數(shù)據(jù)。
帶內(nèi)部基準電壓源的DAC – 主要功能是將數(shù)字數(shù)據(jù)轉換為模擬電壓。
帶多路復用器的AFE – 主要功能是選擇通道和開關模式(即電流/電壓)。
邏輯端接口 – SPI 端口,用于訪問所有器件寄存器和硬件標志以進行診斷。
MAX22000—應用示例 可配置的多量程模擬輸入/輸出
MAX22000設計用于支持終端設備的工業(yè)應用,如需要可配置模擬I/O的可編程邏輯控制器(PLC)。典型應用電路如圖2所示。

圖2.可配置模擬 IO + 3 個單端模擬電壓輸入。
標有“通用模擬 I/O”的終端是軟件可配置且完全靈活的模擬 IO 端口,與標有“Return”的終端一起提供:
電流輸入±20mA (標稱)滿量程范圍為±25mA。
電流輸出±20mA (標稱)滿量程范圍為±25mA。
電壓輸入±10V(標稱),滿量程范圍為±12.5V。
電壓輸出±10V(標稱),滿量程范圍為±12.5V。
為了簡化需要電流隔離的系統(tǒng),MAX22000支持6個邏輯電平GPIO(GPIO[5:0]),可用于需要切換外部元件(MUX/FET/電源)或需要通過隔離柵回讀數(shù)字信號的情況。
源代碼
本應用筆記提供了C源代碼示例,主要提供驅(qū)動器功能,用于訪問MAX22000中的多個寄存器,以實現(xiàn)配置、控制和診斷功能。所有軟件均使用MAX22000評估板進行實現(xiàn)和測試。
全局允許輕松選擇通道/模式:
public enum Register_address
{
GEN_PROD = 0x00,
GEN_REV = 0x01,
GEN_CNFG = 0x02,
GEN_CHNL_CTRL = 0x03,
GEN_GPIO_CTRL = 0x04,
GEN_GPI_INT = 0x05,
GEN_GPI_DATA = 0x06,
GEN_INT = 0x07,
GEN_INTEN = 0x08,
GEN_PWR_CTRL = 0x09,
GEN_TST_MODE_1 = 0x1a,
GEN_TST_ENTRY = 0x1c,
GEN_TST69 = 0x1d,
DCHNL_CMD = 0x20,
DCHNL_STA = 0x21,
DCHNL_CTRL1 = 0x22,
DCHNL_CTRL2 = 0x23,
DCHNL_DATA = 0x24,
DCHNL_N_SEL = 0x25,
DCHNL_N_SOC = 0x26,
DCHNL_N_SGC = 0x27,
AO_DATA_WR = 0x40,
AO_OFFSET_CORR_WR = 0x41,
AO_GAIN_CORR_WR = 0x42,
AO_CNFG_WR = 0x43,
AO_DATA_RD = 0x44,
AO_OFFSET_CORR_RD = 0x45,
AO_GAIN_CORR_RD = 0x46,
AO_STA_RD = 0x47,
};
// DAC is 18bit, full-range = 262144; Half because bipolar: 131072, Theoretical factor = V(range) / half-range
public const double phy_AO_25V_factor = (double) 25 / (double) 262144; //0.00009536743164;
public const double phy_AO_25V_offset = -131072;
public const double phy_AO_12V_factor = (double) 25 / (double) 262144; //0.00009536743164;
public const double phy_AO_12V_offset = 0;
// DAC is 18bit, full-range = 262144; Theoretical factor = mA(range) / half-range (bipolar)
public const double phy_AO_25mA_factor = (double) 50 / (double) 262144; // 0.0001907348633;
public const double phy_AO_25mA_offset = 0;
public const double phy_AO_2mA_factor = (double) 5 / (double) 262144; // 0.00001907348633;
public const double phy_AO_2mA_offset = 0;
public enum Channel_select
{
AI1_SE_b12V = 0x00,
AI2_SE_b12V = 0x01,
AI1_2_diff_b1V = 0x02,
AI3_SE_b12V = 0x03,
AI4_SE_b12V = 0x04,
AI3_4_diff_b25V = 0x05,
AI5_SE_b12V = 0x06,
AI6_SE_b12V = 0x07,
AI5_6_diff_b25V = 0x08,
AI5_SE_b0p125V = 0x09,
AI5_SE_b0p250V = 0x0a,
AI5_SE_b0p500V = 0x0b,
AI5_SE_b2p500V = 0x0c,
AI6_SE_b0p125V = 0x0d,
AI6_SE_b0p250V = 0x0e,
AI6_SE_b0p500V = 0x0f,
AI6_SE_b2p500V = 0x10,
AI5_6_diff_b0p125V = 0x11,
AI5_6_diff_b0p250V = 0x12,
AI5_6_diff_b0p500V = 0x13,
AI5_6_diff_b2p500V = 0x14,
AUX1_SE_u2V = 0x15,
AUX2_SE_u2V = 0x16,
AUX1_2_diff_b2V = 0x17,
};
public enum AOut_Mode
{
high_impedance = 0,
AO_25V = 1,
AO_12V = 2,
AO_6V = 3,
AO_1V = 4,
AO_0p6V = 5,
AO_25mA = 6,
AO_12mA = 7,
AO_2mA = 8,
AO_1mA = 9,
out_of_range1 = 10
}
public enum MAX22000_CIO_Mode
{
Current_Input,
Voltage_Input,
Current_Output,
Voltage_Output,
RTD_Input,
PGA_Input,
PGA_Input_with_Current_sourcing,
Off
};
//********************************************************************
//*
//* Function: MAX22000_read_register
//* Description: Read one Register from MAX22000
//*
//* Input: Register-Address (take from definitions in header-file)
//* Output: 24bit register content
//*
//* if CRC is enabled, then crc8-Command is required
//*
//********************************************************************/
public UInt32 MAX22000EVKIT_read_register(Register_address address)
{
UInt32 result = 0;
UInt32 CRC_read = 0;
if (CRC_Enabled == false)
{
max22000_port.SPI_CS0Enable();
max22000_port.SPI_W_transaction_8( (address << 1) + 0x01 );
result = max22000_port.SPI_R_transaction_24();
max22000_port.SPI_CS0Disable();
}
else
{
max22000_port.SPI_CS0Enable();
max22000_port.SPI_W_transaction_8( (address << 1) + 0x01 );
result = max22000_port.SPI_R_transaction_24();
CRC_read = max22000_port.SPI_R_transaction_8(); // read the CRC
max22000_port.SPI_CS0Disable();
// calculate and check...
byte CRC_TX1 = (address << 1) + 0x01; // TX byte (was sent)
byte CRC_RX1 = (result >>16) & 0xff; // 1st RX byte
byte CRC_RX2 = (result >>8 ) & 0xff; // 2nd RX byte
byte CRC_RX3 = (result ) & 0xff; // 3rd RX byte
byte CRC_Calc = crc8(CRC_TX1, CRC_RX1, CRC_RX2, CRC_RX3);
if (CRC_Calc != CRC_read) printf("CRC read from MAX22000 is incorrect.");
}
return result;
}
//********************************************************************
//*
//* Function: MAX22000_write_register
//* Description: Write one Register to MAX22000
//*
//* Input: Register-Address (take from definitions in header-file)
//* 24bit data (new register content)
//*
//********************************************************************/
public UInt32 MAX22000EVKIT_write_register(Register_address address, UInt32 data)
{
if (CRC_Enabled == false)
{
max22000_port.SPI_CS0Enable();
max22000_port.SPI_W_transaction_8( (ushort) ( ((byte)address << 1) ) );
max22000_port.SPI_W_transaction_24(data);
max22000_port.SPI_CS0Disable();
}
else
{
byte CRC_TX1 = (address << 1);
byte CRC_TX2 = ((data> >16) & 0xff);
byte CRC_TX3 = ((data >>8 ) & 0xff);
byte CRC_TX4 = ( data & 0xff);
byte CRC_Calc = crc8(CRC_TX1, CRC_TX2, CRC_TX3, CRC_TX4);
max22000_port.SPI_CS0Enable();
max22000_port.SPI_W_transaction_8( address << 1 );
max22000_port.SPI_W_transaction_24(data);
max22000_port.SPI_W_transaction_8( CRC_Calc );
max22000_port.SPI_CS0Disable();
}
}
// ********************************************************************
//
// Function: MAX22000_CIO_Setup
// Description: Sets up MAX22000 for one of the CIO Modes
// Assuming HW is connected like the standard application diagram
//
// Input: Desired Mode
// Output: None (MAX22000 will be setup by this routine)
//
// ********************************************************************
uint32_t MAX22000_CIO_Setup (MAX22000_CIO_Mode mode)
{
uint32_t ADC_result = 0;
switch (mode)
{
case MAX22000_CIO_Mode.Current_Input:
// set calibration factors for Current Input
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x100000); // Stop any potentially running conversions
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000000); // No channel selected
MAX22000_write_register(MAX22000_DCHNL_N_SEL, 0x000003); // Select CH AI1-2 diff calibration factor
MAX22000_write_register(MAX22000_DCHNL_N_SOC, 0xFFFFE1); // Write Offset (regular low-side)
MAX22000_write_register(MAX22000_DCHNL_N_SGC, 0xBD934B); // Write Gain (regular low-side)
// END restore calibration
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x008000; // AI1-2 diff (CSA-Mode)
new_GEN_CNFG = (new_GEN_CNFG & 0xf0ffff) + 0x020000; // AO voltage output mode +/- 12.5V range
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
MAX22000_write_register(MAX22000_AO_DATA_WR, 0x000000); // Write AO Voltage to 0V so current can flow
// Prepare ADC
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000300); // AI1-2 diff channel selected
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000300); // select AI1-2 diff mode
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps) (0x340000 = 50sps)
ADC_result = MAX22000EVKIT_read_register(MAX22000_DCHNL_DATA);// read Data
break;
case MAX22000_CIO_Mode.Current_Output:
// Set DAC calibration
MAX22000_write_register(MAX22000_AO_OFFSET_CORR_WR, 0x00F5C0);
MAX22000_write_register(MAX22000_AO_GAIN_CORR_WR, 0xFA3E80);
// END restore calibration
// Set AO Mode (Register 0x02: GEN_CNFG)
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x008000; // AI1-2 diff (CSA-Mode)
new_GEN_CNFG = (new_GEN_CNFG & 0xf0ffff) + 0x060000; // AO current output mode +/- 25mA range
new_GEN_CNFG = (new_GEN_CNFG & 0xeFffff) + 0x000000; // Set 4-wire Mode
new_GEN_CNFG = (new_GEN_CNFG & 0xffefff) + 0x001000; // enable AI3 SE
new_GEN_CNFG = (new_GEN_CNFG & 0xbfffff) + 0x000000; // Internal Reference
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
MAX22000_write_register(MAX22000_GEN_PWR_CTRL, 0x000000); // Normal operation (especially make sure GEN_PD=0
// Set Hex value / physical Value
MAX22000_write_register(MAX22000_AO_DATA_WR, 0);//new_AO_value<<6); // Write new DAC value
break;
case MAX22000_CIO_Mode.Voltage_Input:
// restore calibration
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x100000); // Stop any potentially running conversions
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000000); // No channel selected
MAX22000_write_register(MAX22000_DCHNL_N_SEL, 0x000003); // Select CH AI3 SE calibration factor
MAX22000_write_register(MAX22000_DCHNL_N_SOC, 0xFFFFE1); // Write Offset
MAX22000_write_register(MAX22000_DCHNL_N_SGC, 0xBD934B); // Write Gain
// END restore calibration
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xffefff) + 0x001000; // AI3 SE enabled
new_GEN_CNFG = (new_GEN_CNFG & 0xf0ffff) + 0x000000; // AO High-Impedance mode
new_GEN_CNFG = (new_GEN_CNFG & 0xeFffff) + 0x000000; // Set 4-wire Mode
new_GEN_CNFG = (new_GEN_CNFG & 0xbfffff) + 0x000000; // Internal Reference
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000400); // Select Channel AI3 / Single Ended
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case MAX22000_CIO_Mode.Voltage_Output:
MAX22000_write_register(MAX22000_AO_OFFSET_CORR_WR, 0x00F5C0);
MAX22000_write_register(MAX22000_AO_GAIN_CORR_WR, 0xFA3E80);
// END restore calibration
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xf0ffff) + 0x020000; // 10V is 0b0010 -> 2
new_GEN_CNFG = (new_GEN_CNFG & 0xeFffff) + 0x000000; // Set 4-wire Mode
new_GEN_CNFG = (new_GEN_CNFG & 0xbfffff) + 0x000000; // Internal Reference
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Set Hex value / physical Value
MAX22000_write_register(MAX22000_AO_DATA_WR, 0);//new_AO_value<<6); // Write new DAC value
break;
case MAX22000_CIO_Mode.Off:
// Make AO high-impedance, Stop ADC, Disable all Amplifiers
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x100000); // Stop any potentially running conversions
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000000); // No channel selected
MAX22000_write_register(MAX22000_GEN_CNFG, 0x000000); // Write new_GEN_CNFG_value
break;
case default:
// Make AO high-impedance, Stop ADC, Disable all Amplifiers
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x100000); // Stop any potentially running conversions
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000000); // No channel selected
MAX22000_write_register(MAX22000_GEN_CNFG, 0x000000); // Write new_GEN_CNFG_value
break;
}
}
// ********************************************************************
//
// Function: MAX22000_ADC_Setup
// Description: Sets up MAX22000 for to read one of the ADC Channels in selected Mode
// Assuming all ADCs (at least the selected one) is open / connected to a voltage source
//
// Input: Desired ADC-Channel +Mode
// Output: None (MAX22000 will be setup by this routine, Conversion will be started)
//
// ********************************************************************
uint32_t MAX22000_ADC_Setup (ADC_CH_Mode CH_and_Mode)
{
switch(CH_and_Mode)
{
case ADC_CH_Mode.AI1_SE:
// Setup Channel 1 for Single Ended and continuous sampling
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x006000; // make AI1 and AI2 SE active
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000100); // Select Channel AI1 / Single Ended
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AI2_SE:
// Setup Channel 2 for Single Ended and continuous sampling
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x006000; // make AI1 and AI2 SE active
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000200); // Select Channel AI1 / Single Ended
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AI3_SE:
// Setup Channel 3 for Single Ended and continuous sampling
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x001800; // make AI3 and AI4 SE active
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000400); // Select Channel AI3 / Single Ended
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AI4_SE:
// Setup Channel 4 for Single Ended and continuous sampling
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x000800; // make AI4 SE active
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000500); // Select Channel AI4 / Single Ended
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AI12_DIFF:
// Setup Channel 1-2 for Differeential and continuous sampling
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x008000; // enable AI1-2 diff (CSA) mode
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000300); // Select Channel AI1-2 / Differential
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AI34_DIFF:
// Setup Channel 3-4 for Differeential and continuous sampling
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x001800; // enable AI3-AI4 diff
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000600); // Select Channel AI3-4 / Differential
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AI56_DIFF:
// Setup Channel 5-6 for Differeential and continuous sampling
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x000400; // enable AI5-6 diff +/- 25V range
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000900);// Select Channel AI5-6 / Differential +/-25V
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AI56_PGA_2p500V:
// Setup Channel 5-6 for Differeential and continuous sampling (PGA Path +/-2.5V range)
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x000400; // enable AI5-6 diff +/- 2.5V range (in PGA Mode)
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000c00); // Select Channel AI5-6 / Differential PGA Path
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AI56_PGA_0p500V:
// Setup Channel 5-6 for Differeential and continuous sampling (PGA Path +/-0.5V range)
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x000440; // enable AI5-6 diff +/- 0.5V range
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000c00); // Select Channel AI5-6 / Differential PGA Path
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AI56_PGA_0p250V:
// Setup Channel 5-6 for Differeential and continuous sampling (PGA Path +/-0.250V range)
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x000480; // enable AI5-6 diff +/- 0.250V range
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000c00); // Select Channel AI5-6 / Differential PGA Path
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AI56_PGA_0p125V:
// Setup Channel 5-6 for Differeential and continuous sampling (PGA Path +/-0.250V range)
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x0004c0; // enable AI5-6 diff +/- 0.125V range
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000c00); // Select Channel AI5-6 / Differential PGA Path
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AUX1_SE:
// Setup Channel AUX1 for Single Ended and continuous sampling
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000d00); // Select Channel AUX1 / Single Ended
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AUX2_SE:
// Setup Channel AUX2 for Single Ended and continuous sampling
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000e00); // Select Channel AUX2 / Single Ended
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case ADC_CH_Mode.AUX12_DIFF:
// Setup Channel AUX1-2 for Differential and continuous sampling
// Select Internal REFs, set all channels to single-ended leave as is
MAX22000_write_register(MAX22000_DCHNL_CTRL1, 0x010000); // Continuous Single cycle conversions
MAX22000_write_register(MAX22000_DCHNL_CTRL2, 0x000000); // Internal OSC, use coefficients, ...
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000f00); // Select Channel AUX1-2 / Differential
//MAX22000_write_register(MAX22000_DCHNL_CMD, 0x330000); // Start conversion (30sps)
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x310000); // Start conversion (10sps)
break;
case default:
// Make AO high-impedance, Stop ADC, Disable all Amplifiers
MAX22000_write_register(MAX22000_DCHNL_CMD, 0x100000); // Stop any potentially running conversions
MAX22000_write_register(MAX22000_GEN_CHNL_CTRL, 0x000000); // No channel selected
MAX22000_write_register(MAX22000_GEN_CNFG, 0x000000); // Write new_GEN_CNFG_value
break;
}
}
// ********************************************************************
//
// Function: MAX22000_ADC_Read
// Description: Reads the currently selected and running ADC Channel
// as setup per MAX22000_ADC_Setup
//
// Input: None
// Output: Current ADC Reading in LSB (24bit wide)
//
// ********************************************************************
uint32_t MAX22000_ADC_Read (void)
{
uint32_t adc_result = 0;
wait_for_RDYB(); // When RDYB pin is low, the ADC finished conversion.
adc_result = MAX22000EVKIT_read_register(MAX22000_DCHNL_DATA);// read Data
return adc_result;
}
// ********************************************************************
//
// Function: MAX22000_DAC_Setup
// Description: Sets up the DAC for the selected Mode
// after this the DAC can be updated with DAC_Set_LSB or DAC_Ser_PHY
//
// Input: DAC range
// Output: None, DAC in MAX22000 will be setup according to setting
//
// ********************************************************************
void MAX22000_DAC_Setup (DAC_Range range)
{
switch (range)
{
case DAC_Range.AO_25V:
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xf0ffff) + 0x010000; // AO_CNFG = 0001: AO Current Mode, 25V setting
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Restore Calibration
MAX22000_write_register(MAX22000_AO_OFFSET_CORR_WR, 0x00F5C0);
MAX22000_write_register(MAX22000_AO_GAIN_CORR_WR, 0xFA3E80);
break;
case DAC_Range.AO_12V:
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xf0ffff) + 0x020000; // AO_CNFG = 0010: AO Current Mode, 12.5V setting
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Restore Calibration
MAX22000_write_register(MAX22000_AO_OFFSET_CORR_WR, 0x00F5C0);
MAX22000_write_register(MAX22000_AO_GAIN_CORR_WR, 0xFA3E80);
break;
case DAC_Range.AO_25mA:
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xf0ffff) + 0x060000; // AO_CNFG = 0110: AO Current Mode, 25mA setting
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x008000; // AI1-2 diff (CSA-Mode)
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Restore Calibration
MAX22000_write_register(MAX22000_AO_OFFSET_CORR_WR, 0x00F5C0);
MAX22000_write_register(MAX22000_AO_GAIN_CORR_WR, 0xFA3E80);
break;
case DAC_Range.AO_2mA:
uint32_t new_GEN_CNFG = 0;
new_GEN_CNFG = (new_GEN_CNFG & 0xf0ffff) + 0x080000; // AO_CNFG = 1000: AO Current Mode, 2.5mA setting
new_GEN_CNFG = (new_GEN_CNFG & 0xff1fff) + 0x008000; // AI1-2 diff (CSA-Mode)
MAX22000_write_register(MAX22000_GEN_CNFG, new_GEN_CNFG); // Write new_GEN_CNFG_value
// Restore Calibration
MAX22000_write_register(MAX22000_AO_OFFSET_CORR_WR, 0x00F5C0);
MAX22000_write_register(MAX22000_AO_GAIN_CORR_WR, 0xFA3E80);
break;
default:
// In case invalid range select, do nothing
break;
}
}
// ********************************************************************
//
// Function: MAX22000_DAC_Set_LSB
// Description: Writes a new LSB value to the DAC,
// assuming it is already setup in a specific mode, use DAC_Setup first
// If LDAC-pin is high, it must be toggled after setting up update the output
//
// Input: new DAC value in LSB
// Output: None
//
// ********************************************************************
void MAX22000_DAC_Set_LSB (uint32_t data)
{
// DAC must be setup before using this function
// Below will simply write the new Value to the DAC
MAX22000_write_register(MAX22000_AO_DATA_WR, data);
}
// ********************************************************************
//
// Function: MAX22000_DAC_Set_PHY
// Description: Writes a new PHY value (Volt or mA) to the DAC,
// assuming it is already setup in a specific mode, use DAC_Setup first
// If LDAC-pin is high, it must be toggled after setting up update the output
//
// Input: new DAC value in physical value (either Volt or Miliampere, NOT AMPERE)
// Output: None
//
// ********************************************************************
void MAX22000_DAC_Set_PHY (float volt_V_or_current_mA, DAC_Range range)
{
// DAC must be setup before using this function
// Calculate new LSB Value
uint32_t DAC_LSB_value = 0;
switch (range)
{
case DAC_Range.AO_25V:
if (volt_V_or_current_mA < 25)
{ DAC_LSB_value = 0x1ffff + ((volt_V_or_current_mA / (phy_AO_25V_factor))) + phy_AO_25V_offset + 1; }
else
{ DAC_LSB_value = -0x1ffff + ((volt_V_or_current_mA / (phy_AO_25V_factor)) + phy_AO_25V_offset - 0); }
break;
case DAC_Range.AO_12V:
if (volt_V_or_current_mA < 0)
{ DAC_LSB_value = 0x3ffff - ((-volt_V_or_current_mA / (phy_AO_12V_factor))) + phy_AO_12V_offset + 1; }
else
{ DAC_LSB_value = ((volt_V_or_current_mA / (phy_AO_12V_factor)) + phy_AO_12V_offset - 0); }
break;
case DAC_Range.AO_25mA:
if (volt_V_or_current_mA < 0)
{ DAC_LSB_value = 0x3ffff - ((-volt_V_or_current_mA / (phy_AO_25mA_factor))) + phy_AO_25mA_offset + 1; }
else
{ DAC_LSB_value = ((volt_V_or_current_mA / (phy_AO_25mA_factor)) + phy_AO_25mA_offset - 0); }
break;
case DAC_Range.AO_2mA:
if (volt_V_or_current_mA < 0)
{ DAC_LSB_value = 0x3ffff - ((-volt_V_or_current_mA / (phy_AO_2mA_factor))) + phy_AO_2mA_offset + 1; }
else
{ DAC_LSB_value = ((volt_V_or_current_mA / (phy_AO_2mA_factor)) + phy_AO_2mA_offset - 0); }
break;
default:
DAC_LSB_value = 0; // default means non-existend range selected
break;
}
// ********************************************************************
//
// Function: MAX22000_GPIO_Setup
// Description: Sets up all 6 GPIO Pins, bit0=GPIO0, bit1=GPIO1, ...
// Since the command includes everything Enable/Disable as well as
// GPIO Direction, this function is faster than GPO_Set
// because it doesn't have to read back the setup from the part
//
// Input: GPIO_enable (byte) Bit0 = GPIO0, Bit1 = GPIO1, ... (0 = Off, 1 = On)
// GPIO_direction (byte) Bit0 = GPIO0, Bit1 = GPIO1, ... (0 = Input, 1 = Output)
// GPO_Setting (byte) Bit0 = GPIO0, Bit1 = GPIO1, ... (0 = Low, 1 = High)
// Output: None
//
// ********************************************************************
void MAX22000_GPIO_Setup (uint8_t GPIO_enable, uint8_t GPIO_direction, uint8_t GPO_Setting)
{
uint32_t new_gpio_value = ((GPIO_enable & 0x3f)<<16) + ((GPIO_direction & 0x3f)<<8) + (GPO_Setting & 0x3f);
MAX22000_write_register(MAX22000_GEN_GPIO_CTRL, new_gpio_value); // Write new_GEN_CNFG_value
}
// ********************************************************************
//
// Function: MAX22000_GPO_Set
// Description: Sets GPOs high or low, bit0=GPIO0, bit1=GPIO1, ...
// GPOs must be setup and enabled prior this use MAX22000_GPIO_Setup
//
// Input: GPO Setting, bit0=GPIO0, bit1=GPIO1, ... (0 = Low, 1 = High)
// Output: None
//
// ********************************************************************
void MAX22000_GPO_Set (uint8_t GPO_Setting)
{
uint32_t gpio_setup = MAX22000EVKIT_read_register(MAX22000_GEN_GPIO_CTRL); // read Setup
gpio_setup = gpio_setup & 0xffff00; // Mask out previous GPO settings
MAX22000_write_register(MAX22000_GEN_GPIO_CTRL, gpio_setup); // Write new_GEN_CNFG_value
}
// ********************************************************************
//
// Function: MAX22000_GPI_Get
// Description: Gets all GPI readings high or low, bit0=GPIO0, bit1=GPIO1, ...
// GPIs must be setup and enabled prior this use MAX22000_GPIO_Setup
//
// Input: None
// Output: GPI Setting, bit0=GPIO0, bit1=GPIO1, ... (0 = Low, 1 = High)
//
// ********************************************************************
uint8_t MAX22000_GPI_Get (void)
{
uint32_t gpi_result = MAX22000EVKIT_read_register(MAX22000_GEN_GPI_DATA); // read GPI Data
return gpi_result & 0x3f;
}
public byte crc8(byte BYTE1, byte BYTE2, byte BYTE3, byte BYTE4)
{
byte crc8_start = 0x00;
byte crc8_poly = 0x8c; // rotated 0x31, which is our polinomial
byte crc_result = crc8_start;
// BYTE1
for (int i=0; i<8; i++)
{
if( ( (( BYTE1>>i ) ^ (crc_result) ) & 0x01 ) > 0 )
{ crc_result = (byte) (crc8_poly ^ crc_result>>1 ); }
else
{ crc_result = (byte) (crc_result>>1); }
}
// BYTE2
for (int i=0; i<8; i++)
{
if( ( (( BYTE2>>i ) ^ (crc_result) ) & 0x01 ) > 0 )
{ crc_result = (byte) (crc8_poly ^ crc_result>>1 ); }
else
{ crc_result = (byte) (crc_result>>1); }
}
// BYTE3
for (int i=0; i<8; i++)
{
if( ( (( BYTE3>>i ) ^ (crc_result) ) & 0x01 ) > 0 )
{ crc_result = (byte) (crc8_poly ^ crc_result>>1 ); }
else
{ crc_result = (byte) (crc_result>>1); }
}
// BYTE4
for (int i=0; i<8; i++)
{
if( ( (( BYTE4>>i ) ^ (crc_result) ) & 0x01 ) > 0 )
{ crc_result = (byte) (crc8_poly ^ crc_result>>1 ); }
else
{ crc_result = (byte) (crc_result>>1); }
}
crc8_2_for_testing(BYTE1, BYTE2, BYTE3, BYTE4);
return crc_result;
}
審核編輯:郭婷
-
微控制器
+關注
關注
48文章
8198瀏覽量
160550 -
熱電偶
+關注
關注
5文章
985瀏覽量
79232 -
dac
+關注
關注
44文章
2475瀏覽量
195985
發(fā)布評論請先 登錄
Dialog最新可配置IC擴展電機驅(qū)動應用
Maxim Integrated發(fā)布最新IO-Link通信方案,大幅降低工廠停工時間
閃存可配置的排序器監(jiān)測器MAX16068資料推薦
MAX16046A/MAX16048A EEPROM可配置系
集成式數(shù)字IO和模擬IO產(chǎn)品系列介紹
以STM32為核心的光電隔離可配置多IO板
使用MAX22000進行溫度測量的準則
MAX22000-軟件可配置通用模擬量I/O
使用MAX22000進行溫度測量的準則
軟件可配置模擬 I/O 的設計理念
MAX22005 12通道工廠校準可配置工業(yè)模擬輸入技術手冊
MAX22000工業(yè)可配置模擬I/O技術手冊
Analog Devices / Maxim Integrated MAXREFDES177 IO-Link通用模擬IO特性/框圖

如何對MAX22000可配置模擬IO進行編程
評論