外设驱动库开发笔记1:AD56xx系列DAC驱动

DAC在我们的项目中经常使用到,而使用最多的就是AD56xx系列,包括有单通道的AD5662、双通道的AD5623AD5663、以及四通道的AD5624AD5664等。出于方便复用的原因,我们设计并实现AD56xx系列DAC的驱动。

1、功能概述

AD56xx系列DAC属于nanoDAC系列,是低功耗,12位、14位或者16位缓冲电压输出数模转换器(DAC),采用2.7V5.5V单电源供电。AD56xx采用多功能三线式串行接口,能够以最高50 MHz的时钟速率工作,并与标准SPIQSPIMICROWIREDSP接口标准兼容。它内置片内精密输出放大器,能够实现轨到轨输出摆幅。其功能框图如下所示:

AD56xx系列DAC都有一个24位的移位寄存器,所有的操作都是通过写移位寄存器来实现的。对于不同的型号其移位寄存器的各位略有差异。具体如下图所示:

单通道没有通道选择位,命令位只有2位,所以我们的软件实际上就是针对不同的功能需求配置移位寄存器。

2、驱动设计与实现

前面已经说过,对AD56xx的操作,实际就是根据需要配置移位寄存器。接下来我们将在此基础上分析并实现AD56xx系列DAC的驱动。

2.1、对象定义

在使用对象之前,我们需要抽象对象的定义。对于AD56xx系列DAC我们需要定义类型枚举,因为该系列包含有多种DAC模块。此外我们还要定义AD56xx系列DAC的对象类型。

/*定义DAC器件的类型*/
typedef enum AD56xx{
  AD5662=0,
  AD5623=1,
  AD5643=2,
  AD5663=3,
  AD5624=4,
  AD5644=5,
  AD5664=6,
  TypeNumber,
}AD56xxType;

/* 定义AD56XX对象类型 */
typedef struct AD56xxObject {
  AD56xxType objectType;        //DAC的类型
  void (*WriteDataToDAC)(uint8_t *tData,uint16_t tSize);        //向DAC发送数据
  void (*ChipSelcet)(AD56xxCSType cs);     //片选信号
}AD56xxObjectType;

我们抽象了对象,在我们使用这个对象定义声明了一个具体的对象时,它只是一个代表对象的变量,我们需要对它进行初始化才可使用。于是我们定义初始化对象函数。

/* 初始化AD56xx对象 */
void AD56xxInitialization(AD56xxObjectType *dacObj,AD56xxType objectType,AD56xxWrite write,AD56xxChipSelcet cs)
{
  if((dacObj==NULL)||(write==NULL)||(cs==NULL))
  {
     return;
  }
     
  if(objectType<TypeNumber)
  {
    dacObj->objectType=objectType;
  }
     
  dacObj->WriteDataToDAC=write;
  dacObj->ChipSelcet=cs;
}

2.2、对象操作

我们已经将AD56xx抽象为对象,那么对AD56xx的操作都转化为对某一个对象的操作。接下来我们来实现对象的操作函数。

2.2.1、软件复位

软件复位也是通过操作输入移位寄存器来实现的。命令位的定义没有变化,数据段的最后一位作为软件复位的模式设定,其它位无效。最后一位为0时,会清除DAC寄存器和输入寄存器,而最后一位为1时清除掉全部寄存器。最后一位为1时,实际就是上电复位模式。输入移位寄存器的数据格式如下:

其软件实现如下:

/* 对AD56xx进行软件复位 */
void Ad56xxSoftwareReset(AD56xxObjectType *dacObj,AD56xxResetType resetMode)
{
  uint32_t inputShiftData=0;
 
  if(resetMode==ResetSoftware)
  {
    inputShiftData=RESET|Register_Reset_Software;
  }
 
  if(resetMode==ResetPoweron)
  {
    inputShiftData=RESET|Register_Reset_Poweron;
  }

  uint8_t txData[3];
  txData[0]=inputShiftData>>16;
  txData[1]=inputShiftData>>8;
  txData[2]=inputShiftData;
 
  dacObj->ChipSelcet(AD56xxCS_Enable);
  dacObj->WriteDataToDAC(txData,3);
  dacObj->ChipSelcet(AD56xxCS_Disable);
}

