0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何对MAX14906进行编程四通道工业数字输出、数字输入

星星科技指导员 来源:ADI 作者:ADI 2023-02-22 09:49 次阅读

MAX14906为符合IEC 61131-2标准的高速、四通道工业数字输出、数字输入器件,可按通道配置为高边(HS)开关、推挽(PP)驱动器、1、3型或2型数字输入。SPI接口具有内置芯片寻址解码器,允许利用具有公共片选(CS)的共享SPI与多个MAX14906器件通信。SPI接口为全局和每通道配置和诊断提供了灵活性,包括电源过压和欠压检测、断线或开路检测、热过载和电流限制报告等。

本应用笔记介绍了一系列功能,为MAX14906编程提供简单且经过验证的解决方案(图1)。它们是用C#编写的,应该很容易移植到任何常见的微控制器上。有关MAX14906引脚、工作模式、SPI命令和控制寄存器的详细信息,请参考MAX14906数据资料

pYYBAGP1dI-ALAZwAAFroVMIEDY435.jpg

图1.MAX14906典型应用电路

MAX14906 SPI

MAX14906具有高速SPI串行接口,最大时钟速率为10MHz。SPI 接口遵循时钟极性 CPOL = 0(SCLK 空闲 = 0)和时钟相位 CPHA = 0(上升沿/第一沿对数据进行采样)。命令首先以最高有效位 (MSb) 计时。

MAX14906 SPI支持可寻址SPI,允许使用共享CS信号与多达14906个MAX1直接通信。地址引脚 A0 和 A1 用于配置器件地址。地址位 A0 和 A1 作为 SPI 读写命令的第一和第二位发送。器件监视SPI命令,并在地址与A0和A<>引脚的状态匹配时适当地响应SDO。

MAX14906 SPI支持单周期模式和突发模式。单周期模式一次读取或写入一个寄存器,而突发模式允许在一个SPI周期内读取或写入多个连续寄存器。

单周期SPI命令的长度为16位(8位指令+ 8位数据),禁用CRC,如果启用CRC,则会增加8位,包括5位CRC和3个前导零。命令字节的2 MSB为器件地址位(A1和A0),允许4个MAX14906共享相同的片选(CS)引脚。对于单周期模式,BRST 位设置为 0。设备在SDO上发送的数据报告设备故障情况,如果是写入命令,则报告每个通道的状态,如果是读取命令,则报告寄存器值。单周期读写图如图 2 至图 5 所示。

poYBAGP1dJCAS8pZAAFiVD7-vdk010.jpg

图2.SPI 单周期写入命令,CRC 禁用。

poYBAGP1dJGAXUF0AADMG1kk08I574.jpg

图3.SPI 单周期写入命令,启用 CRC。

poYBAGP1dJKAPkynAAEvhpIUI14116.jpg

图4.SPI 单周期读取命令,CRC 禁用。

pYYBAGP1dJKAShrtAADC8kqst4U039.jpg

图5.SPI 单周期读取命令,启用 CRC。

突发 SPI 命令使用一个 SPI 周期和一个寄存器地址写入或读取多个连续寄存器,并通过将 BRST 位设置为 1 来启用。

突发写入命令写入 SetOUT 和 SetLED 寄存器,BRST = 1、R/W = 1 和 R[3:0] = 0。该命令包含两个数据字节,一个用于配置 SetOUT 寄存器,另一个用于配置 SetLED 寄存器。如果未启用 CRC,则 SCLK 周期数为 24,如果启用 CRC,则 SCLK 周期数为 32。SPI突发写入图如图6和图7所示。

突发读取命令从地址0x02到0x07(DoiLevel、Interrupt、OvrLdChF、OpnWirChF、ShtVDDChF 和 GlobalErr 寄存器)检索六个连续诊断寄存器的数据,BRST = 1, R/W = 0, R[3:0] = 2。如果未启用 CRC,则 SCLK 周期数为 56,如果启用了 CRC,则 SCLK 周期数为 64。在突发读取期间,SDI数据流中的数据位9至59可以是0或1,但如果启用CRC,这些位用于计算CRC位。SPI突发读取图如图8和图9所示。

