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

  在产品设计过程中,我们经常会遇到数模转换的应用需求。在本篇种我们就来讨论一下MCP4725单通道数模转换器的驱动设计与实现。

1、功能概述

  MCP4725是一个低功耗,高精度,单通道,12位缓冲电压输出数字到模拟转换器(DAC)与非易失性存储器(EEPROM)。它的板载精度输出放大器允许它实现轨到轨模拟输出摆动。
  DAC输入和配置数据可以被编程到非易失性存储器(EEPROM)由用户使用I2C接口命令。非易失性存储器特性使DAC设备能够在断电时保存DAC输入代码,并且在通电后立即提供DAC输出。当DAC设备被用作网络中其他设备的支持设备时,这个特性非常有用。MCP4725的引脚定义及排布如下:

  MCP4725有一个外部A0地址位选择引脚。这个A0引脚可以绑定到用户应用PCB板的VDD或VSS上。这个引脚被用户用来选择A0地址位。用户可以将这个引脚绑定到VSS(逻辑’ 0 ‘),或VDD(逻辑’ 1 '),或可以由数字逻辑级别主动驱动,如I2C主输出。
  MCP4725的地址字节由两个部分组成,第一部分为4位设备代码,固定设置为1100的,设备代码后面是三位为地址位(A2, A1, A0),如下图所示:

  A2和A1位的选择可由客户提供,作为订购过程的一部分。两位在出厂前设定好,如果客户没有特别要求的话,A2和A1会默认编程为“00”。而A0位则由A0引脚的逻辑状态决定。
  MCP4725设备包括一个上电复位(POR)电路,以确保可靠的上电,以及一个用于EEPROM编程电压的板载电荷泵。DAC引用是直接从VDD驱动的。在down模式下,输出放大器可以配置为已知的低、中或高阻输出负载,如下图。

  MCP472的写命令用于将配置位和DAC输入码加载到DAC寄存器,或写入设备的EEPROM。写命令类型由三个写命令类型位(C2、C1、C0)定义。写命令类型及其作用如下表所示。

2、驱动设计与实现

  在前一节中,我们梳理了MCP4725单通道数模转换器的基本技术参数。在这一节中,我们将依据这些技术参数来设计MCP4725单通道数模转换器的驱动程序。我们依然是基于对象的思想来实现之。

2.1、对象定义

  我们基于对象来实现驱动程序,所以我们就需要先得到对象,在这里我们首先将抽象出MCP4725单通道数模转换器的对象类型。一版来说,对象皆包含属性与操作两个方面的内容。在抽象对象类型的过程中,我们需要分析MCP4725单通道数模转换器都有哪些属性和操作。
  我们先来分析MCP4725单通道数模转换器的对象的属性。每一台I2C从设备都有一个设备地址,这个地址实际上标识了总线上设备的身份,MCP4725亦如此,所以我们将设备地址作为对象的一个属性。对于MCP4725单通道数模转换器,有一个掉电处理模式是需要配置的,为了掌握其配置状态我们将其作为对象的一个属性记录下来。
  接下来分析MCP4725单通道数模转换器的对象的操作。MCP4725单通道数模转换器的基本操作无非就是读写数据,而要实现读和写则依赖于具体的软硬件平台,所以我们将读和写MCP4725单通道数模转换器都作为对象的操作来实现。
  根据上述关于MCP4725单通道数模转换器对象属性和操作的分析,我们可以抽象得到其对象类型如下:

/*定义MCP4725对象类型*/
typedef struct Mcp4725Object {uint8_t devAddress;Mcp4725PDModeType pdMode;void (*Write)(struct Mcp4725Object *mcp,uint8_t *wData, uint16_t wSize);void (*Read)(struct Mcp4725Object *mcp,uint8_t *rData, uint16_t rSize);
}Mcp4725ObjectType;

  抽象了对象类型后就可声明对象变量,可是这个对象变量必须作必要的初始化才能使用。所以我们需要一个初始化函数来对其进行初始化。在此函数中,我们将检测变量的有效性和初始状态赋值,并对设备进行必要的配置。根据这些要求我们设计MCP4725单通道数模转换器的对象初始化函数如下:

/*MCP4725初始化配置*/
void Mcp4725Initialization(Mcp4725ObjectType *mcp,  //MCP4725对象变量uint8_t slaveAddress,    //从站设备的地址Mcp4725PDModeType pdMode,//掉电操作模式Mcp4725Write write,      //写数据函数指针Mcp4725Read read         //读数据函数指针)
{if((mcp==NULL)||(write==NULL)||(read==NULL)){return;}mcp->Write=write;mcp->Read=read;if((slaveAddress==0x60)||(slaveAddress==0x61)){mcp->devAddress=(slaveAddress<<1);}else if((slaveAddress==0xC0)||(slaveAddress==0xC2)){mcp->devAddress=slaveAddress;}else{mcp->devAddress=0x00;}mcp->pdMode=pdMode;}

2.2、对象操作

  有了对象变量,也完成了初始化,那么我们就可以用其来操作MCP4725单通道数模转换器了。所以我们来看看实现对MCP4725单通道数模转换器的读写操作。
首先我们来看看写MCP4725单通道数模转换器的实现。写MCP4725单通道数模转换器有两种模式:快速模式和正常模式。快速模式就是将命令与数据结合在一起,这要只需发送三个字节就可完成写数据的过程。具体的操作时序如下:

  而正常模式则是命令是单独的字节,数据是另外的2个字节,所以正常模式一次发送4个字节才能完成写的过程。正常模式可以操作寄存器也可操作EEPROM,这一点与快速模式是不一样的。具体的操作时序如下:

  根据前面的描述和时序图,我们可以设计写MCP4725单通道数模转换器的函数。下面的函数可以快速模式和普通模式,有命令类型来决定最终的操作方式。

/*设置MCP4725输出*/
void Mcp4725SetDatas(Mcp4725ObjectType *mcp,Mcp4725CommandType cmd,uint16_t data)
{uint8_t wData[3];uint8_t pdMode=0;uint16_t wSize=0;uint8_t command[]={Fast_Mode,Write_DAC_Register,Write_DAC_Register_EEPROM};pdMode=(uint8_t)(mcp->pdMode);if(cmd==Mcp4725_Fast_Mode)  //快速模式{wData[1]=(uint8_t)data;wData[0]=(uint8_t)(data>>8);wData[0]=wData[0]|command[cmd];wData[0]=wData[0]|(pdMode<<4);wSize=2;}else    //普通模式{wData[0]=command[cmd];wData[0]=wData[0]|(pdMode<<1);wData[1]=(uint8_t)(data>>4);wData[2]=(uint8_t)(data<<4);wSize=3;}mcp->Write(mcp,wData,wSize);
}

  MCP4725单通道数模转换器不断可以写数据也可以读数据。读回来的数据包括状态命令字、DAC寄存器数据以及EEPROM数据,总共是5个字节。具体的操作时序如下:

  根据前速的分析以及时序图,我们可以简单实现读操作如下:

/*读取MCP4725数据*/
void Mcp4725GetDatas(Mcp4725ObjectType *mcp,uint8_t *rData)
{mcp->Read(mcp,rData,5);
}

3、驱动的使用

  我们已经实现了MCP4725单通道数模转换器的驱动程序。我们还需要将这一驱动程序实际应用一下以确认驱动程序的正确性。

3.1、声明并初始化对象

  同样,我们先声明一个MCP4725单通道数模转换器对象变量。前面我们已经抽象了对象类型,使用MCP4725单通道数模转换器对象类型声明如下:

Mcp4725ObjectType mcp4725;

  对于这个对象变量,我们还需要使用Mcp4725Initialization函数对它进行初始化才能使用。这个初始化函数有多个输入参数:

Mcp4725ObjectType *mcp,  //MCP4725对象变量
uint8_t slaveAddress,    //从站设备的地址
Mcp4725PDModeType pdMode,//掉电操作模式
Mcp4725Write write,      //写数据函数指针
Mcp4725Read read         //读数据函数指针

  这些参数中,第一个参数是我们要初始化的对象变量,已经在前面声明了。slaveAddress是指MCP4725单通道数模转换器的设备地址。掉电操作模式是枚举类型,根据使用需要选择就可以了。最后两个读写操作函数指针则需要我们实现相应的函数。这两个函数的原型定义如下:

typedef void (*Mcp4725Write)(struct Mcp4725Object *mcp,uint8_t *wData, uint16_t wSize);
typedef void (*Mcp4725Read)(struct Mcp4725Object *mcp,uint8_t *rData, uint16_t rSize);

  读写操作函数的实现与具体的软硬件平台是相关的,这里我们实现STM32F103硬件平台和HAL库的对应函数:

/*通过I2C1端口写MCP4725*/
static void BmcbMcp4725Write(struct Mcp4725Object *mcp,uint8_t *wData, uint16_t wSize)
{HAL_I2C_Master_Transmit(&hi2c1,mcp->devAddress,wData,wSize,1000);
}/*通过I2C1端口读MCP4725*/
static void BmcbMcp4725Read(struct Mcp4725Object *mcp,uint8_t *rData, uint16_t rSize)
{HAL_I2C_Master_Receive(&hi2c1,mcp->devAddress,rData,rSize,1000);
}
有了这些参数后,我们就可以使用这些参数来初始化MCP4725单通道数模转换器的对象变量了。
Mcp4725Initialization(&mcp4725,         //MCP4725对象变量0xC0,             //从站设备的地址MCP4725_Normal,   //掉电操作模式BmcbMcp4725Write, //写数据函数指针BmcbMcp4725Read   //读数据函数指针);

3.2、基于对象进行操作

  关于对象的应用这块,我们将实际工程中的应用代码节选过来。具体很简单就是计算当前应该下发的数字编码并将其下发给MCP4725单通道数模转换器就可以了。

uint16_t code=0;
code=(uint16_t)((aPara.phyPara.presControl/100.0)*4095.0);
Mcp4725SetDatas(&mcp4725,Mcp4725_Write_DAC,code);

4、应用总结

  我们设计并实现了MCP4725单通道数模转换器的驱动程序,而且将其运用到了实际的工程当中,使用情况符合我们的预期。
源码下载:https://github.com/foxclever/ExPeriphDriver

欢迎关注:

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

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

相关文章

如何确保不使用动态内存

在许多嵌入式应用程序中&#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;当你在互联网…

怎么调节电机启动值_开关式智能充电机-全自动充电机-铅酸电池充电机品牌-济南能华...

开关式智能充电机-全自动充电机-铅酸电池充电机品牌-济南能华NHCD系列 全自动智能充电机&#xff0c;可调智能充电机&#xff0c;可调直流充电机&#xff0c;可调全自动充电机 &#xff0c;可调蓄电池充电机 便携式可调智能充电机 便携式全自动充电机 大功率可调充电机 大功率智…

奇妙的安全旅行之MD算法

hi&#xff0c;大家好&#xff0c;今天我们开始介绍消息摘要算法中的MD&#xff08;Message Digest&#xff09;算法&#xff0c;MD算法家族包括&#xff1a;MD2&#xff0c;MD4&#xff0c;MD5&#xff0c;MD算法生成的消息摘长度要都是128位的。 其中MD5算法是消息摘要算法的…

的图层类型有哪些_东莞都市领航平面设计培训班都学习哪些内容?

平面设计的工作稳定性是很高的&#xff0c;经济繁荣时期毫无疑问&#xff0c;即使经济下滑&#xff0c;仍不会有很大影响&#xff0c;以前两年为例&#xff0c;北美的大规模裁员浪潮&#xff0c;给高科技行业带来巨大冲击&#xff0c;放慢了高科技产品的开发速度&#xff0c;当…

dockerfile拉取私库镜像_还在用Alpine作为你Docker的Python开发基础镜像?其实Ubuntu更好一点...

原文转载自「刘悦的技术博客」https://v3u.cn/a_id_173一般情况下&#xff0c;当你想为你的Python开发环境选择一个基础镜像时&#xff0c;大多数人都会选择Alpine&#xff0c;为什么&#xff1f;因为它太小了&#xff0c;仅仅只有 5 MB 左右&#xff08;对比 Ubuntu 系列镜像接…

2020,再见;2021,我来了!

现在是2021年1月16日下午16点33分&#xff0c;星期六。此时北京正在通报昨日新冠肺炎新增病例情况&#xff0c;这种每天戴口罩的鬼日子还不知道什么时候能结束。最近由于天气变冷&#xff0c;病毒更容易存活和传播&#xff0c;最近一个月就突然又变的非常紧张起来了&#xff0c…

cuda tensorflow版本对应_Windows10下安装tensorflow-gpu(2.2.0)安装教程(避坑+保姆式教学)...

本文实现了Windows10下GPU版本的tensorflow2.2.0的安装&#xff0c;用到的软件主要包括&#xff1a;CUDA 10.2 cuDNN Anaconda tensorflow-gpu 2.2.0。&#xff08;注&#xff1a;此教程在Win7环境下也同样适用&#xff01;另附报错缺少cudart64_101.dll的解决办法&#xff…

奇妙的安全旅行之DES算法(二)

hi&#xff0c;大家好&#xff0c;上一节我们详细介绍了对称加密算法DES的基本内容&#xff0c;由于明文的长度不固定&#xff0c;而加密算法只能处理特定长度的一块数据&#xff0c;所以就需要对比较长的明文进行分组后再加密&#xff0c;但是分组后&#xff0c;最后一组的长度…

c++创建虚拟串口_linux虚拟串口控制器驱动实现——适用于无开发板学习串口驱动...

在上一章我们已经说明了uart驱动的开发流程&#xff0c;本章我们就不再介绍uart相关的接口实现&#xff0c;仅通过实现一个虚拟的串口控制器程序&#xff0c;用以说明虚拟串口的开发流程。本次开发的虚拟串口提供的功能如下&#xff1a;提供两个串口实例串口名称的前缀为vttyU为…

奇妙的安全旅行之AES算法

hi&#xff0c;大家好&#xff0c;今天开始我们来介绍一下对称加密算法中的AES算法。 AES简介 AES&#xff08;英语&#xff1a;Advanced Encryption Standard&#xff0c;缩写&#xff1a;AES&#xff09;&#xff0c;即高级加密标准&#xff0c;在密码学中又称Rijndael加密…