外设驱动库开发笔记41:ADS1256 ADC驱动

  我们经常会碰到多通道AD采集的需求,有时候甚至需要高精度的ADC器件。本篇我们将来设计并实现ADS1256模数转换器的驱动。并简单讨论该驱动使用方式。

1、功能概述

  ADS1256是TI公司推出的一款低噪声高分辨率的24位Sigma-Delta(E-v)模数转换器(ADC)。E-vADC与传统的逐次逼近型和积分型ADC相比有转换误差小而价格低廉的优点,但由于受带宽和有效采样率的限制,E-vADC不适用于高频数据采集的场合。该款ADS1256可适合于采集最高频率只有几千赫兹的模拟数据的系统中,数据输出速率最高可为30K采样点/秒,4路差分或8路伪差分输入,有完善的自校正和系统校正系统,SPI串行数据传输接口。其结构图如下所示:

  从结构图可以看出来,ADS1256是模拟区域与数字区域完全独立的ADC,即AVDD给模拟区域供电,DVDD给数字区域供电,在原理图设计方面按照官方指导文档,需要对两个区域做独立的布线与隔离处理,才能让信噪比最佳。
  ADS1256采用SSOP的封装形式,具有8个模拟输入通道,共28个引脚,与其类似的2通道产品ADS1255共有20引脚,其实两者操作相同,所以我们设计驱动也会考虑兼容性。其中ADS1256引脚排布和定义如下图所示:

  ADS1255和ADS1256的操作是通过一组寄存器来控制的。这些寄存器包含了配置部件所需的所有信息,如数据速率、多路复用器设置、PGA设置、校准等。这些寄存器的地址及结构如下表所述:

  我们知道了这些寄存器的定义,那么就可以操作ADS1256了。可是我们怎么来实现对这些寄存器的访问呢?这就涉及到操作命令的问题了。ADS1256有多个操作命令,具体如下表所示:

  在以上这些命令中,除了读写寄存器操作需要有第二个字节命令和数据外,其它命令都是独立使用的。

2、驱动设计与实现

  我们已经了解了ADS1256的相关结构、寄存器及操作命令。接下来我们就来考虑如何设计ADS1256的驱动程序。

2.1、对象定义

  与以往一样,我们依然是基于对象来实现ADS1256的驱动程序,所以我们需要抽象出ADS1256的对象类型。

2.1.1、抽象数据类型

  我们先来考虑一下ADS1256对象类型的定义问题。一个对象一般来说主要包括属性和操作两个方面的内容,我们也从这两个方面来分析ADS1256对象。
  首先我们来考虑ADS1256模数转换器对象的属性。这些属性必须能够标识ADS1256模数转换器对象的特征,或者是存储ADS1256模数转换器对象的某种状态。对于ADS1256模数转换器对象我们希望可以记录寄存器的状态,所以我们将各个寄存器定义为该对象的属性。
  接下来我们再来考虑一下ADS1256模数转换器对象的操作。一个对象有各种各样的操作,或者说他能实现很多的操作,但不是所有的操作都是我们要提取的。我们需要考虑的是那些对象所独有并且同类对象都必不可少的操作,以及那些不能由对象独自完成,依赖于具体平台但又决定对象的行为的必要操作。对于ADS1256莫数转换器,我们需要读写数据,操作片选信号,读取就绪信号等。但这些操作都依赖于具体的软硬件平台,我们将这些操作定义对象的操作,通过函数指针的方式将具体的操作函数传递给对象变量,以便于适用于不同的软硬件平台。此外,由于时序控制的需要我们需要在驱动中使用延时操作,而延时操作的实现依赖于具体的软硬件平台,所以我们也将其抽象为对象的操作。根据上述我们的分析,可以定义ADS1256模数转换器对象的类型如下:

/*定义ADS1256对象类型*/
typedef struct ADS1256Object {uint8_t Register[11];void (*ReadWrite)(uint8_t *wData,uint8_t *rData,uint16_t size);       //实现读写操作void (*ChipSelect)(ADS1256CSType cs);  //实现片选uint16_t (*GetReadyInput)(void);      //实现Ready状态监视void (*Delay)(volatile uint32_t nTime);       //实现ms延时操作
}ADS1256ObjectType;