pYYBAGP1dJOAB0lMAADEVMieTyY333.jpg

图6.SPI 突发写入命令,CRC 禁用。

poYBAGP1dJSAFyCQAAGJgj1AV7s237.jpg

图7.SPI 突发写入命令,已启用 CRC。

pYYBAGP1dJSAfRc-AAOTjaNP_sE767.jpg

图8.SPI 突发读取命令,CRC 已禁用。

poYBAGP1dJWAV3WoAAPjJ8SHyzQ718.jpg

图9.SPI 突发读取命令,已启用 CRC。

有关SPI命令的更多详细信息以及寄存器表和指令,请参考MAX14906数据资料。

MAX14906 - 代码应用示例

MAX14906设计用于支持终端设备的工业应用,如可编程逻辑控制器PLC),需要可配置的数字输入(1/3型或2型)或数字输出(高边开关或推挽式驱动器)。典型应用电路支持4通道组隔离,采用单个MAX14483数字隔离器,如图1所示。

源代码

本应用笔记提供了C#源代码示例,主要提供驱动器功能,用于访问MAX14906中的多个寄存器,以实现配置、控制和诊断功能。所有软件均使用MAX14906评估板进行实现和测试。本应用笔记中的功能用于MAX14906评估板软件,用于处理MAX14906 SPI的基本读写命令。设计用于与MAX2232评估板硬件上的FT14906微控制器配合使用。本文档不包括USB通信和低级FT2232功能。本文档中也未包含图形界面功能。

客户应仅将本文档中的功能用作参考,并根据其应用程序中的微控制器和硬件实现设计自己的固件/软件。

单周期写入

       public void WriteRegister(int index)
        {
            if (index < 0 || index >= registers.Count) { return; }

            byte register = 0x00;
            byte[] txBuffer = new byte[2];
            byte[] rxBuffer = new byte[2];

            // Register Byte
            register = 0x01;// Write
            register |= (byte)(index << 1);// Register Address
            register |= (byte)(Address << 6);// Chip Address
            txBuffer[0] = register;
            // Data Byte
            txBuffer[1] = registers[index].Value;
            SPIWriteRead(txBuffer, ref rxBuffer, 2);

            // Store Fault Data
            SDOFaults.SHTVDD = ((rxBuffer[0] & 0x20) >> 5);
            SDOFaults.AbvVDD = ((rxBuffer[0] & 0x10) >> 4);
            SDOFaults.OWOffF = ((rxBuffer[0] & 0x08) >> 3);
            SDOFaults.OvrCurr = ((rxBuffer[0] & 0x04) >> 2);
            SDOFaults.OvldF = ((rxBuffer[0] & 0x02) >> 1);
            SDOFaults.GLOBLF = (rxBuffer[0] & 0x01);
            SDOFaults.ChannelFaults = rxBuffer[1];

            // If successful, clean up
            registers[index].Modified = false;
        }

单周期读取

  public void ReadRegister(int index)
        {
            if (index < 0 || index >= registers.Count) { return; }

            FTDI.FT_STATUS ftStatus;
            byte register = 0x00;
            byte[] txBuffer = new byte[2];
            byte[] rxBuffer = new byte[2];

            // Register Byte
            register = 0x00;// Read
            register |= (byte)(index << 1);// Register Address
            register |= (byte)(Address << 6);// Chip Address
            txBuffer[0] = register;
            // Data Byte
            txBuffer[1] = 0x00;
            ftStatus = SPIWriteRead(txBuffer, ref rxBuffer, 2);
            if (ftStatus == FTDI.FT_STATUS.FT_OK)
            {
                registers[index].Value = rxBuffer[1];
            }

            // Store Fault Data
            SDOFaults.SHTVDD = ((rxBuffer[0] & 0x20) >> 5);
            SDOFaults.AbvVDD = ((rxBuffer[0] & 0x10) >> 4);
            SDOFaults.OWOffF = ((rxBuffer[0] & 0x08) >> 3);
            SDOFaults.OvrCurr = ((rxBuffer[0] & 0x04) >> 2);
            SDOFaults.OvldF = ((rxBuffer[0] & 0x02) >> 1);
            SDOFaults.GLOBLF = (rxBuffer[0] & 0x01);
            //SDOFaults.ChannelFaults = rxBuffer[1];// Not Valid, bc on read this is register data
            
            // If successful, clean up
            registers[index].Modified = false;
        }

