MAX22000為可配置模擬IO器件。它支持1通道通用電壓/電流輸入輸出(IO)以及RTD或熱電偶輸入作為行業(yè)標(biāo)準(zhǔn)4端子接口?;蛘?,它可用于創(chuàng)建雙通道差分模擬輸入或六通道單端模擬輸入。微控制器兼容型串行外設(shè)接口(SPI)提供對許多高級功能的訪問。本應(yīng)用筆記提供了C代碼實(shí)現(xiàn)示例,包括設(shè)置、監(jiān)控和診斷功能。
介紹
MAX22000集成了24位ADC、18位DAC和模擬前端(AFE),可創(chuàng)建軟件可配置IO,支持所有標(biāo)準(zhǔn)工業(yè)模擬接口:-10V至+10V模擬輸入或輸出、-20mA至+20mA模擬輸入或輸出,以及用于溫度測量的RTD或熱電偶輸入。當(dāng)用作模擬輸入 (AI) 時(shí),該器件支持具有兩個(gè)單端輸入的差分輸入通道或多達(dá)六個(gè)單端輸入通道。此外,一個(gè)差分輸入通道(AI5和AI6)具有集成的低噪聲可編程增益放大器(PGA),專為熱電偶或RTD測量而設(shè)計(jì)。
如果使用模擬輸出(AO),則在電流輸出模式下需要一個(gè)差分模擬輸入對,或者在電壓輸出模式下需要一個(gè)單端模擬輸入通道。
本應(yīng)用筆記介紹了一系列功能,為MAX22000編程提供更快、經(jīng)過驗(yàn)證的解決方案(圖1)。它們是用C語言編寫的,應(yīng)該很容易移植到任何常見的微控制器上。有關(guān)MAX22000引腳、工作模式和控制寄存器的詳細(xì)信息,請參考MAX22000數(shù)據(jù)資料。
	
圖1.MAX22000功能框圖
MAX22000 SPI
MAX22000 SPI命令為32位長(8位指令+24位數(shù)據(jù)),CRC禁用,如果使能CRC,則CRC8將增加8位;有關(guān)CRC計(jì)算的詳細(xì)信息,請參見應(yīng)用筆記7072:MAX22000可配置模擬IO的CRC編程指南,其中更詳細(xì)地顯示了CRC8編碼。SPI 命令結(jié)構(gòu)如表 1所示。MAX22000的SPI模式為CPOL = 0 (CLK空閑= 0),CPHA = 0 (上升沿/第一沿對數(shù)據(jù)進(jìn)行采樣),數(shù)據(jù)/命令需要先以MSB時(shí)鐘。
	表 1.MAX22000 SPI命令結(jié)構(gòu)
	
| 地址 | 控制 | 數(shù)據(jù) | 
|---|---|---|
| 7 位 A[6:0],MSB 至 LSB | R/W 位,讀取 = 1,寫入 = 0 | 24 位 D[23:0],MSB 至 LSB | 
有關(guān)SPI讀寫周期的詳細(xì)信息,以及寄存器表和指令,請參見MAX22000數(shù)據(jù)資料。
圖1所示為MAX22000的主要功能塊。從本質(zhì)上講,該設(shè)備有四個(gè)主要部分:
帶有內(nèi)部基準(zhǔn)電壓源的Σ-Δ型ADC – 主要功能是轉(zhuǎn)換可使用SPI讀取的模擬數(shù)據(jù)。
帶內(nèi)部基準(zhǔn)電壓源的DAC – 主要功能是將數(shù)字?jǐn)?shù)據(jù)轉(zhuǎn)換為模擬電壓。
帶多路復(fù)用器的AFE – 主要功能是選擇通道和開關(guān)模式(即電流/電壓)。
邏輯端接口 – SPI 端口,用于訪問所有器件寄存器和硬件標(biāo)志以進(jìn)行診斷。
MAX22000—應(yīng)用示例 可配置的多量程模擬輸入/輸出
MAX22000設(shè)計(jì)用于支持終端設(shè)備的工業(yè)應(yīng)用,如需要可配置模擬I/O的可編程邏輯控制器(PLC)。典型應(yīng)用電路如圖2所示。
	
圖2.可配置模擬 IO + 3 個(gè)單端模擬電壓輸入。
標(biāo)有“通用模擬 I/O”的終端是軟件可配置且完全靈活的模擬 IO 端口,與標(biāo)有“Return”的終端一起提供:
電流輸入±20mA (標(biāo)稱)滿量程范圍為±25mA。
電流輸出±20mA (標(biāo)稱)滿量程范圍為±25mA。
電壓輸入±10V(標(biāo)稱),滿量程范圍為±12.5V。
電壓輸出±10V(標(biāo)稱),滿量程范圍為±12.5V。
為了簡化需要電流隔離的系統(tǒng),MAX22000支持6個(gè)邏輯電平GPIO(GPIO[5:0]),可用于需要切換外部元件(MUX/FET/電源)或需要通過隔離柵回讀數(shù)字信號的情況。
源代碼
本應(yīng)用筆記提供了C源代碼示例,主要提供驅(qū)動器功能,用于訪問MAX22000中的多個(gè)寄存器,以實(shí)現(xiàn)配置、控制和診斷功能。所有軟件均使用MAX22000評估板進(jìn)行實(shí)現(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;
        }
	審核編輯:郭婷
	
- 
                                微控制器
                                +關(guān)注
關(guān)注
48文章
8213瀏覽量
160913 - 
                                熱電偶
                                +關(guān)注
關(guān)注
5文章
985瀏覽量
79281 - 
                                dac
                                +關(guān)注
關(guān)注
44文章
2520瀏覽量
196090 
發(fā)布評論請先 登錄
Dialog最新可配置IC擴(kuò)展電機(jī)驅(qū)動應(yīng)用
Maxim Integrated發(fā)布最新IO-Link通信方案,大幅降低工廠停工時(shí)間
閃存可配置的排序器監(jiān)測器MAX16068資料推薦
如何對STM32的IO口進(jìn)行配置
MAX16046A/MAX16048A EEPROM可配置系
    
集成式數(shù)字IO和模擬IO產(chǎn)品系列介紹
以STM32為核心的光電隔離可配置多IO板
    
使用MAX22000進(jìn)行溫度測量的準(zhǔn)則
    
MAX22000-軟件可配置通用模擬量I/O
    
使用MAX22000進(jìn)行溫度測量的準(zhǔn)則
    
軟件可配置模擬 I/O 的設(shè)計(jì)理念
    
MAX22005 12通道工廠校準(zhǔn)可配置工業(yè)模擬輸入技術(shù)手冊
    
MAX22000工業(yè)可配置模擬I/O技術(shù)手冊
    
Analog Devices / Maxim Integrated MAXREFDES177 IO-Link通用模擬IO特性/框圖
    
          
        
        
如何對MAX22000可配置模擬IO進(jìn)行編程
                
 
           
            
            
                
            
評論