2.1.2、对象初始化函数

  我们抽象了ADS1256模数转换器的对象类型,使用这一对象类型我们可以获得具体的对象变量,但这一对象变量必须要进行必要的属性和操作设定才能进行正确的操作。为了完成对象变量属性和操作的配置,我们需要一个对象初始化函数。

/*ADS1256初始化配置函数*/
void ADS1256Initialization(ADS1256ObjectType *ads,              //待初始化的ADS1256对象ADS1256OrderType order,              //数据顺序ADS1256ACALType acal,                //自动校准使能ADS1256BufenType bufEn,              //模拟量缓存使能ADS1256ClkoutType clkOut,            //时钟输出类型ADS1256SDCSType sdcs,                //传感器检测电流ADS1256GainType gain,                //增益ADS1256DRateType dataRate,           //数据输出速率ADS1256DIOType *dio,                 //输入输出配置ADS1256ReadWriteType readWrite,      //读写函数指针ADS1256ChipSelectType cs,            //片选函数指针ADS1256GetReadyInputType ready,      //就绪函数指针ADS1256DelaymsType delayms           //毫秒延时函数指针)
{uint8_t Order[]={STATUS_ORDER_MOST,STATUS_ORDER_LEAST};uint8_t ACAL[]={STATUS_ACAL_DISABLE,STATUS_ACAL_ENABLE};uint8_t BUFEN[]={STATUS_BUFEN_DISABLE,STATUS_BUFEN_ENABLE};uint8_t clkck[]={ADCON_CLOCK_OFF,ADCON_CLOCK_FCLKIN,ADCON_CLOCK_HALF,ADCON_CLOCK_QUARTER};uint8_t sDCS[]={ADCON_SDCS_OFF,ADCON_SDCS_05uS,ADCON_SDCS_2uS,ADCON_SDCS_10uS};uint8_t gains[]={ADCON_PGA_GAIN1,ADCON_PGA_GAIN2,ADCON_PGA_GAIN4,ADCON_PGA_GAIN8,ADCON_PGA_GAIN16,ADCON_PGA_GAIN32,ADCON_PGA_GAIN64};uint8_t dRate[]={DRATE_30000SPS,DRATE_15000SPS,DRATE_7500SPS,DRATE_3750SPS,DRATE_2000SPS,DRATE_1000SPS,DRATE_500SPS,DRATE_100SPS,DRATE_60SPS,DRATE_50SPS,DRATE_30SPS,DRATE_25SPS,DRATE_15SPS,DRATE_10SPS,DRATE_5SPS,DRATE_2_5SPS};uint8_t dir[4][2]={{GPIO_DIR0_OUTPUT,GPIO_DIR0_INPUT},{GPIO_DIR1_OUTPUT,GPIO_DIR1_INPUT},{GPIO_DIR2_OUTPUT,GPIO_DIR2_INPUT},{GPIO_DIR3_OUTPUT,GPIO_DIR3_INPUT}};if((ads==NULL)||(readWrite==NULL)||(ready==NULL)||(delayms==NULL)){return;}ads->ReadWrite=readWrite;ads->GetReadyInput=ready;ads->Delay=delayms;if(cs==NULL){ads->ChipSelect=ADS1256ChipSelect;}else{ads->ChipSelect=cs;}for(int i=0; i<11;i++){ads->Register[i]=0x00;}ads->Register[REG_STATUS]=Order[order]||ACAL[acal]||BUFEN[bufEn];ads->Register[REG_MUX]=0x00;ads->Register[REG_ADCON]=clkck[clkOut]||sDCS[sdcs]||gains[gain];ads->Register[REG_DRATE]=dRate[dataRate];ads->Register[REG_IO]=dir[0][dio[0]]||dir[1][dio[1]]||dir[2][dio[2]]||dir[3][dio[3]];WriteADS1256Register(ads,REG_STATUS,1);WriteADS1256Register(ads,REG_MUX,1);WriteADS1256Register(ads,REG_ADCON,1);WriteADS1256Register(ads,REG_DRATE,1);WriteADS1256Register(ads,REG_IO,1);ADS1256Calibration(ads,SELFCAL);ReadADS1256Register(ads,REG_STATUS,11);
}

  在这个初始化函数中,我们完成两个方面的内容:一是对属性的赋值和对操作函数指针进行初始化;二是对对象变量所代表的对象进行初始化配置。

2.2、对象操作

  我们获得了ADS1256模数转换器的对象类型,也编写了初始化对象变量的函数,接下来我们考虑一下ADS1256模数转换器的一些主要的操作过程。

2.2.1、读数据

  作为模数转换器,我们首要的目的就是从其获得我们想要的数据。ADS1256读数据分为连续读取和非连续读取,在这里我们考虑单次读取数据的操作。当模数转换完成后,就绪信号下拉到“0”,这个时候可以读取数据,数据读取后就绪信号将上拉到“1”。

  根据上述描述和时序图我们可以编写读取数据的操作如下:

/*ADS1256读取数据*/
static uint32_t ADS1256ReadData(ADS1256ObjectType *ads)
{uint8_t cmd[1]={RDATA};uint8_t rData[3];uint32_t result=0;while(ads->GetReadyInput()==1);ads->ChipSelect(ADS1256CS_Enable);ads->ReadWrite(cmd,rData,3);ads->ChipSelect(ADS1256CS_Disable);result=rData[0];result=(result<<8)+rData[1];result=(result<<8)+rData[2];return result;
}

2.2.2、读寄存器

  我们已经了解ADS1256有11个寄存器,这些寄存器都可读取。读取寄存器的命令由2个字节组成。第一个字节是读寄存器命令0x10与寄存器起始地址合并而成。第二个字节是所要读取的寄存器数量减1。具体的操作时序如下图所示:

  根据上述对读寄存器的描述和时序图我们可以编写读寄存器的操作如下:

/*读ADS1256寄存器*/
static void ReadADS1256Register(ADS1256ObjectType *ads,uint8_t regAddr,uint8_t regNum)
{uint8_t cmd[2];uint8_t rData[11];cmd[0]=RREG|regAddr;cmd[1]=regNum-1;ads->ChipSelect(ADS1256CS_Enable);ads->ReadWrite(cmd,rData,2);cmd[0]=0;cmd[1]=0;ads->ReadWrite(cmd,rData,regNum);ads->ChipSelect(ADS1256CS_Disable);for(int i=0;i<regNum;i++){ads->Register[regAddr+i]=rData[i];}
}

2.2.3、写寄存器

  在ADS1256的11个寄存器中有一些寄存器用于配置ADS1256的工作特性,可以写这些寄存器。写寄存器的命令也是由2个自己组成。第一个字节是读寄存器命令0x50与寄存器起始地址合并而成。第二个字节是所要写的寄存器数量减1。具体的操作时序如下图所示:

  根据上述对写寄存器的描述和时序图我们可以编写写寄存器的操作如下:

/*写ADS1256寄存器*/
static void WriteADS1256Register(ADS1256ObjectType *ads,uint8_t regAddr,uint8_t regNum)
{uint8_t wData[7];uint16_t index=0;uint8_t rData[2];wData[index++]=WREG|regAddr;wData[index++]=regNum-1;for(int i=0;i<regNum;i++){wData[index++]=ads->Register[regAddr+i];}ads->ChipSelect(ADS1256CS_Enable);ads->ReadWrite(wData,rData,index);ads->ChipSelect(ADS1256CS_Disable);
}

3、驱动的使用

  我们已经设计并实现了ADS1256模数转换器的驱动程序。在这一节中我们将设计一个简单的例子,通过这个例子我们将简单的验证驱动程序的正确性,并简要说明驱动的使用方法。

3.1、声明并初始化对象

  我们为ADS1256模数转换器设计的驱动是基于对象开发的,所以我们在使用驱动之前需要声明一个ADS1256模数转换器对象变量。使用我们前面定义的ADS1256模数转换器对象类型声明这一变量如下:
  ADS1256ObjectType ads1256;
  声明了这个对象变量后,我们还需要使用对象初始化函数来将这个对象变量变量进行初始化。我们设计的初始换函数有多个参数:

ADS1256ObjectType *ads,              //待初始化的ADS1256对象
ADS1256OrderType order,              //数据顺序
ADS1256ACALType acal,                //自动校准使能
ADS1256BufenType bufEn,              //模拟量缓存使能
ADS1256ClkoutType clkOut,            //时钟输出类型
ADS1256SDCSType sdcs,                //传感器检测电流
ADS1256GainType gain,                //增益
ADS1256DRateType dataRate,           //数据输出速率
ADS1256DIOType *dio,                 //输入输出配置
ADS1256ReadWriteType readWrite,      //读写函数指针
ADS1256ChipSelectType cs,            //片选函数指针
ADS1256GetReadyInputType ready,      //就绪函数指针
ADS1256DelaymsType delayms           //毫秒延时函数指针

  这些参数中,ADS1256对象我们已经声明。数据顺序、自动校准使能、模拟量缓存使能、时钟输出类型、传感器检测电流、增益、数据输出速率等几个参数均为枚举量,我们们根据需要选择就可,在这里我们均按默认值选择。输入输出配置这个参数,因有4个IO需独立配置,所以我们定义一个数组,并将其传入。剩下的几个函数指针其原型定义如下:

/*定义读写操作函数指针类型*/
typedef void (*ADS1256ReadWriteType)(uint8_t *wData,uint8_t *rData,uint16_t size);
/*实现片选*/
typedef void (*ADS1256ChipSelectType)(ADS1256CSType cs);
/*实现Ready状态监视*/
typedef uint16_t (*ADS1256GetReadyInputType)(void);
/*实现ms延时操作*/
typedef void (*ADS1256DelaymsType)(volatile uint32_t nTime);

  我们需要根据函数的原型声明来结合具体的软硬件平台设计这几个函数,并将函数指针以参数的形式传递给初始函数。我们是在STM32平台来实现这个示例,所以延时函数我们直接采用HAL_Delay即可,其他几个函数实现如下:

/*定义片选信号函数*/
void ADS1256CS(ADS1256CSType en)
{if(ADS1256CS_Enable==en){HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_RESET);}else{HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_SET);}
}/* 定义就绪信号读取函数 */
uint16_t ADS1256CheckReady(void)
{return HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_0);
}/*定义发送数据函数*/
void ADS1256WriteReadData(uint8_t *wData,uint8_t *rData,uint16_t size)
{HAL_SPI_TransmitReceive(&ads1256hspi,wData,rxData,size,1000);
}

  根据上述这些定义后,我们可以调用初始化函数来实现对ADS1256对象变量进行初始化。具体如下:

ADS1256DIOType dio[4]={ADS1256_DIO_INPUT,ADS1256_DIO_INPUT,ADS1256_DIO_INPUT,ADS1256_DIO_OUTPUT};/*ADS1256初始化配置函数*/ADS1256Initialization(&ads1256,               //待初始化的ADS1256对象ADS1256_ORDER_MOST,     //数据顺序ADS1256_ACAL_DISABLE,   //自动校准使能ADS1256_BUFEN_DISABLE,  //模拟量缓存使能ADS1256_CLKOUT_FCLKIN,  //时钟输出类型ADS1256_SDCS_OFF,       //传感器检测电流ADS1256_GAIN1,          //增益ADS1256_DRATE_30000SPS, //数据输出速率dio,                    //输入输出配置ADS1256WriteReadData,   //读写函数指针ADS1256CS,              //片选函数指针ADS1256CheckReady,      //就绪函数指针HAL_Delay               //毫秒延时函数指针);

3.2、基于对象进行操作

  在完成对象变量的初始化后,我们就可以通过操作这个对象变量获取采集的数据。这里我们采集8路单端输入的数据。需要注意的是每次读出来的数据并非我们当前设定的通道的数据,而是我们上次设定的通道的数据。据此我们设计简单的数据采集函数如下:

/*获取通道数据*/
void GetADS1256ChannelValue(void)
{int32_t dataCode[8];for(ADS1256ChannelType ainP=ADS1256_AIN0;ainP<ADS1256_AINCOM;ainP++){if(ainP==ADS1256_AIN0){dataCode[7]=ADS1256SingleReadData(&ads1256,ainP,ADS1256_AINCOM);}else{dataCode[ainP]=ADS1256SingleReadData(&ads1256,ainP,ADS1256_AINCOM);}}}

4、应用总结

  我们设计了ADS1256模数转换器的驱动程序,并利用一个简单的例子对齐进行了验证,读取数据没有问题。
  在使用驱动程序时需要注意,片选信号并非必须实现。因为有些时候我们可能需要在硬件上直接将其选中,此时添加片选操作函数是没有什么意义的,我们可以在初始化时传入NULL来完成。
  在使用驱动程序时需要注意,ADS1256模数转换器在设置通道选择然后就可以在转换过程中读取上一个转换周期的数据。所以在驱动程序中,设置通道选择后,没有等待转化完成,而是直接读取了数据,这个数据实际上是上一次转换的数据,这样可以充分利用转换周期。所以在使用驱动程序需要注意读取的数据所对应的通道。

欢迎关注:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PID参数自整定库之一:继电反馈整定算法

在前述的篇章中&#xff0c;我们实现了PID控制器并在后续对其进行了改进。但作为经典PID控制器还存在PID参数整定的问题。通常我们可以采取人工整定的办法&#xff0c;但人工整定涉及到比较专业的知识&#xff0c;而且找到合适的参数本身也不是一件容易的事&#xff0c;所以人们…

外设驱动库开发笔记42:DAC8552 DAC驱动

模拟信号输出是经常会遇到的应用需求&#xff0c;解决的办法应多种&#xff0c;但我们使用最多的还是数模转换。对于不同的数模转换器我们需要为其编写适用的驱动程序&#xff0c;在这一篇中我们就来考虑如何实现DAC8552高精度模数转换器的驱动程序。 1、功能概述 该DAC8552是…

软件设计开发笔记2:基于QT设计串口调试工具

串口通信是我们经常会遇到的问题。很多时候当我们设计一个串口应用时&#xff0c;我们希望有一个简便的、可视的方式来验证它。这一篇中我们就来基于QT设计一个串口调试工具。 1、概述 在开始软件设计之前&#xff0c;我们来简略地分析一下这样一个小软件其要包含的主要内容有…

外设驱动库开发笔记43:GPIO模拟SPI驱动

SPI总线是我们常用的串行设备接口&#xff0c;一般情况下我们都会适应硬件SPI接口&#xff0c;但有些时候当硬件端口不足时&#xff0c;我们也希望可以使用软件来模拟SPI硬件接口&#xff0c;特别是要求不是很高的时候。在这一篇中我们将来讨论如何使用GPIO和软件来模拟SPI通讯…

外设驱动库开发笔记44:DDC114 ADC驱动

在产品设计过程中&#xff0c;很多时候都会用到ADC器件&#xff0c;而在一些特殊场合还需要一些特别的ADC器件。我们在这篇中将讨论常用于医疗器件方面的&#xff0c;DDC114这款电流输入ADC&#xff0c;并为其设计一个驱动程序。 1、功能概述 模数转换器DDC114是一款电流输入型…

PID控制器改进笔记之七:改进PID控制器之防超调设定

我们已经设计了PID控制器&#xff0c;并根据实际使用的情况对器进行了诸多的改进。在这一篇中我们将讨论如何改进PID控制器超调的问题。 1、问题提出 在前面的文章中&#xff0c;我们曾推导过增量式PID控制器的公式&#xff0c;并且对其进行了离散化以适用于程序实现&#xff…

软件设计开发笔记3:基于QT的Modbus RTU主站

Modbus是一种常见的工业系统通讯协议。在我们的设计开发工作中经常使用到它。在这一篇中我们将简单实现一个基于QT的Modbus RTU主站上位工具。 1、概述 Modbus RTU主站应用很常见&#xff0c;有一些是通用的&#xff0c;有一些是专用的。而这里我们希望实现一个主要针对我们的…

外设驱动库开发笔记45:MS4515DO压力传感器驱动

很多时候我们需要检测流量和压力这些参数&#xff0c;比如我们要检测大气压&#xff0c;或者通过测量差压来获得输送流体的流量等&#xff0c;都需要用到压力传感器。这一篇我们就来讨论MS4515DO压力传感器的数据获取。 1、功能概述 MS4515DO是TE公司推出的一款基于PCB安装的小…

外设驱动库开发笔记48:MCP4725单通道DAC驱动

在产品设计过程中&#xff0c;我们经常会遇到数模转换的应用需求。在本篇种我们就来讨论一下MCP4725单通道数模转换器的驱动设计与实现。 1、功能概述 MCP4725是一个低功耗&#xff0c;高精度&#xff0c;单通道&#xff0c;12位缓冲电压输出数字到模拟转换器(DAC)与非易失性存…

如何确保不使用动态内存

在许多嵌入式应用程序中&#xff0c;内存分配必须是静态的&#xff0c;而不是动态的。意味着在应用程序中不应使用对malloc()或free()等内容的调用&#xff0c;因为它们可能会在运行时失败&#xff08;内存不足、堆碎片&#xff09;。 但是&#xff0c;当与第三方库甚至 C/C 标…

go 单元测试 testing 打印输出_2020,你需掌握go 单元测试进阶篇

本文说明go语言自带的测试框架未提供或者未方便地提供的测试方案&#xff0c;主要是用于解决写单元测试中比较头痛的依赖问题。也就是伪造模式&#xff0c;经典的伪造模式有桩对象(stub),模拟对象(mock)和伪对象(fake)。比较幸运的是&#xff0c;社区有丰富的第三方测试框架支持…

一文读懂Git工作流

Git是目前最流行的代码管理工具&#xff0c;相信大家也都是在用Git来管理自己团队的源代码。 团队一般为了规范开发&#xff0c;保持良好的代码提交记录以及维护 Git 分支结构清晰&#xff0c;方便后续维护等&#xff0c;都会迫切需要一个比较规范的 Git 工作流。 本文就是在…

xbox360fsd更新游戏封面_游戏类短视频创作指南

一&#xff0e;起步阶段1.内容发布垂直&#xff0c;整体风格一致&#xff0c;选定一个品类的游戏内容风格持续更新注意&#xff1a;冷启动时期不要频繁更换游戏类型2.账号IP化 根据自身风格特色打造独特的风格账号。有利延长账号生命周期&#xff0c;提升粉丝转化率。搞笑、中二…

开发者们都在关注的网站

开发者们都在关注的网站 &#x1f609; 综合类&#xff08;5个&#xff09; 1、GitHub 全球最大的编程开源社区&#xff0c;很多优秀的开源项目都在上边&#xff0c;不知道这个都不要说自己是程序员&#x1f602; 访问地址&#xff1a;https://github.com 2、CSDN 全球最大中…

ios framework 调用第三方 framework_Python基础:标准库和常用的第三方库

Python的标准库有&#xff1a;名称作用datetime为日期和时间处理同时提供了简单和复杂的方法。zlib直接支持通用的数据打包和压缩格式&#xff1a;zlib&#xff0c;gzip&#xff0c;bz2&#xff0c;zipfile&#xff0c;以及 tarfile。random提供了生成随机数的工具。math为浮点…

作图神器ProcessOn - 免费好用

因工作需要&#xff0c;我经常需要花一些流程图&#xff0c;时序图&#xff0c;架构图什么的&#xff0c;之前使用的Windows系统&#xff0c;大部分情况下就用的Visio来画图。后来为了工作方便&#xff0c;换成了Mac电脑&#xff0c;结果发现Mac上没有Visio&#xff0c;然后就在…

三电平igbt死区时间计算_基于大功率三电平IGBT模块并联的参考设计

当前的可再生能源行业中&#xff0c;光伏和风力发电均面临着补贴逐步退坡&#xff0c;平价上网时代即将到来的挑战。为应对这一挑战&#xff0c;光伏逆变器和风力变流器厂家研发的新品单机功率越来越高&#xff0c;以取得更低的单位功率成本。市场上1.5MW的集中式光伏逆变器和3…

手把手教你搭建开发环境之Java开发

大家好呀&#xff0c;从今天开始&#xff0c;我们的手把手系列教程就正式开始啦。 如果你觉得本文对你有一些帮助&#xff0c;欢迎大家关注、点赞、分享给需要的小伙伴们&#xff0c;谢谢大家啦。 前言 Java虽然是一个比较老的语言&#xff0c;但到现在依然充满了活力&#x…

opc服务器组态文件已写保护_远程组态软件不仅方便了PLC无线远程监控,也大大降低了工程成本...

远程组态软件不仅方便了PLC无线远程监控&#xff0c;也大大降低了工程成本组态软件远程监控1.本地上位SCADA系统采集分布各地现场PLC等设备运行的数据&#xff0c;并可以下发控制指令&#xff1b;2.提供稳定的OPC接口服务&#xff0c;常年稳定运行&#xff0c;规模可达10万数据…

奇妙的安全旅行之加密算法概述

前言 hi&#xff0c;大家好呀&#xff0c;信息安全作为当前社会中比较重要的一个课题&#xff0c;已经覆盖了人们生活的方方面面&#xff0c;虽然有时候我们可能并没有意识到&#xff0c;其实信息安全防护已经在背后默默的保护我们的信息安全了。例如&#xff0c;当你在互联网…