当前位置: 首页 > 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.dtcms.com/a/302346.html

相关文章:

  • python每日一题
  • 如何在 Apache Ignite 中创建和使用自定义 SQL 函数(Custom SQL Functions)
  • 生物信息学数据技能-学习系列001
  • 牛客网之华为机试题:坐标移动
  • 利用径向条形图探索华盛顿的徒步旅行
  • 数据分析干货| 衡石科技可视化创作之仪表盘控件如何设置
  • 开源智能体-JoyAgent集成ollama私有化模型
  • 【docker】DM8达梦数据库的docker-compose以及一些启动踩坑
  • 攻防世界-引导-Web_php_unserialize
  • Kafka单机如何多Broker实例集群搭建?
  • Python----大模型(基于Fastapi+gradio的对话机器人)
  • 降低焊接机器人保护气体消耗的措施
  • 递归算法的一些具体应用
  • 开发避坑短篇(6):Vue+window.print()打印实践
  • vue如何在data里使用this
  • android-屏幕-刷新流程
  • .NET AI从0开始入门 SemanticKernel 从基础到实践
  • 【GIS数据分享】建筑矢量数据带高度
  • 数据链路层 和 ARP协议
  • 最大连续子数组
  • Makefile if语句用法
  • 【传奇开心果系列】Flet纵向瀑布流本地图片布局排列自定义模板
  • 【硬件】LVGL
  • 15-C语言:第15天笔记
  • keepalived原理及实战部署
  • 【数据库】时序数据库选型指南:从大数据视角看IoTDB的核心优势
  • 张 LLama 多语言语义相似度计算全解析:不同语言 同义词的相似度计算
  • idea启动java应用报错
  • idea编译报错 java: 非法字符: ‘\ufeff‘ 解决方案
  • OSPF笔记