2.2.2、上电复位

上电复位也是通过操作输入移位寄存器来实现的。命令位的定义没有变化,数据段的DB5DB4定义掉电的模式,而DB1DB0定义操作的通道。输入移位寄存器的数据格式如下:

其软件实现如下:

/* 设置AD56xx上电/掉电工作模式 */
void Ad56xxPowerUpDownMode(AD56xxObjectType *dacObj,AD56xxChannelType channel,AD56xxPowerdownType powerdownType)
{
  uint32_t inputShiftData=0;
  uint32_t pdc=0;
  uint32_t pdm=0;
  uint32_t cmd=Power_Down;
  
  uint32_t pdChannel[]={DAC_A,DAC_B,DAC_C,DAC_D,DAC_ALL,DAC_None};
 
  pdc=pdChannel[channel];
 
  uint32_t pdMode[]={Normal_Operation,_1K_GND,_100K_GND,Three_State};
 
  pdm=pdMode[powerdownType];
 
  if(dacObj->objectType==AD5662)
  {
    pdc=DAC_None;
    pdm=(pdm<<12);
    cmd=Write_to_Input_Register;
  }
 
  inputShiftData=cmd|pdc|pdm;
  
  uint8_t txData[3];
  txData[0]=inputShiftData>>16;
  txData[1]=inputShiftData>>8;
  txData[2]=inputShiftData;
 
  dacObj->ChipSelcet(AD56xxCS_Enable);
  dacObj->WriteDataToDAC(txData,3);
  dacObj->ChipSelcet(AD56xxCS_Disable);
}

2.2.3LDAC功能

除去单通道的设备外,其他的AD56xx设备都具有LDAC操作功能。而对LDAC操作的寄存器设置如下图所示:

其软件实现如下:

/* 设置AD56xx及同类器件LDAC功能 */
void SetAd56xxLdacFunction(AD56xxObjectType *dacObj,AD56xxChannelType channel)
{
  uint32_t inputShiftData=0;
 
  uint32_t pdChannel[]={DAC_A,DAC_B,DAC_C,DAC_D,DAC_ALL,DAC_None};
 
  inputShiftData=pdChannel[channel];
 
  inputShiftData=inputShiftData|LDAC_Register_Setup;
 
  uint8_t txData[3];
  txData[0]=(uint8_t)(inputShiftData>>16);
  txData[1]=(uint8_t)(inputShiftData>>8);
  txData[2]=(uint8_t)inputShiftData;
 
  dacObj->ChipSelcet(AD56xxCS_Enable);
  dacObj->WriteDataToDAC(txData,3);
  dacObj->ChipSelcet(AD56xxCS_Disable);
}

2.2.4、内部基准电压源设置

有一些型号以R结尾的AD56xx器件是包含有内部参考电源的。片内基准电压源在上电时默认关闭。通过设置控制寄存器中的软件可编程位DB0,可以开启或关闭此基准电压源。 具体的寄存器设置如下图所示:

其软件实现如下:

/* 开启或关闭内部参考电压源 */
void SetInternalReference(AD56xxObjectType *dacObj,AD56xxRefType ref)
{
  uint32_t inputShiftData=0;
      
  inputShiftData=Reference_Set;
      
  if(ref==AD56xxRef_ON)
  {
     inputShiftData=inputShiftData|Reference_ON;
  }
      
  uint8_t txData[3];
  txData[0]=(uint8_t)(inputShiftData>>16);
  txData[1]=(uint8_t)(inputShiftData>>8);
  txData[2]=(uint8_t)inputShiftData;
 
  dacObj->ChipSelcet(AD56xxCS_Enable);
  dacObj->WriteDataToDAC(txData,3);
  dacObj->ChipSelcet(AD56xxCS_Disable);
}

2.2.5、输出操作

对各输出通道值的操作也是通过输入移位寄存器来完成。其数据格式如前面输入移位寄存器的介绍。后16位是数据(0-65535),然后是3位地址和3位命令。通讯的时序图如下所示:

其软件实现如下:

/* 设置DA通道的值 */
void SetAD56xxChannelValue(AD56xxObjectType *dacObj,AD56xxChannelType channel,uint16_t data)
{
  uint32_t inputShiftData=0;
  uint32_t dac=0;
  uint32_t cmd=WriteTo_Update_DAC_Channel;
 
  uint32_t dacChannel[]={DAC_Channel_A,DAC_Channel_B,DAC_Channel_C,DAC_Channel_D,DAC_Channel_ALL};
 
  uint32_t shiftV[]={0,4,2,0,4,0};
 
  if(channel>=ChannelNone)
  {
    return;
  }
 
  dac=dacChannel[channel];
 
  if(dacObj->objectType==AD5662)
  {
    dac=DAC_Channel_A;
    cmd=Write_to_Input_Register;
  }

  inputShiftData=dac|cmd|(data<<shiftV[dacObj->objectType]);
  
  uint8_t txData[3];
  txData[0]=(uint8_t)(inputShiftData>>16);
  txData[1]=(uint8_t)(inputShiftData>>8);
  txData[2]=(uint8_t)inputShiftData;
 
  dacObj->ChipSelcet(AD56xxCS_Enable);
  dacObj->WriteDataToDAC(txData,3);
  dacObj->ChipSelcet(AD56xxCS_Disable);
}

3、驱动的使用

我们已经实现了AD56xx系列DAC的驱动,接下来我们就可以使用我们的这个驱动实现我们的应用了。

3.1、声明并初始化对象

首先需要使用AD56xx对象类型AD56xxObjectType声明一个对象变量。具体声明形式如下:AD56xxObjectType ad56xx;

对象变量需要使用AD56xxInitialization函数进行初始化。这个函数的参数除了对象变量外还有对象类型以及写数据操作和片选操作2个函数指针。在调用初始化函数之前必须准备好这些参数。所以我们需要按如下类型定义相关函数。

/* 向DAC发送数据函数指针类型 */
typedef void (*AD56xxWrite)(uint8_t *tData,uint16_t tSize);

/* 片选操作函数指针类型 */
typedef void (*AD56xxChipSelcet)(AD56xxCSType cs);

我们实现这几个函数并将函数指针作为参数传递给初始化函数。初始化函数的调用样式如下:

AD56xxInitialization(&ad56xxobjectTypewritecs);

后两个参数即是上面定义的2个函数的函数指针。这两个函数根据具体的硬件电路来实现。第二个参数为对象类型,为AD56xxType枚举类型。

3.2、基于对象进行操作

初始化完成后就可以操作对象了。对AD56xx系列DAC对象的操作包括:软件复位操作,上下电模式控制,LDAC控制,参考电压操作以及输出控制。下面将调用驱动函数实现相应的应用。

AD56xx系列DAC拥有14个通道,所以我们需要为操作制定通道。还有向该通道设定的数据,由于AD56xx系列DAC1216位,所以我们要发送一个不超过16位的无符号整数。有了这两个参数我们就可以调用SetAD56xxChannelValue函数为AD56xx系列DAC设定输出了。

SetAD56xxChannelValue(&ad56xxchanneldata);

第二个参数为设定的通道,是一个AD56xxChannelType类型的枚举,以此决定我们当前操作的是哪一个通道。而其它的函数:

/*设置AD56xx上电/掉电工作模式*/
void Ad56xxPowerUpDownMode(AD56xxObjectType *dacObj,AD56xxChannelType channel,AD56xxPowerdownType powerdownType);

/*对AD56xx进行软件复位*/
void Ad56xxSoftwareReset(AD56xxObjectType *dacObj,AD56xxResetType resetMode);

/* 开启或关闭内部参考电压源 */
void SetInternalReference(AD56xxObjectType *dacObj,AD56xxRefType ref);

/*设置AD56xx及同类器件LDAC功能*/
void SetAd56xxLdacFunction(AD56xxObjectType *dacObj,AD56xxChannelType channel);

