MAX22000為可配置模擬IO器件。它支持1通道通用電壓/電流輸入輸出(IO)以及RTD或熱電偶輸入作為行業標準4端子接口。或者,它可用于創建雙通道差分模擬輸入或六通道單端模擬輸入。微控制器兼容型串行外設接口(SPI)提供對許多高級功能的訪問。本應用筆記提供了C代碼實現示例,包括設置、監控和診斷功能。
介紹
MAX22000集成了24位ADC、18位DAC和模擬前端(AFE),可創建軟件可配置IO,支持所有標準工業模擬接口:-10V至+10V模擬輸入或輸出、-20mA至+20mA模擬輸入或輸出,以及用于溫度測量的RTD或熱電偶輸入。當用作模擬輸入 (AI) 時,該器件支持具有兩個單端輸入的差分輸入通道或多達六個單端輸入通道。此外,一個差分輸入通道(AI5和AI6)具有集成的低噪聲可編程增益放大器(PGA),專為熱電偶或RTD測量而設計。
如果使用模擬輸出(AO),則在電流輸出模式下需要一個差分模擬輸入對,或者在電壓輸出模式下需要一個單端模擬輸入通道。
本應用筆記介紹了一系列功能,為MAX22000編程提供更快、經過驗證的解決方案(圖1)。它們是用C語言編寫的,應該很容易移植到任何常見的微控制器上。有關MAX22000引腳、工作模式和控制寄存器的詳細信息,請參考MAX22000數據資料。
圖1.MAX22000功能框圖
MAX22000 SPI
MAX22000 SPI命令為32位長(8位指令+24位數據),CRC禁用,如果使能CRC,則CRC8將增加8位;有關CRC計算的詳細信息,請參見應用筆記7072:MAX22000可配置模擬IO的CRC編程指南,其中更詳細地顯示了CRC8編碼。SPI 命令結構如表 1所示。MAX22000的SPI模式為CPOL = 0 (CLK空閑= 0),CPHA = 0 (上升沿/第一沿對數據進行采樣),數據/命令需要先以MSB時鐘。
表 1.MAX22000 SPI命令結構
地址 | 控制 | 數據 |
---|---|---|
7 位 A[6:0],MSB 至 LSB | R/W 位,讀取 = 1,寫入 = 0 | 24 位 D[23:0],MSB 至 LSB |
有關SPI讀寫周期的詳細信息,以及寄存器表和指令,請參見MAX22000數據資料。
圖1所示為MAX22000的主要功能塊。從本質上講,該設備有四個主要部分:
帶有內部基準電壓源的Σ-Δ型ADC – 主要功能是轉換可使用SPI讀取的模擬數據。
帶內部基準電壓源的DAC – 主要功能是將數字數據轉換為模擬電壓。
帶多路復用器的AFE – 主要功能是選擇通道和開關模式(即電流/電壓)。
邏輯端接口 – SPI 端口,用于訪問所有器件寄存器和硬件標志以進行診斷。
MAX22000—應用示例 可配置的多量程模擬輸入/輸出
MAX22000設計用于支持終端設備的工業應用,如需要可配置模擬I/O的可編程邏輯控制器(PLC)。典型應用電路如圖2所示。
圖2.可配置模擬 IO + 3 個單端模擬電壓輸入。
標有“通用模擬 I/O”的終端是軟件可配置且完全靈活的模擬 IO 端口,與標有“Return”的終端一起提供:
電流輸入±20mA (標稱)滿量程范圍為±25mA。
電流輸出±20mA (標稱)滿量程范圍為±25mA。
電壓輸入±10V(標稱),滿量程范圍為±12.5V。
電壓輸出±10V(標稱),滿量程范圍為±12.5V。
為了簡化需要電流隔離的系統,MAX22000支持6個邏輯電平GPIO(GPIO[5:0]),可用于需要切換外部元件(MUX/FET/電源)或需要通過隔離柵回讀數字信號的情況。
源代碼
本應用筆記提供了C源代碼示例,主要提供驅動器功能,用于訪問MAX22000中的多個寄存器,以實現配置、控制和診斷功能。所有軟件均使用MAX22000評估板進行實現和測試。
全局允許輕松選擇通道/模式:
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文章
7496瀏覽量
151083 -
熱電偶
+關注
關注
5文章
928瀏覽量
75501 -
dac
+關注
關注
43文章
2272瀏覽量
190852
發布評論請先 登錄
相關推薦
評論