突发写入

    public void BurstWriteRegisters(int startIndex, int endIndex)
        {
            // Typically always 0 and 1 only
            if (endIndex < startIndex) { return; }
            if (startIndex < 0) { return; }
            if (endIndex >= registers.Count) { return; }

            int byteCount = (endIndex - startIndex) + 2;
            byte register = 0x00;
            byte[] txBuffer = new byte[byteCount];
            byte[] rxBuffer = new byte[byteCount];

            // Register Byte
            register = 0x01;// Write
            register |= (byte)(startIndex << 1);// Register Address
            register |= (byte)(Address << 6);// Chip Address
            register |= (byte)(0x01 << 5);// Burst
            txBuffer[0] = register;

            // Data Byte
            for (int x = 0; x < (byteCount - 1); x++)
            {
                txBuffer[1 + x] = registers[startIndex + x].Value;
                registers[startIndex + x].Modified = false;
            }
            SPIWriteRead(txBuffer, ref rxBuffer, byteCount);

            // Store Fault Data
            SDOFaults.SHTVDD = ((rxBuffer[0] & 0x20) >> 5);
            SDOFaults.AbvVDD = ((rxBuffer[0] & 0x10) >> 4);
            SDOFaults.OWOffF = ((rxBuffer[0] & 0x08) >> 3);
            SDOFaults.OvrCurr = ((rxBuffer[0] & 0x04) >> 2);
            SDOFaults.OvldF = ((rxBuffer[0] & 0x02) >> 1);
            SDOFaults.GLOBLF = (rxBuffer[0] & 0x01);
            SDOFaults.ChannelFaults = rxBuffer[1];            
        }

突发读取

   public void BurstReadRegisters(int startIndex, int endIndex)
        {
            if (endIndex < startIndex) { return; }
            if (startIndex < 0) { return; }
            if (endIndex >= registers.Count) { return; }

            FTDI.FT_STATUS ftStatus;
            int byteCount = (endIndex - startIndex) + 2;
            byte register = 0x00;
            byte[] txBuffer = new byte[byteCount];
            byte[] rxBuffer = new byte[byteCount];

            // Register Byte
            register = 0x00;// Read
            register |= (byte)(startIndex << 1);// Register Address
            register |= (byte)(Address << 6);// Chip Address
            register |= (byte)(0x01 << 5);// Burst
            txBuffer[0] = register;

            // Data Byte
            for (int x = 0; x < (byteCount - 1); x++)
            {
                txBuffer[1 + x] = 0x00;
            }
            ftStatus = SPIWriteRead(txBuffer, ref rxBuffer, byteCount);

            if (ftStatus == FTDI.FT_STATUS.FT_OK)
            {
                for (int x = 0; x < (byteCount - 1); x++)
                {
                    registers[startIndex + x].Value = rxBuffer[1 + x];
                    registers[startIndex + x].Modified = false;
                }
            }

            // Store Fault Data
            SDOFaults.SHTVDD = ((rxBuffer[0] & 0x20) >> 5);
            SDOFaults.AbvVDD = ((rxBuffer[0] & 0x10) >> 4);
            SDOFaults.OWOffF = ((rxBuffer[0] & 0x08) >> 3);
            SDOFaults.OvrCurr = ((rxBuffer[0] & 0x04) >> 2);
            SDOFaults.OvldF = ((rxBuffer[0] & 0x02) >> 1);
            SDOFaults.GLOBLF = (rxBuffer[0] & 0x01);
        }

