当前位置: 首页 > news >正文

【学习笔记】AD7708/18(1)-理解官网的参考代码

文章目录

  • 参考教程
  • AD7708 概述
  • AD7708 特性
  • 引脚布局
  • 参考教程1
    • 代码
      • SPI通信函数详解:
      • 关键设计思想:

背景:需要用到AD芯片,为了学习使用它,从官网找到了通过8051单片机控制它的参考代码。本篇主要是尝试理解参考教程1中的文件。

参考教程

教程1
analog-ad7718中的AD7718参考代码
教程2
MSP430程序库<六>通过SPI操作AD7708
教程3
AD7708-7718寄存器(中文)

AD7708 概述

AD7708、AD7718是适合低频测量应用的完整模拟前端。AD7718内置一个含PGA的24位Σ-Δ ADC,可配置为4/5个全差分输入通道或8/10个伪差分输入通道。该器件上的两个引脚可配置为模拟输入或基准电压输入。AD7708是AD7718的16位版本。利用这些ADC,可以直接转换20mV至2.56V范围的输入信号,支持传感器信号直接输入,无需进行信号调理。

AD7708 特性

8/10通道、高分辨率Σ-Δ ADC
16位分辨率
出厂校准
单转换周期设置
可编程增益前端
50 Hz、60 Hz同时抑制
VREF Select ™ 提供绝对测量和比率测量能力
可针对模拟性能(CHOP‾=0\overline{CHOP} = 0CHOP=0
或通道吞吐量(CHOP‾=1\overline{CHOP} = 1CHOP=1)优化操作

引脚布局

在这里插入图片描述

在这里插入图片描述
模拟输入通道1.可编程增益模拟输入,与AINCOM配合使用时可用作伪差分输入,与AIN2配合使用时可用作全差分输入对的正输入。(参见ADC控制寄存器部分。)
模拟输入通道3。可编程增益模拟输入,与AINCOM配合使用时可用作伪差分输入,与AIN4配合使用时可用作全差分输入对的正输入。(参见ADC控制寄存器部分。)

在这里插入图片描述

参考教程1

代码

/*********************************************************************Author        : ADI - CAST            Date          : September 2003File          : AD7718.cHardware      : ADuC832Description   :*********************************************************************/
/******************************************************************
DEFINE CONTROL PINS OF ADUC832 FOR THE PURPOSE OF AD7718 CONTROL.
Customers should define the pins according to their design.
If P0 is used as the control port, pull-up resistors should be added to each pin of P0.
******************************************************************/
#include<stdio.h>
#include<aduc832.h>sbit CS=0x085;
sbit DIN=0x0B4;
sbit DOUT=0x0B5;
sbit DRDY=0x0B3;
sbit RESET=0x084;
sbit SCLOCK=0x0A7;
int sig;
void int0_int() interrupt 0{sig=0;return;   }
void writetoreg(unsigned char);
void readfromreg(int);
void read(int);
void main()
{int tim;/* Set up UART */
T3CON = 0x082;
T3FD = 0x02D;
SCON   = 0x052;tim=1000;
/* PRECONFIGURE...*/
RESET=0;
while(tim--);
RESET=1;
SCLOCK=1;
DIN=1;
DOUT=1;
CS=1;
DRDY=1;
printf("\n");
writetoreg(0x03); //write to communication register. The next step is writing to FILTER REGISTER
writetoreg(0x45); //set the FILTER register
writetoreg(0x02); //write to communication register. The next step is writing to ADC CONTROLO register
writetoreg(0x0F); //unipolar,2.56V input channel AIN1-AINCOM
IT0=1;EA=1;EX0=1;
sig=1;
while(sig);
writetoreg(0x01);//write to communication register. The next step is writing to MODE register
writetoreg(0x06);//system zero-scale calibration
while(DRDY);
printf("system zero-scale calibration finished.\n");
sig=1;
while(sig);writetoreg(0x01);//write to communication register. The next step is writing to MODE register
writetoreg(0x07);//system full-scale calibrationwhile(DRDY);
printf("system full-scale calibration finished.\n");sig=1;
while(sig);writetoreg(0x01);//writing to communication register, the next step is write to MODE register
writetoreg(0x03);//continuous conversion mode
writetoreg(0x40); //read from status
readfromreg(8);
printf("\n");
writetoreg(0x41); //read from mode
readfromreg(8);
printf("\n");
writetoreg(0x42); //read from adc control
readfromreg(8);
printf("\n");
writetoreg(0x43); //read from filter
readfromreg(8);
printf("\n");
writetoreg(0x45);//read from offset register
readfromreg(24);
printf("\n");
writetoreg(0x46);//read from gain register
readfromreg(24);
printf("\n");read(200);
}void writetoreg(byteword)	 //The subroutine write byteword to the corresponding registers of AD7709
unsigned char byteword;{
unsigned char temp;
int i;
CS=0;
temp=0x80;
for(i=0;i<8;i++){if((temp&byteword)==0)DIN=0;else DIN=1;SCLOCK=0;SCLOCK=1;temp=temp>>1;}
CS=1;
}void readfromreg(bytenumber)	//The subroutine read from the corresponding register 
int bytenumber;
{int j;unsigned char temp1;CS=0;temp1=0x00;for(j=0;j<bytenumber;j++){SCLOCK=0;SCLOCK=1;if(DOUT==0)temp1=temp1<<1;else{temp1=temp1<<1;temp1=temp1+0x01;}if(j==7||j==15||j==23){ printf("%02BX",temp1);temp1=0x00;}}
CS=1;}void read(readtime)	//The subroutine read 200 data from the data register
int readtime;
{unsigned char temp1;
int i,j;temp1=0x00;
for(i=0;i<readtime;i++){ while(DRDY);writetoreg(0x44);CS=0;for(j=0;j<24;j++){SCLOCK=0;SCLOCK=1;if(DOUT==0)temp1=temp1<<1;else{temp1=temp1<<1;temp1=temp1+0x01;}if(j==7||j==15||j==23){ printf("%02BX",temp1);temp1=0x00;}}printf("\n");CS=1;}printf("\n\n\n");
}

AD7718控制代码的设计原理和实现细节:

#include<stdio.h>
#include<aduc832.h>  // 包含ADuC832微控制器的寄存器定义文件

解释:包含标准I/O库用于串口打印,以及ADuC832微控制器的特殊功能寄存器定义文件。

sbit CS=0x085;    // 片选信号 (P0.5)
sbit DIN=0x0B4;   // 串行数据输入 (P3.4)
sbit DOUT=0x0B5;  // 串行数据输出 (P3.5)
sbit DRDY=0x0B3;  // 数据就绪信号 (P3.3)
sbit RESET=0x084; // 复位信号 (P0.4)
sbit SCLOCK=0x0A7;// 串行时钟 (P2.7)
int sig;          // 全局状态标志

解释:使用sbit关键字定义AD7718的控制引脚:

  • 地址0x085对应P0.5(片选)
  • 0x0B4对应P3.4(数据输入)
  • 0x0B5对应P3.5(数据输出)
  • 0x0B3对应P3.3(数据就绪中断)
  • 0x084对应P0.4(硬件复位)
  • 0x0A7对应P2.7(串行时钟)
  • sig变量用于中断状态标志
void int0_int() interrupt 0 {sig=0;  // 中断触发时清除标志return;
}

解释:外部中断0服务程序。当DRDY引脚变低(数据就绪)时触发,将sig标志设为0通知主程序。

void main()
{int tim;  // 延时计数器

解释:主函数开始,声明延时计数器变量。

    /* Set up UART */T3CON = 0x082;  // 定时器3控制:1000 0010 T3FD = 0x02D;   // 波特率重装值SCON   = 0x052; // 串口控制:0101 0010

解释:配置UART串口通信:

  • T3CON=0x82:定时器3作为波特率发生器,模式2
  • T3FD=0x2D:设置波特率(如9600)
  • SCON=0x52:串口模式1(8位UART),允许接收
    tim=1000;  // 初始化延时计数器/* PRECONFIGURE...*/RESET=0;    // 拉低复位引脚while(tim--); // 延时保持复位状态RESET=1;    // 释放复位

解释:硬件复位AD7718。保持RESET低电平约1000个周期(具体时间取决于CPU频率),完成芯片复位。

    SCLOCK=1;  // 时钟空闲高电平DIN=1;     // 数据线默认高DOUT=1;    // 数据线默认高CS=1;      // 取消片选DRDY=1;    // 初始化状态

解释:初始化SPI控制线状态。符合SPI总线空闲状态要求(时钟高,数据线高)。

    printf("\n");  // 输出换行符(测试串口)

解释:发送换行符验证串口是否正常工作。

    writetoreg(0x03); // 写通信寄存器:选择FILTER寄存器writetoreg(0x45); // 写滤波器寄存器:0100 0101

解释:配置滤波器寄存器:

  • 0x03:通信寄存器命令,表示下一个操作对象是滤波器寄存器
  • 0x45:设置滤波器参数(输出数据速率和滤波器特性)
    writetoreg(0x02); // 写通信寄存器:选择ADC控制寄存器writetoreg(0x0F); // 写控制寄存器:0000 1111

解释:配置ADC控制寄存器:

  • 0x02:通信寄存器命令,选择ADC控制寄存器
  • 0x0F:设置单极性模式、2.56V量程、AIN1输入通道
    IT0=1;  // 边沿触发中断EA=1;   // 全局中断使能EX0=1;  // 外部中断0使能

解释:配置中断系统:

  • IT0=1:外部中断0为下降沿触发
  • EA=1:开启总中断
  • EX0=1:开启外部中断0(连接DRDY)
    sig=1;          // 设置等待标志while(sig);     // 等待DRDY中断

解释:等待第一次数据就绪中断,确保ADC初始化完成。

    writetoreg(0x01); // 选择模式寄存器writetoreg(0x06); // 系统零点校准while(DRDY);     // 等待校准完成

解释:执行零点校准:

  • 0x01:选择模式寄存器
  • 0x06:启动系统零点校准
  • while(DRDY):等待校准完成(DRDY变低)
    printf("system zero-scale calibration finished.\n");sig=1;  // 重置标志while(sig);  // 等待中断

解释:打印校准完成信息,等待下一次数据就绪中断。

    writetoreg(0x01); // 选择模式寄存器writetoreg(0x07); // 系统满量程校准while(DRDY);     // 等待校准完成printf("system full-scale calibration finished.\n");

解释:执行满量程校准(流程同零点校准)。

    writetoreg(0x01); // 选择模式寄存器writetoreg(0x03); // 连续转换模式

解释:设置连续转换模式(0x03),ADC开始持续采样。

    // 读取各寄存器值用于验证writetoreg(0x40); // 读状态寄存器readfromreg(8);// ...类似读取其他寄存器

解释:读取并打印关键寄存器值(状态、模式、控制等),用于调试和配置验证。

    read(200);  // 读取200个采样数据
}

解释:主程序最终任务:连续读取200个24位采样值。


SPI通信函数详解:

void writetoreg(unsigned char byteword)
{unsigned char temp;int i;CS=0;  // 使能芯片temp=0x80;  // 1000 0000 掩码for(i=0;i<8;i++){DIN = (temp & byteword) ? 1 : 0;  // 提取最高位SCLOCK=0;  // 时钟下降沿SCLOCK=1;  // 上升沿锁存数据temp >>= 1;  // 右移掩码}CS=1;  // 禁用芯片
}

设计原理

  1. MSB优先的SPI通信
  2. 通过掩码(temp)逐位提取数据
  3. 在时钟上升沿锁存数据
  4. 完整8位数据传输后释放片选
void readfromreg(int bytenumber)
{int j;unsigned char temp1 = 0;CS=0;  // 使能芯片for(j=0;j<bytenumber;j++){SCLOCK=0;  // 准备时钟SCLOCK=1;  // 上升沿读取数据temp1 <<= 1;  // 左移腾出位置if(DOUT) temp1 |= 0x01;  // 设置最低位// 每8位打印一次if(j%8 == 7) {printf("%02X",temp1);temp1=0;}}CS=1;  // 禁用芯片
}

设计原理

  1. 时钟上升沿采样数据
  2. 左移拼接数据位
  3. 每8位组成一个字节并打印
  4. 支持读取任意位数(8/16/24等)
void read(int readtime)
{for(int i=0;i<readtime;i++){while(DRDY);  // 等待数据就绪writetoreg(0x44);  // 选择数据寄存器CS=0;// 读取24位数据for(int j=0;j<24;j++){SCLOCK=0;SCLOCK=1;  // 上升沿读取// 数据拼接逻辑if(j%8 == 7) printf("%02X",temp);  // 每8位打印}printf("\n");  // 完成一个采样CS=1;}
}

设计原理

  1. 等待DRDY变低(数据就绪)
  2. 发送0x44命令选择数据寄存器
  3. 读取24位转换结果
  4. 每8位作为一字节打印(共3字节)
  5. 循环读取指定次数

关键设计思想:

  1. 精确时序控制:通过直接操作寄存器实现硬件级SPI时序
  2. 中断驱动:利用DRDY信号触发中断提高效率
  3. 校准流程:严格的零点和满量程校准确保精度
  4. 模块化设计:读写操作封装为独立函数
  5. 调试支持:通过串口输出关键状态信息
  6. 低位优先处理:适合AD7718的MSB-first通信协议
  7. 状态机管理:通过通信寄存器实现多寄存器访问

这段代码完整展示了如何通过8051单片机控制高精度24位ADC,涉及硬件接口、通信协议、校准流程和数据处理等关键技术,是嵌入式数据采集系统的典型实现。

http://www.lryc.cn/news/602573.html

相关文章:

  • MacBook IOS操作系统格式化U盘FAT32
  • 【深度解析】R语言与作物模型(以DSSAT模型为例)融合应用
  • 分布式微服务--核心组件与架构关系(一)
  • R语言简介(附电子书资料)
  • Leetcode_349.两个数组的交集
  • JavaScript手录09-内置对象【String对象】
  • 6.2 总线事务和定时 (答案见原书 P295)
  • 基于Flask的智能停车场管理系统开发实践
  • C语言:20250728学习(指针)
  • 使用node-cron实现Node.js定时任务
  • Javaweb Day3
  • 主要分布于内侧内嗅皮层的层Ⅲ的网格-速度联合细胞(Grid × Speed Conjunctive Cells)对NLP中的深层语义分析的积极影响和启示
  • 学习人工智能所需知识体系及路径详解
  • BUUCTF-MISC-[HBNIS2018]caesar1
  • 科技风杂志《科技风》杂志社科技风编辑部2025年第19期目录
  • 《Ai智能眼镜的市场定义及用户分析》- 深圳市天趣星空科技有限公司 CEO 王洁
  • 【7.26-7.28胜算云AI日报:首个开源3D世界生成模型腾讯混元、微软预示 8 月 GPT-5 发布、Nemotron推理、商汤悟能、DM夺金】
  • Python 实现多服务器并发启动 SDK-C Master 与 Viewer 的分布式方案
  • 科技赋能成长 脑力启迪未来
  • windows内核研究(异常-CPU异常记录)
  • 计算机视觉---Halcon概览
  • 暑期自学嵌入式——Day10(C语言阶段)
  • 生成器和迭代器的区别
  • 【65 Pandas+Pyecharts | 山东省2025年高考志愿投档数据分析可视化】
  • MCP架构:模型上下文协议的范式革命与工程实践
  • JSBridge原理与实现全解析
  • 嵌入式单片机中位带操作控制与实现
  • flutter使用firebase集成谷歌,苹果登录
  • C++20实战FlamingoIM开发
  • 和豆包玩的AI文字冒险游戏(可以当小说看)