其调用方式是类似的。需要指出的是SetInternalReference函数,只有具有内部参考电源的器件调用这个函数才有作用。

4、应用总结

我们使用AD56xx系列DAC实现过多种应用,都是基于我们的驱动开发的。使用的结果基本都与我们的预期一样。

需要注意对象的类型,特别是AD5662的移位寄存器有很大区别。虽然驱动在这一方面作了处理,但是基于初始化时配置的类型执行的。所以在调用初始化函数初始化对象时一定要传递正确的类型。

​源码公布到GitHUB:https://github.com/foxclever/ExPeriphDriver

欢迎关注:

  • 10
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
图1所示电路是一种全功能、灵活、可编程的模拟输出解决方案,它满足可编程逻辑控制器(PLC)和分布式控制系统(DCS)应用的大部分要求。AD5662低功耗(0.75 mW @ 5 V)、轨到轨输出、16位nanoDAC:registered: 转换器和 AD5750 工业电流/电压输出驱动器的基准电压要求和输入输出电压完全匹配。ADR444 低漂移(B级最大为3 ppm/°C)、高初始精度(B级最大为0.04%)和低噪声(1.8 μV p-p典型值,0.1 Hz至10 Hz)特性,能够同时为AD5750和AD5662提供基准电压,确保超低噪声、高精度、低温漂。这种电路具有16位分辨率、无失码、0.05%线性度和 低于0.2%的总输出误差,提供所有典型电压和电流输出范围。 图1 该电路还具有一些支持工业应用的重要特性,如片内输出故障检测和保护(短路、欠压输出、开路电流输出和过温)、用于防止分组错误(PEC)的CRC 校验以及灵活的上电选项等,非常适合构建鲁棒的工业控制系统。在大批量生产中,它无需外部精密电阻或校准程序就能保持一致的性能,因而是PLC或DCS模 块的理想选择。 AD5750/AD5750-1 均为单通道、低成本、精密电压/电流输出驱动器,设计用于满足工业过程控制应用的需要。电压输出范围可以针对PLC和DCS应用的标准输出范围进行编 程:0 V至5 V、0 V至10 V、−5 V至+5 V和−10 V至+10 V。针对标准范围,还提供了20%的超范围设置,由此便可得到下列选项:0 V至6 V、0 V至12 V、-6 V至+6 V和-12 V至+12 V。 电流输出通过单独的引脚提供,可以编程为以下范围:4 mA至20 mA、0 mA至20 mA、−20 mA至+20 mA、0 mA至24 mA和−24 mA至+24 mA。单极性范围具有2%的超范围设置。由于AD5750/AD5750-1的电流输出既可以是源电流,也可以是吸电流,因此它能与广泛的传感器或执行器 接口。如果需要,可以将电压和电流输出引脚连在一起,以便将终端系统配置为单通道输出。 AD5662 是一款单通道、低成本、低功耗、轨到轨电压缓冲输出的nanoDAC:registered:器件,它能在0.75 V至VVD电源的宽基准电压范围内保证±1 LSB DNL,所以AD5750和AD5662可以由ADR444提 供的4.096 V公共基准电压源来供电。整个系统将受益于ADR444的超低噪声和低温度系数。ADR44x系列基准电压源具有源电流和吸电流能力,非常适合驱动转换器 的基准电压或电源输入。AD5662还内置一个上电复位电路,确保DAC输出上电至中间量程或零电平并保持该电平,直到执行一次有效的写操作为止。 用于PLC和DCS应用的器件所需的ESD保护和过压保护一般远高于形式上的推荐要求。AD5750的各引脚内置ESD保护二极管,可以防止3 kV瞬变(人体模型)损害器件。但是,工业控制环境可能会使I/O电路遭受高得多的瞬变。EVAL-CN0202-SDPZ电路板内置外部30 V/600 W瞬变电压抑制器(TVS)、50 mA/30 V自恢复保险丝(PolySwitch)和肖特基功率二极管,以提供更高电压的ESD保护、50 mA过流保护和30 V过压保护。 附件内容包括: AD5662开发板原理图、PCB、集成件,用PADS软件打开; AD5662开发板bom材料清单;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值