CRC 计算

 private CRC8 crc8 = new CRC8(0x15, 0x1F);

    class CRC8
    {
        private readonly byte POLY = 0x00;
        private readonly byte START_VALUE = 0x00;

        public CRC8(byte poly, byte startValue = 0x00)
        {
            this.POLY = poly;
            this.START_VALUE = startValue;
        }

        public byte ComputeChecksum3MSB(byte[] bytes)
        {
            byte remainder = START_VALUE;
            byte min = 0;
            for (int bite = 0; bite < bytes.Length; ++bite)
            {
                // For MAX14906 it does 8/16bits plus the 3 "0" MSBs of check byte
                if (bite == (bytes.Length - 1)) { min = 5; }

                for (byte bit = 8; bit > min; --bit)
                {
                    remainder = (((bytes[bite] >> (bit - 1) & 0x01) ^ ((remainder >> 4) & 0x01)) > 0) ? (byte)((remainder << 1) ^ POLY) : (byte)(remainder << 1);
                }
            }
            return (byte)(remainder & 0x1F);
        }
    }

为每个通道配置操作模式的示例

   public void SendModeAndSetting(int channel, int mode, int setting)
        {
            if (channel < 1 || channel > 4) { return; }
            if (mode < 0 || mode > 2) { return; }
            if (((mode == 1) && (setting < 0 || setting > 4)) || ((mode == 0) && (setting < 0 || setting > 2)) || (mode == 2 && setting != 0)) { return; }
            
            byte register = 0x00;
            byte data = 0x00;
            byte[] txBuffer = new byte[2];
            byte[] rxBuffer = new byte[2];

            if (mode == 0 || mode == 2)// Input or Low-leakage
            {
                ////////////////////////////
                // Reg 0x00:
                ///////////////////////////
                // Register Byte
                register = 0x01;// Write
                register |= (0x00 << 1);// Register Address
                register |= (byte)(Address << 6);// Chip Address
                txBuffer[0] = register;
                // Data Byte
                // Set current bit mode from FTDI
                byte temp = 0x00;
                // Remember bit logic for FTDI input/output inverted from MAX14906 Reg 0x00 
                temp = (byte)((~FTDI_ADBUS_MODE & 0x80) >> 7);// DIO1
                data |= (byte)(temp << 4);
                temp = (byte)((~FTDI_ACBUS_MODE & 0x01));// DIO2
                data |= (byte)(temp << 5);
                temp = (byte)((~FTDI_ACBUS_MODE & 0x02) >> 1);// DIO3
                data |= (byte)(temp << 6);
                temp = (byte)((~FTDI_ACBUS_MODE & 0x04) >> 2);// DIO4
                data |= (byte)(temp << 7);
                // New Mode to Set
                temp = (byte)(0x01 << (channel + 3));
                data = (mode == 0 || mode == 2) ? (byte)(temp | data) : (byte)(~temp & data);
                txBuffer[1] = data;
                SPIWriteRead(txBuffer, ref rxBuffer, 2);

                ////////////////////////////
                // Reg 0x0C:
                ///////////////////////////
                // Register Byte
                register = 0x00;// Read
                register |= (0x0C << 1);// Register Address
                register |= (byte)(Address << 6);// Chip Address
                txBuffer[0] = register;
                // Get Current Data from Reg 0x0C
                SPIWriteRead(txBuffer, ref rxBuffer, 2);
                temp = rxBuffer[1];

                // Register Byte
                register = 0x01;// Write
                register |= (0x0C << 1);// Register Address
                register |= (byte)(Address << 6);// Chip Address
                txBuffer[0] = register;
                // Data Byte
                data = (setting == 1) ? (byte)(temp | 0x80) : (byte)(temp & ~0x80);// Type 2 IEC Mode, Note this forces all DI to be in this mode
                txBuffer[1] = data;
                SPIWriteRead(txBuffer, ref rxBuffer, 2);

                ////////////////////////////
                // Reg 0x0D:
                ///////////////////////////
                // Register Byte
                register = 0x01;// Write
                register |= (0x0D << 1);// Register Address
                register |= (byte)(Address << 6);// Chip Address
                txBuffer[0] = register;
                // Data Byte
                data = (byte)(DO_Settings & ~(0x03 << (channel - 1) * 2));// Whether any setting (Normal, IEC 2, or Low-leakage) zero out both bits
                if (mode == 2)// Low-leakage
                {
                    data |= (byte)(0x02 << (channel - 1) * 2);// For Low-leakage DI must set PP
                }
                DO_Settings = data;

                txBuffer[1] = data;
                SPIWriteRead(txBuffer, ref rxBuffer, 2);
            }
            else// Output
            {
                ////////////////////////////
                // Reg 0x00:
                ///////////////////////////
                // Register Byte
                register = 0x01;// Write
                register |= (0x00 << 1);// Register Address
                register |= (byte)(Address << 6);// Chip Address
                txBuffer[0] = register;
                // Data Byte
                // Set current bit mode from FTDI
                byte temp = 0x00;
                // Remember bit logic for FTDI input/output inverted from MAX14906 Reg 0x00 
                temp = (byte)((~FTDI_ADBUS_MODE & 0x80) >> 7);// DIO1
                data |= (byte)(temp << 4);
                temp = (byte)((~FTDI_ACBUS_MODE & 0x01));// DIO2
                data |= (byte)(temp << 5);
                temp = (byte)((~FTDI_ACBUS_MODE & 0x02) >> 1);// DIO3
                data |= (byte)(temp << 6);
                temp = (byte)((~FTDI_ACBUS_MODE & 0x04) >> 2);// DIO4
                data |= (byte)(temp << 7);
                // New Mode to Set
                temp = (byte)(0x01 << (channel + 3));
                data = (mode == 0) ? (byte)(temp | data) : (byte)(~temp & data);
                txBuffer[1] = data;
                SPIWriteRead(txBuffer, ref rxBuffer, 2);

                ////////////////////////////
                // Reg 0x0D:
                ///////////////////////////
                // Register Byte
                register = 0x01;// Write
                register |= (0x0D << 1);// Register Address
                register |= (byte)(Address << 6);// Chip Address
                txBuffer[0] = register;
                // Data Byte
                data = (byte)(DO_Settings & ~(0x03 << (channel - 1) * 2));// Whether any setting (HS, HS 2x, PP clamp, PP low) zero out both bits
                data |= (byte)(setting << (channel - 1) * 2);

                DO_Settings = data;// Update settings

                txBuffer[1] = data;
                SPIWriteRead(txBuffer, ref rxBuffer, 2);
            }

            // Store Fault Data
            SDOFaults.SHTVDD = ((rxBuffer[0] & 0x20) >> 5);
            SDOFaults.AbvVDD = ((rxBuffer[0] & 0x10) >> 4);
            SDOFaults.OWOffF = ((rxBuffer[0] & 0x08) >> 3);
            SDOFaults.OvrCurr = ((rxBuffer[0] & 0x04) >> 2);
            SDOFaults.OvldF = ((rxBuffer[0] & 0x02) >> 1);
            SDOFaults.GLOBLF = (rxBuffer[0] & 0x01);
            SDOFaults.ChannelFaults = rxBuffer[1];
        }

