新闻详情

新闻详情

首页 / 资讯中心 / 详情

AD7745/AD7746电容检测芯片C51驱动详解:I2C与寄存器配置

发布时间:2026/9/13 21:06:58来源:尧图网络
AD7745/AD7746电容检测芯片C51驱动详解:I2C与寄存器配置
简介一套基于C51单片机的AD7745/AD7746电容检测芯片I2C接口驱动源码包适用于单片机、嵌入式硬件及STM32/ARM平台开发者可帮助快速掌握通过I2C总线完成芯片初始化、数据读取与错误处理的实现方法。AD7745/AD7746是高精度电容检测ADC内置信号调理与模数转换电路AD7745偏重单通道测量AD7746支持多通道输入源码包中的AD7745dianrong.c和main.c文件清晰展示了驱动编写的关键环节。压缩包共13个文件包括C源码、Keil工程文件ewd/ewp/eww及调试配置文件等整体仅31KB目录结构紧凑便于查阅和移植。目前已有995人学习对电容传感、液位检测等应用场景具有直接参考价值。通过Keil工程可直接编译调试驱动逻辑也可在STM32/ARM等平台复用工程内包含调试输出目录方便定位问题与验证数据是理解I2C通信协议与电容检测芯片驱动开发的实用范例。1. 从 I2C 接口驱动包开始先分清 AD7745 的“读”与“配”拿到一份标题里带着“I2C 接口 AD7745/AD7746 电容检测芯片 C51 单片机驱动程序源码”的压缩包先别急着把文件全塞进 Keil C51 工程。AD7745 和 AD7746 这对芯片把模拟端的激励、采样、滤波都做完了C51 单片机真正要处理的只有两条 I2C 的时序和几组寄存器配置多数工程卡住的原因不在芯片本身而在驱动源码里地址字节、ACK 判断和 CAPDAC 校准这三件事没对齐。下面按“测量链路 → 底层 I2C 驱动 → 寄存器配置与校准 → 验证手段”的顺序把这份源码里必须具备的模块拆开讲适合正在做微小电容检测、液位或介电常数测量的开发者直接照着移植。2. AD7745/AD7746 的 24 位电容测量链路与 I2C 寄存器映射2.1 24 位 Σ-Δ 电容前端主控只负责读结果电容检测芯片的价值在于把“电容变化”这件事变成了“寄存器数值”。AD7745 内部有激励源和一片高精度 Σ-Δ 调制器EXC 引脚输出激励信号给传感器传感器电容变化会改变调制器输入电荷最终以 24 位二进制补码形式输出。默认满量程大约是 ±4.096 pF灵敏度可以到几十 fF 甚至更低。这个 ±4.096 pF 经常被误解为“传感器只能接 4 pF”。实际它指的是相对芯片内部零点的可测量变化范围传感器本身的静态电容可以远大于 4 pF超出量程的部分通过芯片内部的 CAPDAC 在数字上抵扣。AD7745 是单通道型号AD7746 是双通道型号两者的寄存器布局基本一致所以 C51 驱动源码通常会把两个型号合并成一份文件只通过一个宏或一个通道选择位区分。2.2 I2C 从机地址由 ADDR0/ADDR1 引脚决定别只认 0x90不少源码包里的地址被写死在宏里换一块板子就采集不到数据。AD7745/AD7746 的 7 位 I2C 地址由 ADDR0 和 ADDR1 两个引脚的电平共同决定常见的组合与对应的 8 位读写地址如下ADDR1ADDR07 位地址写地址读地址低低0x480x900x91低高0x490x920x93高低0x4A0x940x95高高0x4B0x960x97驱动代码里应把写地址和读地址分别定义成宏而不是在函数里到处写数字。改板子时只需检查 ADDR0/ADDR1改两行宏即可。2.3 寄存器映射数据读取与配置写入的最小集合AD7745 的寄存器不复杂驱动源码里必须要认识的只有下面这几块地址寄存器作用说明0x00STATUS 状态寄存器转换完成位、通道状态等0x01~0x03CAP DATA 电容数据24 位二进制补码高字节在前0x06CAP SETUP 电容控制通道使能、通道选择、斩波模式0x07转换时间/采样配置决定电容转换时间和温度转换时间0x08CAPDAC 标定 DAC抵消传感器静态电容和 PCB 寄生电容0x09~0x0BVT DATA 温度/电压数据24 位结果读取方式与电容数据相同读取电容数据时从 0x01 开始连续读 3 个字节高字节在前。0x06 的 CAPEN 位负责打开电容通道0x08 的 CAPDAC 决定是否启用内部标定 DAC。调试阶段先把 0x08 写成 0关闭 CAPDAC直接读原始偏移。2.4 AD7745 与 AD7746 在驱动代码里的实际差异两个芯片的 I2C 时序完全一致连寄存器地址都相同。唯一差异在于 AD7746 有 CAP2 通道需要在 CAP SETUP 寄存器的通道选择位里切换。驱动源码中常见的做法是写一个统一的初始化函数把通道作为参数传进去而不是为 AD7745 和 AD7746 各维护一套函数/* 通道参数示意0 对应 CAP11 对应 CAP2 */ unsigned char AD7746_SetChannel(unsigned char ch) { unsigned char cap_setup; if (ch 1) return 0; cap_setup 0x01; /* 先只打开 CAPEN */ if (ch 1) cap_setup | 0x04; /* 合并通道选择位0x04 以手册为准 */ return AD7745_WriteReg(0x06, cap_setup); }这里把通道选择位的组合值留给你手上手册去核对因为不同批次芯片的保留位定义有差异。代码结构本身可以直接用写入 0x06 前先读回旧值再修改对应位比直接整体覆写更安全。如果只想先跑通基本测量用 0x06 0x01 让 CAPEN 置 1其余位保持默认通常就能在 STATUS 里看到转换完成标志。3. C51 下 I2C 底层驱动的完整实现上拉、时序与 ACK 判断3.1 准双向口和开漏引脚的配合读之前先写 1C51 的 I/O 口属于准双向口输出 0 时引脚被强下拉输出 1 时只靠内部弱上拉拉高。AD7745 的 I2C 引脚是开漏结构SCL 和 SDA 必须外接上拉电阻才能产生高电平。100 kHz 速率下通常用 10 kΩ 上拉400 kHz 时建议换成 4.7 kΩ如果总线电容偏大上升沿会变缓此时要么降速要么换更小的上拉。总线电容推荐上拉电阻可用速率小于 100 pF10 kΩ100 kHz100~200 pF4.7 kΩ100~400 kHz大于 200 pF2.2 kΩ 或降速建议 100 kHzC51 读 SDA 之前必须执行I2C_SDA 1;让引脚先释放到弱上拉状态再去读外部设备真正拉出的电平。这个细节是从 STM32 等真开漏模式移植到 C51 时最容易踩的坑。3.2 起始与停止条件SCL 高电平时切换 SDAI2C 的起始条件是 SCL 为高电平期间 SDA 由 1 变 0停止条件是 SCL 为高电平期间 SDA 由 0 变 1。C51 实现如下sbit I2C_SCL P2^1; sbit I2C_SDA P2^0; #define I2C_DELAY() { _nop_(); _nop_(); _nop_(); } void I2C_Start(void) { I2C_SDA 1; I2C_SCL 1; I2C_DELAY(); I2C_SDA 0; /* SCL 高电平期间 SDA 由 1 变 0 */ I2C_DELAY(); I2C_SCL 0; } void I2C_Stop(void) { I2C_SDA 0; I2C_SCL 1; I2C_DELAY(); I2C_SDA 1; /* SCL 高电平期间 SDA 由 0 变 1 */ }I2C_DELAY宏的位置决定 I2C 总线速率。12 MHz 晶振下三个_nop_()大约是 3 μs整个位周期接近 6 μs对应速率在 100 kHz 左右。如果用的是 STC 的 1T 单片机执行速度更快延时循环次数要适当增加否则总线速率会超出 AD7745 的 400 kHz 上限。3.3 写字节与读字节从机应答落在第 9 个时钟主机写数据时每发完 8 位从机会在第 9 个时钟把 SDA 拉低表示 ACK主机读数据时主机自己决定第 9 个时钟回 ACK 还是 NACK。C51 的完整读写函数如下bit I2C_WriteByte(unsigned char dat) { unsigned char i; for (i 0; i 8; i) { I2C_SDA (dat 0x80) ? 1 : 0; dat 1; I2C_DELAY(); I2C_SCL 1; I2C_DELAY(); I2C_SCL 0; } I2C_SDA 1; /* 释放 SDA准备接收从机应答 */ I2C_DELAY(); I2C_SCL 1; I2C_DELAY(); bit ack I2C_SDA; /* 从机应答为低电平 */ I2C_SCL 0; return (ack 0) ? 1 : 0; } unsigned char I2C_ReadByte(bit ack) { unsigned char i, dat 0; I2C_SDA 1; /* 准双向口读前必须先写 1 */ for (i 0; i 8; i) { dat 1; I2C_SCL 1; I2C_DELAY(); if (I2C_SDA) dat | 0x01; I2C_SCL 0; I2C_DELAY(); } I2C_SDA ack ? 0 : 1; /* 主机应答ack1 拉低ack0 释放 */ I2C_DELAY(); I2C_SCL 1; I2C_DELAY(); I2C_SCL 0; I2C_SDA 1; return dat; }I2C_WriteByte的返回值含义是“是否收到从机 ACK”。驱动源码里常见的if (!I2C_WriteByte(...))意思是写地址或写数据后如果收到 NACK直接中止本次通信。读操作则相反I2C_ReadByte(1)表示主机回 ACK告诉从机继续发下一字节I2C_ReadByte(0)表示主机回 NACK告诉从机这是最后一个字节。3.4 ACK 方向最容易写反的位置主读的最后一位主写模式下每个字节的 ACK 都是从机给主机主读模式下第 9 个时钟的 ACK 由主机给从机。很多移植不成功的源码问题就出在读数据时所有字节都回 ACK从机以为主机还要继续读下一帧数据从一开始就错位。读多字节数据的标准动作是前 N-1 个字节回 ACK最后一个字节回 NACK然后立刻产生停止条件。这个 NACK 的作用是明确告知从机释放 SDA避免总线被从机继续占用。C51 工程里如果发现读回来的数据每次都在同一位置多移位优先检查的就是这段 ACK/NACK 逻辑。4. AD7745 寄存器配置与 CAPDAC 校准24 位原始数据换算皮法4.1 最小配置序列先打开电容通道再确认状态寄存器寄存器读写函数是驱动包的核心先确保它能正确工作#define AD7745_ADDR_W 0x90 #define AD7745_ADDR_R 0x91 unsigned char AD7745_WriteReg(unsigned char reg, unsigned char val) { I2C_Start(); if (!I2C_WriteByte(AD7745_ADDR_W)) return 0; if (!I2C_WriteByte(reg)) return 0; if (!I2C_WriteByte(val)) return 0; I2C_Stop(); return 1; } unsigned char AD7745_ReadReg(unsigned char reg) { unsigned char val; I2C_Start(); I2C_WriteByte(AD7745_ADDR_W); I2C_WriteByte(reg); I2C_Start(); /* 重复起始位 */ I2C_WriteByte(AD7745_ADDR_R); val I2C_ReadByte(0); /* 单字节读主机直接回 NACK */ I2C_Stop(); return val; }初始化时不要一次把 0x06、0x07、0x08 的网上例程值整段照搬因为 0x07 的转换时间位在不同手册上定义不完全一致。最稳妥的做法是先只打开 CAPENvoid AD7745_Init(void) { AD7745_WriteReg(0x06, 0x01); /* CAPEN 置 1其余位保持默认 */ AD7745_WriteReg(0x08, 0x00); /* 先关闭 CAPDAC读原始偏移 */ }0x07 的转换时间配置建议从手册里把“电容转换时间”和“连续转换模式”对应的位组合出来组合成一个宏放在头文件。找不到依据的值不要硬抄写错后最典型的现象是 STATUS 的转换完成位长期不变主程序一直停在等待循环里。4.2 读 24 位电容数据重复起始位、符号扩展与皮法换算AD7745 的电容数据是 24 位二进制补码从 0x01 开始连续读 3 字节long AD7745_ReadCap(void) { unsigned long raw 0; I2C_Start(); I2C_WriteByte(AD7745_ADDR_W); I2C_WriteByte(0x01); /* 指向电容数据高字节 */ I2C_Start(); /* 重复起始位切换到读方向 */ I2C_WriteByte(AD7745_ADDR_R); raw (unsigned long)I2C_ReadByte(1) 16; /* 高字节回 ACK */ raw | (unsigned long)I2C_ReadByte(1) 8; /* 中字节回 ACK */ raw | (unsigned long)I2C_ReadByte(0); /* 低字节回 NACK */ I2C_Stop(); if (raw 0x800000) raw | 0xFF000000; /* 24 位补码扩展为 32 位 */ return (long)raw; } float CapToPf(long code) { return (float)code * 4.096f / 8388608.0f; }I2C_ReadByte(1)对应 ACKI2C_ReadByte(0)对应 NACK。如果你把读函数改成I2C_ReadByte(1)连续读 4 次会把 0x04 地址的内容也读回来数据整体错位。符号扩展那一步不能省否则负的电容变化会被当成接近 16 百万的大正数换算出来的皮法值完全错误。4.3 CAPDAC 两步校准把传感器静态电容抵扣掉传感器一接上读到的值通常是正的满量程偏移因为 PCB 走线、焊盘、传感器自身静态电容全都在输入回路里。CAPDAC 的作用就是在数字域把这些电容扣掉让目标变化量落在量程中间。校准步骤按下面做关闭 CAPDAC即 0x08 写 0。在目标传感器正常连接的条件下连续读 8 次电容数据取平均值记为 C_off单位 pF。打开手册找到 CAPDAC 的 LSB 值把 C_off 除以这个 LSB得到要写入 0x08 的 DAC 码。把 DAC 码连同 CAPDAC 使能位一起写回 0x08。完成后重新读数理想情况下应该接近 0。如果读数从正满量程直接翻到负满量程说明 CAPDAC 的方向位反了切换方向后重新校准。注意校准必须在传感器连接状态下做不能拿空载值代替因为寄生电容来源包括整个输入回路。4.4 温度数据与温漂补偿的工程取舍AD7745 内置温度传感器数据在 0x09~0x0B读取方式和电容数据完全一致。温度数据适合做周期性的温漂补偿而不是每帧都读。芯片内部电容转换和温度转换共享资源频繁读温度会占用转换周期导致电容数据的更新率下降。工程上常见的做法是每隔几十秒读一次温度计算一次补偿系数叠加到电容测量结果上。对液位这类应用温漂补偿通常用一次线性修正就够对材料检测这类对绝对精度要求更高的场景需要先在不同温度点标定几组数据再做个分段线性表。5. 验证 AD7745 驱动的 3 个检查点地址、RDY 与双通道切换5.1 用逻辑分析仪确认 0x90 和 0x91 后面的应答调试 I2C 驱动最直接的工具永远是逻辑分析仪不需要多贵采样率大于 2 MHz 就够。抓一次初始化过程看四件事起始位置是否正确、0x90 后有没有 ACK、寄存器地址字节后有没有 ACK、重复起始后 0x91 后有没有 ACK。如果 0x90 发出去后从机没有拉低 SDA说明地址不对。此时不要改代码先量 ADDR0 和 ADDR1 两个引脚的实际电平再按章节 2.2 的表格核对地址。逻辑分析仪上会看到 0x90 后面跟着的是一段高电平这一眼就能断定是地址问题比反复怀疑时序要快得多。5.2 STATUS 轮询不要用固定延时替代转换是否完成以 STATUS 寄存器为准。驱动源码里如果写死延时等待换一片芯片或调整转换速率后代码就会在错误的时间点读数据。轮询写法如下unsigned char status; do { status AD7745_ReadReg(0x00); } while ((status 0x01) 0); /* 0x01 位是否有效以手册为准 */注意 AD7745 的状态位在部分手册里是低有效在另一些版本里是高有效判断条件必须和你手上手册一致。只要 STATUS 轮询能稳定退出读数据时机的正确性就由芯片自己保证了不再依赖主频和延时参数。5.3 AD7746 双通道切换的推荐顺序AD7746 在两个通道之间切换时说复杂不复杂但顺序不能错。正确的切换步骤是把 CAP SETUP 的 CAPEN 位清零停掉当前通道。改写通道选择位指向 CAP2 或 CAP1。重新置位 CAPEN。等待约 200 μs再轮询 STATUS。确认转换完成后才开始读电容数据。如果跳过第一步直接改通道位读取到的数据可能还是上一个通道的残余值。把这三步封装成一个AD7746_SelectChannel函数底层驱动源码里就只有一个入口应用层调起来不会乱。把这个检查点过完那份 i2c_ad7745.c 里的地址宏、通道位和轮询逻辑就可以直接复用到下一块板子上。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Ubuntu 20.04:无人机开发不可绕过的Linux工程基线 2026/9/13 22:01:05

Ubuntu 20.04:无人机开发不可绕过的Linux工程基线

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
企业级RAG知识库实战:从文档到精准问答的工业流水线 2026/9/13 22:01:05

企业级RAG知识库实战:从文档到精准问答的工业流水线

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
免费远程桌面方案实战:P2P直连与串流技术全解析 2026/9/13 22:01:05

免费远程桌面方案实战:P2P直连与串流技术全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Mastra Factory 的 factory-plan 技能:为工作项产出可验证的分阶段实施计划 2026/9/13 22:01:05

Mastra Factory 的 factory-plan 技能:为工作项产出可验证的分阶段实施计划

Mastra Factory 的 factory-plan 技能:为工作项产出可验证的分阶段实施计划 【免费下载链接】mastra Mastra is the modern TypeScript framework for AI-powered applications and agents. 项目地址: https://gitcode.com/GitHub_Trending/ma/mastra 导读 …

阅读更多 →
工业紧凑型线缆组件设计与选型实战指南 2026/9/13 22:01:05

工业紧凑型线缆组件设计与选型实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
C语言流程控制:从基础到高级应用 2026/9/13 21:58:04

C语言流程控制:从基础到高级应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