如何对MAX22007可配置模拟输出进行编程

max22007为可配置模拟输出器件。它支持4个通道,每个通道可单独编程为0v至+10v电压输出或0ma至+20ma电流输出。
微控制器兼容型串行外设接口(spi)提供对许多高级功能的访问。本应用笔记提供了在微控制器中实现设置、监控和诊断功能的c代码示例。
介绍
max22007集成了4个12位dac(数模转换器),可创建4个通道,输出为软件可配置,支持0v至+10v或0ma至+20ma模拟输出。每个通道还可以检测负载阻抗,并确定负载是电压还是电流输入。
图1.max22007功能框图
本应用笔记阐述了一系列功能,以便对max22007进行更快、更成熟的编程。这些功能是用c语言编写的,很容易移植到任何常见的微控制器。请参考max22007数据资料,了解max22007引脚、工作模式和控制寄存器的详细信息。
max22007 spi
max22007串行外设接口(spi)命令为24位(8位指令+16位数据),crc禁用时为24位,crc启用时为32位。表 1 显示了 spi 命令结构。max22007的spi模式为cpol = 0 (clk空闲 = 0)和cpha = 0 (上升沿/第一沿对数据进行采样)。数据/命令必须首先以最高有效字节 (msb) 计时。
地址 控制 数据
7 位 a[6:0],msb 至最低有效字节 (lsb) r/w 位,读取 = 1,写入 = 0 16 位 d[15:0],msb 至 lsb
max22007数据资料详细介绍了spi读写周期、寄存器表和指令。
图1所示为max22007的主要功能块。有四个通道可以单独编程为电压或电流输出,以及一个带有spi端口的控制逻辑,用于访问所有寄存器和硬件标志以进行诊断。
max22007支持8路逻辑电平gpio(通用输入/输出),以简化需要电流隔离的系统。gpio可以控制外部组件,如多路复用器、fet(场效应晶体管)或使能切换电源,或通过隔离栅回读数字信号。该器件还支持菊花链模式,这也减少了隔离设计所需的io引脚数量。
源代码
本应用笔记提供c源代码示例,提供驱动器功能,用于访问max22007中的多个寄存器,以实现配置、控制和诊断功能。
请注意,配置寄存器 0x03 ld_cnfg[3:0](位 15 至 12)在上电时设置为 0。所有四个输出在ldac引脚上发生高低转换时同时更新。如果通道要求透明并立即更新,请将ld_cnfg位设置为 1。
用于通道/模式选择的全局变量
public enum register_address { // all registers revision_id = 0x00, status_interrupts = 0x01, interrupt_enable = 0x02, configuration = 0x03, control = 0x04, channel_mode = 0x05, soft_reset = 0x06, channel0_data = 0x07, channel1_data = 0x08, channel2_data = 0x09, channel3_data = 0x0a, gpio_control = 0x0b, gpio_data = 0x0c, gpi_edge_ctrl = 0x0d, gpi_edge_status = 0x0e, }; public enum aout_mode { high_impedance = 0, ao_12v = 1, ao_25ma = 2, out_of_range1 = 3, }; //********************************************************************//*//* function: max22007_read_register//* description: read one register from max22007//*//* input: register-address (take from definitions in header-file)//* output: 16bit register content//*//* if crc is enabled, then crc8-command is required//*//********************************************************************/public uint32 max22007evkit_read_register(register_address address){ if (crc_enabled == false) { max22007_port.spi_cs0enable(); max22007_port.spi_w_transaction_8( (ushort) ( ((byte)address << 1) + 0x01 ) ); result = max22007_port.spi_r_transaction_16(); max22007_port.spi_cs0disable(); } else { max22007_port.spi_cs0enable(); max22007_port.spi_w_transaction_8( (ushort) ( ((byte)address << 1) + 0x01 ) ); result = max22007_port.spi_r_transaction_16(); max22007_port.spi_cs0disable(); crc_result = max22007_port.spi_r_transaction_8(); // read the crc byte crc_tx1 = (address 8) & 0xff); byte crc_rx2 = ((result ) & 0xff); byte crc_calc = crc8(crc_tx1, crc_rx1, crc_rx2); if (crc_calc != crc_result) { result = 0xfffffffe; // return a 32 bit value to flag an error } }}//********************************************************************//*//* function: max22007_write_register//* description: write one register to max22007//*//* input: register-address (take from definitions in header-file)//* 16bit data (new register content)//*//********************************************************************/public void max22007evkit_write_register(register_address address, uint16 data){ byte crc_tx1 = (byte)((byte)address << 1); if (crc_enabled == false) { max22007_port.spi_cs0enable(); max22007_port.spi_w_transaction_8( (ushort) ( ((byte)address 8) & 0xff); byte crc_tx3 = (byte)( data & 0xff); byte crc_calc = crc8(crc_tx1, crc_tx2, crc_tx3); max22007_port.spi_cs0enable(); max22007_port.spi_w_transaction_8( (ushort) ( ((byte)address < 12.5) { return 0xfffe; } // return out of range value to highlight there was an error if (voltage 25) { return 0xfffe; } // return out of range value to highlight there was an error if (current_ma < 0) { return 0xfffe; } // return out of range value to highlight there was an error // convert voltage to lsb value result = (current_ma / phy_ao_25ma_factor); new_hex_value = (uint16) result; return new_hex_value;} // ********************************************************************//// function: max22007_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//// ********************************************************************private void max22007_set_dac(byte channel, uint16 lsb_code){ uint16 dac_out_register = (uint16) (lsb_code << 4); // shift bits to match with register switch (channel) { case 0: max22007evkit_write_register (register_address.channel0_data, dac_out_register); // write ao data register ch0 break; case 1: max22007evkit_write_register (register_address.channel1_data, dac_out_register); // write ao data register ch1 break; case 2: max22007evkit_write_register (register_address.channel2_data, dac_out_register); // write ao data register ch2 break; case 3: max22007evkit_write_register (register_address.channel3_data, dac_out_register); // write ao data register ch3 break; }}// ********************************************************************//// function: main// description: the follwoing function would setup:// 1. all outputs to immediately update on write// 2. channel 0 in voltage mode and drive 5v// 3. channel 1 in current mode and drive 10ma//// input: float: current in ma// output: uint16 lsb value for the dac//// ********************************************************************private void setup_main (){ max22007evkit_write_register (register_address.configuration, 0xf000); // set all latch bits max22007_mode_set(0, aout_mode.ao_12v); // setup channel 0 to voltage mode max22007_mode_set(1, aout_mode.ao_25ma); // setup channel 1 to current mode uint16 dac_lsb_value = 0; dac_lsb_value = max22007_convert_voltage_to_lsb ((float) 5.0); // get integer value for 5.0 volt max22007_set_dac(0, dac_lsb_value); // write this 5v value to channel 0 dac_lsb_value = max22007_convert_current_to_lsb ((float)10.0); // get integer value for 10.0 ma max22007_set_dac(1, dac_lsb_value); // write this 10.0ma value to channel 1} // ********************************************************************//// function: max22007_gpio_setup// description: sets up all 8 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 does not 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)//// output: none//// ********************************************************************void max22007_gpio_setup (byte gpio_enable, byte gpio_direction){ uint16 new_gpio_value = (uint16) ( ( (gpio_enable & 0xff) << 8) + ( (gpio_direction & 0xff) ) ); max22007evkit_write_register(register_address.gpio_control, new_gpio_value);}// ********************************************************************//// function: max22007_gpo_set// description: sets gpos high or low, bit0=gpio0, bit1=gpio1, ...// gpos must be setup and enabled prior this use max22007_gpo_set//// input: gpo setting, bit0=gpio0, bit1=gpio1, ... (0 = low, 1 = high)// output: none//// ********************************************************************void max22007_gpo_set (byte gpo_setting){ uint16 gpo_data = (uint16) ((gpo_setting< for write commands send result as the crc code// -> for read commands compare result to check for errors//// ******************************************************************** public byte max22007_crc8(byte byte1, byte byte2, byte byte3){ 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>i ) ^ (crc_result) ) & 0x01 ) > 0 ) // if(xor(c6;bitand(d5;2^4)/2^4) { crc_result = (byte) (crc8_poly ^ crc_result>>1 ); } // bitxor($d$1;bitand((d5*2);31)) else { crc_result = (byte) (crc_result>>1); } } // byte2 for (int i=0; i>i ) ^ (crc_result) ) & 0x01 ) > 0 ) // if(xor(c6;bitand(d5;2^4)/2^4) { crc_result = (byte) (crc8_poly ^ crc_result>>1 ); } // bitxor($d$1;bitand((d5*2);31)) else { crc_result = (byte) (crc_result>>1); } } // byte3 for (int i=0; i>i ) ^ (crc_result) ) & 0x01 ) > 0 ) // if(xor(c6;bitand(d5;2^4)/2^4) { crc_result = (byte) (crc8_poly ^ crc_result>>1 ); } // bitxor($d$1;bitand((d5*2);31)) else { crc_result = (byte) (crc_result>>1); } } return crc_result;} 结论
本应用笔记介绍了如何针对所有可能的用例对max22007进行编程。max22007评估板用于测试该代码。本应用笔记中的c代码示例是一种经过验证的解决方案,可在常用微控制器和max22007之间快速、轻松地实现接口。


LED和手机双轮驱动 蓝宝石进入景气周期
交换机如何工作?三种交换技术
OPPO Find9渲染图又来了:我才是今年国产第一旗舰!
与非门组成水位计线路图
光耦合器的工作原理/类型/工作模式/作用/应用
如何对MAX22007可配置模拟输出进行编程
国产32位MCU APT32F1023H8S6助力高露洁电动牙刷
VR+安全让你亲身体验灾害的可怕
液态金属赋能柔性电子器件
智能手机“钟情”的卫星通信,到底有何魅力?
用2.4G/5G双频WiFi+蓝牙组合模块破解智能家居WiFi信号受干扰难题
OPPO专利的一款全屏幕的智能手机直接取消掉了前摄
某医疗器械的电磁兼容性电路优化改进方案
变电站无功补偿装置的作用和接入方式
3D打印偏光隐形眼镜,可改善急性光过敏症
台积电将于Q2季度量产苹果A14芯片,使用5nm EUV技术制造
如何监测电梯的故障问题,以保障乘梯者的安全
德国梅赛德斯已开发出基于区块链技术的平台
AMD收购赛灵思后有望诞生业界最大的高性能计算公司
发力64位处理器芯片,苹果又领先一步?