结论

本应用笔记介绍了如何对MAX14906进行编程,以监测输入、驱动输出和诊断故障条件。该代码使用MAX14906EVKIT#进行测试。工程师可以使用本应用笔记中提到的C代码示例,快速轻松地实现常用微控制器和MAX14906之间的接口。

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 微控制器
    +关注

    关注

    48

    文章

    6812

    浏览量

    147659
  • 驱动器
    +关注

    关注

    51

    文章

    7319

    浏览量

    142996
  • SPI
    SPI
    +关注

    关注

    17

    文章

    1615

    浏览量

    89669
收藏 人收藏

    评论

    相关推荐

    四通道示波器

    四通道示波器,要的拿走
    发表于 08-26 08:46

    求大神帮忙设计一个四通道位半的数字电压表,量程为0-2500mv,感激不尽

    求大神帮忙设计一个四通道位半的数字电压表,量程为0-2500mv,感激不尽
    发表于 08-03 16:04

    【小梅哥FPGA进阶教程】第十三章 四通道数字电压表

    ,数码管上均有正常的显示,且切换通道时数据可以随之更新。至此一个四通道数字电压表设计完毕。附:基于查找表的数据电压换算前面指出了一种数据处理及码制的方式,这里再列举利用查找表的实现方式。这里因为是
    发表于 02-26 15:52

    HZD-W/L型四通道振动监控仪

    HZD-W/L型四通道振动监控仪为双切换的仪表,与SZ-6系列振动速度传感器配套,可以检测振动位移和振动速度。振动值的大小由前面板的表头显示,同时具有标准的电流输出,可与各种DCS、PLC系统
    发表于 06-13 13:31

    请问tlc5620四通道怎么同时输出

    请问tlc5620四通道怎么同时输出,类似的dac方法也可以,求借鉴
    发表于 09-11 16:14

    可实现四通道模拟输入和双通道模拟输出的参考设计

    描述TIDA-00170 是适用于工业控制模拟混合输入输出模块的参考设计。该设计可实现四通道模拟输入和双通道模拟
    发表于 11-09 16:58

    允许单端和差动输入源的四通道14位250Msps数字转换器

    描述此参考设计展示了一种具有宽输入范围的四通道 14 位 250Msps 数字转换器,采用了 LMH6881 可编程差动放大器和 ADS4449
    发表于 12-17 15:40

    四通道电源管理电路MAX16922相关资料分享

    四通道电源管理电路MAX16922资料下载内容包括:MAX16922引脚功能MAX16922内部方框图MAX16922极限参数
    发表于 03-31 06:46

    现货供应RIGOL普源DS4014四通道数字示波器

    现货供应RIGOL普源DS4014四通道数字示波器普源DS4014成色漂亮 出售+收购安捷伦/力科/泰克/普源/横河 /是德等品牌:各型号/示波器。收购工厂闲置+个人闲置二手测量仪器仪表。
    发表于 10-25 16:35

    AD9144,AD9148,AD9177的四通道输出都可以路同步输出吗?

    AD9144,AD9148,AD9177这三款芯片都是四通道输出的芯片,请问这三款芯片的四通道输出都可以路同步
    发表于 12-01 12:24

    使用AD7656进行四通道采样,将四通道输入接地后采样值出现异常的原因?

    求助:使用AD7656进行四通道采样,将四通道输入接地后采样发现采样值出现异常,具体表现(见图1)为: 1. 第一通道采样正确,跳动量不超
    发表于 12-18 06:10

    使用数字I/O IC简化您的PLC设计

      Maxim Integrated 推出了其最新的 DIO 产品MAX14906,它解决了关键的 PLC 和电机控制系统设计挑战。MAX14906 四通道器件采用 SafeDemag ™技术,可快速关断无限电感,工作电源电压高
    的头像 发表于 05-20 08:41 1795次阅读

    MAX14906: Quad-Channel Industrial Digital Output, Digital Input Data Sheet MAX14906: Quad-Channel Industrial Digital Output, Digital Input D

    电子发烧友网为你提供ADI(ADI)MAX14906: Quad-Channel Industrial Digital Output, Digital Input Data Sheet相关产品参数
    发表于 10-13 18:44
    <b class='flag-5'>MAX14906</b>: Quad-Channel Industrial Digital Output, Digital Input Data Sheet <b class='flag-5'>MAX14906</b>: Quad-Channel Industrial Digital Output, Digital Input D

    MAX14906PMB: Evaluation Kit for the MAX14906 Data Sheet MAX14906PMB: Evaluation Kit for the MAX14906 Data Sheet

    电子发烧友网为你提供ADI(ADI)MAX14906PMB: Evaluation Kit for the MAX14906 Data Sheet相关产品参数、数据手册,更有MAX14906
    发表于 10-13 18:54
    <b class='flag-5'>MAX14906</b>PMB: Evaluation Kit for the <b class='flag-5'>MAX14906</b> Data Sheet <b class='flag-5'>MAX14906</b>PMB: Evaluation Kit for the <b class='flag-5'>MAX14906</b> Data Sheet

    MAX14906EVKIT: Evaluation Kit for the MAX14906 Data Sheet MAX14906EVKIT: Evaluation Kit for the MAX14906 Data Sheet

    电子发烧友网为你提供ADI(ADI)MAX14906EVKIT: Evaluation Kit for the MAX14906 Data Sheet相关产品参数、数据手册,更有
    发表于 10-17 19:14
    <b class='flag-5'>MAX14906</b>EVKIT: Evaluation Kit for the <b class='flag-5'>MAX14906</b> Data Sheet <b class='flag-5'>MAX14906</b>EVKIT: Evaluation Kit for the <b class='flag-5'>MAX14906</b> Data Sheet