基于DAC0832的程控衰减器

news/2024/10/31 3:21:04/

基于DAC0832的程控衰减器

文章目录

  • 基于DAC0832的程控衰减器
    • 一、需求分析:
    • 二、主要元器件:
    • 三、设计流程
    • 四、工作原理
      • 4.1完整原理图
      • 4.2仿真环境
      • 4.3基准源 2.56V
      • 4.4基准源 0.02V
      • 4.5衰减电路
      • 4.6放大电路
      • 4.7模式切换
    • 五、程序代码
    • 六、相关资料下载

一、需求分析:

1、对输入信号Vin(2.56V直流)进行程控衰减,倍数为2~256倍,由按键控制

2、程控放大器模式,对输入信号(0.02V直流)进行程控放大

3、程控放大器模式,对输入信号(Vp-p=0.1V正弦信号)放大128倍

4、显示器(SMS0801)显示倍数和电压

5、通过程控方式,在衰减器和放大器两种模式下切换

二、主要元器件:

稳压源TL431;稳压二极管LM385;

数模转换DAC0832;模数转换ADS1115;

显示器SMS0801;运算放大器OP07;继电器

三、设计流程

在这里插入图片描述

四、工作原理

4.1完整原理图

在这里插入图片描述

①—2.56V基准源;②—0.02V基准源;③—衰减/放大电路;④—模式切换;⑤—DAC0832的输出状态、继电器输入的模拟;⑥显示的模拟

4.2仿真环境

在线仿真:电子森林 https://www.eetree.cn/war/circuitjs.html?lang=zh

离线仿真:Protues;

4.3基准源 2.56V

功能描述:

对应原理图模块①,采用TL431的恒压电路产生2.56V的稳定电压,使用可调电阻可以精确调节输出电压值Vo,又简化了阻值的计算,但对电路造成了后置影响,即在连接后续电路后输出电压会低于2.56V。

原理分析:

TL431的内部含有一个2.5V的基准电压,所以当在REF端引入输出反馈时,器件可以通过从阴极到阳极很宽范围的分流,控制输出电压。如上图所示,当R1和R2的阻值确定后,两者对Vo的分压引入反馈,若Vo增大,反馈量增大,TL431的分流也就增加,从而又导致Vo下降。显见,这个深度的负反馈电路必然在VI等于基准电压处稳定,此时Vo=(1+R1/R2)Vref。选择不同的R1和R2的值可以得到从2.5V到36V范围内的任意范围电压输出,特别地,当R1=R2时,Vo=5V。需要注意的是,在选择电阻时必须保证TL431工作的必要条件,就是通过阴极的电流要大于1mA

在这里插入图片描述

[1]资料来源:TL431常用电路整理-电子发烧友网 http://m.elecfans.com/article/577647.html

4.4基准源 0.02V

功能描述:

对应原理图模块②,使用LM385制作输出电压约为1.2V的电压基准,经过一个运放构成的电压跟随器后(实现阻抗变换,保障信号衰减小),通过两个电阻分压实现0.02V的稳定输出。同上采用了可调电阻,虽然本次结果显示影响较小,但实际上采用阻值固定的电阻较好。

原理分析:

参考LM324的数据手册构建电压基准源,使用一个电阻器保证有大于Iz(min)=8uA的电流流入阴极。

在这里插入图片描述

4.5衰减电路

功能描述:

对应原理图模块③,DAC0832的8脚VREF作输入端9脚RFB作反馈电阻,通过改变DAC0832的DI7~0口输出状态实现不同倍数的衰减。第二个运算放大器起输出电压反相的作用。

原理分析:

DAC0832是采用CMOS工艺制成的单片直流输出型8位数/模转换器。如图所示,它由倒T型R-2R电阻网络、模拟开关、运算放大器和参考电压VREF四大部分组成。

在这里插入图片描述

倒T型R-2R电阻网络

可以等效为
在这里插入图片描述

网路特点:任何一个节点的三条分支的等效电阻都是2R,因此流进任何一个选定分支的电流为I=UR/3R。同时因为并联结构,流入其他节点时,电流会被平分。

以图中模拟A0=1为例,A0的电流为I=UR/(2R||2R+2R)=UR/3R,A1的电流就为I/2,A2的电流为I/4…以此类推,A7的电流为1/128,流入Rfb的电流为I/256,最终输出电压为Vo=I/256*Rfb。当Rfb=3R时,Vo=1/256UR。

运算放大器的输出模拟量Vo为:

在这里插入图片描述

4.6放大电路

功能描述:

对应原理图模块③,与衰减电路相似,8脚VREF作为反馈,9脚RFB作为输入端,改变DAC0832的DI7~0口输出状态实现不同倍数的放大。

原理分析:

电路原理与衰减相同,简言之是将输入、输出交换。

在这里插入图片描述

运算放大器的输出模拟量Vo为:在这里插入图片描述

4.7模式切换

功能描述:

对应原理图模块④,电路上,通过继电器实现不同线路的切换;程序上,通过改变控制端口的输出电压,让继电器在跳转/未跳转两种状态之间切换。

原理分析:

对比衰减和放大电路,可以发现模式的切换只需要交换输入、输出端即可,因而采用继电器控制不同线路的选择,电路中使用三极管实现控制端口的电压变化影响继电器工作状态的效果。

五、程序代码

程序代码主要包括按键功能、液晶显示、AD采集三大部分。

/********************
*主程序代码参考(C51)
*********************/
#include <reg52.h>
#include <ads1115.h>sbit CLKPIN  = P3^0;  	//CLK对应单片机引脚
sbit DIPIN   = P3^1;  	//DI对应单片机引脚
sbit KEY_1 = P1^2;		//按键1减小倍数
sbit KEY_2 = P1^3;		//按键2增加倍数
sbit KEY_3 = P1^4;		//按键3切换模式
sbit KEY_4 = P1^5;		//按键4置空sbit P1_6  = P1^6;		// P1.6、1.7 控制继电器的工作状态
sbit P1_7  = P^7;//以下Num1_Ram至Num8_Ram为数字1至8在演示程序中的RAM地址预定义
#define NUMBERS 8                       //显示数字的个数
unsigned char Num1_Ram;                 //数字1
unsigned char Num2_Ram;                 //数字2
unsigned char Num3_Ram;                 //数字3
unsigned char Num4_Ram;                 //数字4
unsigned char Num5_Ram;                 //数字5
unsigned char Num6_Ram;                 //数字6
unsigned char Num7_Ram;                 //数字7
unsigned char Num8_Ram;                 //数字8//数码笔段顺序:  D76543210
//               ABCDEFGX
unsigned char code NUMCODETAB[]={0xFC,0x60,0xDA,0xF2,  //数字0,1,2,30x66,0xB6,0xBE,0xE0,  //数字4,5,6,70xFE,0xF6,0x00,0x02,  //数字8,9,字符空格,字符-0x9C,0xCE,0x9E,0x8E}; //字符C,字符P,字符E,字符Funsigned char KeySta[4] ={1,1,1,1};				//按键的当前状态unsigned int ValVoltage(unsigned char n);				//ADC读取函数
void delay(unsigned int xms);							//软件延时函数,单位1ms
void ConfigTimer0(unsigned int ms);						//定时器0配置函数
void ShowNumber(unsigned int num,unsigned int value);	//数码管显示函数
void KeyScan();											//按键扫描函数
void KeyDriver();										//按键功能驱动函数//SMS0801B的函数定义
void decodetolcd(void);                 //液晶显示控制器译码子程序
void transram(void);                    //LCD显示刷新子程序
void transbyte(unsigned char d);        //送1字节数据到液晶显示控制器子程序
void transbit(bit d);                   //送1位数据到液晶显示控制器子程序unsigned char T0RH =0; 					// T0重载值的高字节
unsigned char T0RL =0; 					// T0重载值的低字节
unsigned int shift =32;					// DAC当前的输出状态,即衰减/放大的倍数,初始为256/32=8倍
unsigned int adcValue;					// ADC1115获取的电压值//--------------------------------------------------------------------------------------------------void main()
{  EA = 1;       			//使能总中断ConfigTimer0(10);		//配置T0定时10msConfige1115();			//配置AD寄存器delay(5);           
//		P1_6=0;					//设置P1.6、P1.7的初始状态,需根据硬件电路作改动
//		P1_7=0;while (1){KeyDriver();				// 调用按键驱动函数			delay(100);P2=shift;					// 将倍数发送至DACadcValue=ValVoltage(100);	// ADS1115采集电压信息ShowNumber(shift,adcValue);	//显示放大倍数、电压值,SMS0801本质上是8个数码管			}
}//--------------------------------------------------------------------------------------------------
/*延时函数,单位1ms*/
void delay(unsigned int xms)
{unsigned int i,j;for(i=xms;i>0;i--)for(j=30;j>0;j--);
}//----------------------------------------------------------------------
/*按键驱动函数*/
void KeyDriver()
{unsigned char i;for(i=0;i<4;i++)		// 循环检测4个按键{if(KeySta[i]==0)	// 检测按键动作{if(i==0)								// 减小键,DAC数值增加,倍数减小{while(KeySta[i]==0)					//等待按键释放,实现长按功能{if(shift<255)	shift++;delay(500);						//延时0.5s,约每隔0.5s加1ShowNumber(shift,adcValue);	}}else if (i == 1)						// 增大键,DAC数值减小,倍数增加{while(KeySta[i]==0)					//等待按键释放,实现长按功能{if(shift>1)	shift--;			//延时0.5s,约每隔0.5s减1delay(500);ShowNumber(shift,adcValue);	}}else if (i == 2)						//模式转换按键,P2.7,P2.6输出反转{while(KeySta[i]==0) delay(1000);P1_6 = ~P1_6;P1_7 = ~P1_7;}}}
}//----------------------------------------------------------------------
/*显示函数*/
void ShowNumber(unsigned int num,unsigned int val)
{signed char i;unsigned char buf[8];//倍数显示//num = 256/num;for(i=7; i>=5 ;i--) 				//把长整型数转换为8位十进制数组{									buf[i] = num%10;			//个位存入buf[7],十位存入buf[6],百位存入buf[5]num = num/10;}for(i=5;i<=7;i++)					//高位0不显示{if(buf[i]==0)buf[i]=10;else break;}//电压显示val = val*187.5/1000000*100;		//对ADS1115采集的数据进行换算,// *100 的作用是将小数化为所需整数,以便显示,如2.56变为256for(i=3; i>=0 ;i--)					//把长整型数转换为8位十进制数组{buf[i] = val%10;val = val/10;}Num1_Ram=buf[0];            //第1位Num2_Ram=buf[1];            //第2位,输出该位时点亮小数点Num3_Ram=buf[2];            //第3位Num4_Ram=buf[3];			//第4位Num5_Ram=buf[4]; 			//第5位,显示'-'Num6_Ram=buf[5];            //第6位Num7_Ram=buf[6];            //第7位Num8_Ram=buf[7];            //第8位transram();delay(300);
}//----------------------------------------------------------------------
/*ADC1115读取电压值*/
unsigned int ValVoltage(unsigned char n)
{unsigned long int idata sum=0;unsigned int idata val;unsigned char idata i;val=read1115();val=read1115();for(i=0;i<n;i++){sum += read1115();}val = sum/n;return val;
}//----------------------------------------------------------------------
/*液晶刷新*/
void transram(void)                     //LCD显示刷新子程序
{   decodetolcd();                      //按地址映射表字节顺序,所有数据译码后送//LCD液晶显示控制器
}void decodetolcd(void)                  //按地址映射表字节顺序,所有数据译码后送
{ unsigned char buf;                    //LCD液晶显示控制器子程序
//LCDBUF+0 缓冲区第1个字节译码buf=0x00;                             //当前译码数据置初始值//需译码的BIT为ABCDEFGZ位buf|=NUMCODETAB[Num1_Ram]&0xFE;       //第1个8字的ABCDEFG笔段译码                         transbyte(buf);                       //将当前译码数据送LCD液晶显示控制器//LCDBUF+1 缓冲区第2个字节译码buf=0x00;                             //当前译码数据置初始值//需译码的BIT为ABCDEFGZ位buf|=NUMCODETAB[Num2_Ram]&0xFE;       //第2个8字的ABCDEFG笔段译码buf+=0x01;							//显示小数点transbyte(buf);                       //将当前译码数据送LCD液晶显示控制器//LCDBUF+2 缓冲区第3个字节译码buf=0x00;                             //当前译码数据置初始值//需译码的BIT为ABCDEFGZ位buf|=NUMCODETAB[Num3_Ram]&0xFE;       //第3个8字的ABCDEFG笔段译码transbyte(buf);                       //将当前译码数据送LCD液晶显示控制器//LCDBUF+3 缓冲区第4个字节译码buf=0x00;                             //当前译码数据置初始值//需译码的BIT为ABCDEFGZ位buf|=NUMCODETAB[Num4_Ram]&0xFE;       //第4个8字的ABCDEFG笔段译码transbyte(buf);                       //将当前译码数据送LCD液晶显示控制器//LCDBUF+4 缓冲区第5个字节译码buf=0x02;                             //当前译码数据置初始值,第5位一直为'-'transbyte(buf);                       //将当前译码数据送LCD液晶显示控制器//LCDBUF+5 缓冲区第6个字节译码buf=0x00;                             //当前译码数据置初始值//需译码的BIT为ABCDEFGZ位buf|=NUMCODETAB[Num6_Ram]&0xFE;       //第6个8字的ABCDEFG笔段译码                         transbyte(buf);                       //将当前译码数据送LCD液晶显示控制器//LCDBUF+6 缓冲区第7个字节译码buf=0x00;                             //当前译码数据置初始值//需译码的BIT为ABCDEFGZ位buf|=NUMCODETAB[Num7_Ram]&0xFE;  //第7个8字的ABCDEFG笔段译码                          transbyte(buf);                       //将当前译码数据送LCD液晶显示控制器//LCDBUF+7 缓冲区第8个字节译码buf=0x00;                             //当前译码数据置初始值//需译码的BIT为ABCDEFGX位buf|=NUMCODETAB[Num8_Ram]&0xFE;       //第8个8字的ABCDEFG笔段译码transbyte(buf);                       //将当前译码数据送LCD液晶显示控制器
}//----------------------------------------------------------------------
/*字节数据传输*/
void transbyte(unsigned char d)         //送1字节数据到液晶显示控制器子程序
{   unsigned char i;for(i=0;i<8;i++){   if((d&0x1) == 0x1)transbit(1);elsetransbit(0);d>>=1;                          //从低到高位送字节位数据到液晶显示控制器}
}//----------------------------------------------------------------------
/*位数据传输*/
void transbit(bit d)                    //送1位数据到液晶显示控制器子程序
{  DIPIN = d;                           //先送数据到数据口线DI_nop_();_nop_();CLKPIN = 1;                          //再使时钟口线发一个负脉冲_nop_();_nop_();CLKPIN = 0;_nop_();_nop_();CLKPIN = 1;
}//----------------------------------------------------------------------
/*按键扫描*/
void KeyScan()
{unsigned char i;static unsigned char keybuf[4] = {0xFF,0xFF,0xFF,0xFF};// 将一行按键值移入缓冲区keybuf[0] = (keybuf[0] << 1) | KEY_1;keybuf[1] = (keybuf[1] << 1) | KEY_2;keybuf[2] = (keybuf[2] << 1) | KEY_3;keybuf[3] = (keybuf[3] << 1) | KEY_4;//消抖后更新按键状态for(i=0;i<4;i++){if((keybuf[i]&0x0F) == 0x00){	// 连续4次扫描值为0,认为按键已稳定的按下KeySta[i] = 0;}else if ((keybuf[i])&0x0F == 0x0F){KeySta[i] = 1;}}
}//----------------------------------------------------------------------
/*定时器配置*/
void ConfigTimer0(unsigned int ms)
{unsigned long tmp;	//临时变量tmp = 11059200 / 12;	// 定时器计数频率tmp = (tmp*ms)/1000;	// 计算所需的计数值tmp = 65536 - tmp;		// 计算定时器重载值tmp = tmp +12;T0RH = (unsigned char)(tmp >>8);T0RL = (unsigned char)tmp;TMOD &= 0xF0;		// 清零T0的控制位TMOD |= 0x01;		// 配置T0为模式1TH0 = T0RH;			// 加载T0重载值TL0 = T0RL;ET0 = 1;				// 使能T0中断TR0 = 1;				// 启动T0
}//----------------------------------------------------------------------
/* 定时器0中断服务函数*/
void InterruptTimer0() interrupt 1
{	TH0 = T0RH;	// 重新加载重载值TL0 = T0RL;KeyScan();	// 调用按键扫描函数
}

六、相关资料下载

https://download.csdn.net/download/AriesPIG/20466303


http://www.ppmy.cn/news/456002.html

相关文章

python控制程控电源_程控开关与控制的基础介绍

为了使测试系统达到准确和精确就需要选择适当的仪器&#xff0c;在设计测试方法方面需要有创造性&#xff0c;同时要仔细地考虑技术指标和误差源。大多数测试系统设计的十分复杂&#xff0c;设计者们最 关心的是将不受控制的变量减少到最少。为了实现这个目的&#xff0c;此系统…

VC++控制程控电源2306读取电流

VC++开发常用功能一系列文章 (欢迎订阅,持续更新...) 吉时利2306 KEITHLEY2306通讯测试程控电源程序控制 支持双通道控制: 直接上代码: 自动化技术得到飞跃发展的今天,测试中各种仪表也都支持IEEE 488协议,可以利用PC完成控制。在GPIB总线编程中,将总结过去用到…

python控制程控电源_程控电源的用途

简介 程控电源指通过外部控制来设定输出电压、输出电流的稳压、稳流或稳压/稳流的电源。程控河试电源采用微机控制&#xff0c;技术先进&#xff0c;全程控、全按键操作&#xff0c;体积小、重量轻、携带方便&#xff0c;既可用于实验室&#xff0c;也可以现场使用。 程控电源的…

程控直流电源是什么?为什么选择程控电源?

什么是程控直流电源?程控直流电源通过外部控制来设置输出电压和输出电流&#xff0c;并设置连续电流和电压稳定度&#xff0c;程控直流电源由微型计算机控制&#xff0c;该设备配备了先进的技术&#xff0c;所有操作都可以使用按键进行操作&#xff0c;体积小&#xff0c;轻巧…

C#使用NI VISA实现程控仪器的自动化控制

转自https://www.cnblogs.com/hitfredrick/p/6402998.html 1.概述 生产测试当中&#xff0c;测试仪器不可或缺&#xff0c;如果是小规模生产&#xff0c;手动测试可以对付&#xff1b;但是要想到达大批量生产的目的&#xff0c;为了简化测试&#xff0c;节约时间&#xff0c;…

python控制程控电源_六大步骤认识程控电源的界面操作

1 程控电源按键说明 2 1) 0&#xff5e;9&#xff1a;用于在输入框里面输入数据&#xff1b; 3 2) 小数点&#xff1a;用于在输入框中输入带小数的数据&#xff1b; 4 3) 10.0%↑键&#xff1a;当操作焦点位于调节滑块上时&#xff0c;可以用来将当前输出值增加额定值的10%&…

程控交换复习

交换系统的基本技术有&#xff1a;接口技术&#xff0c;互联接口&#xff0c;信令技术&#xff0c;控制技术。 构成通信网的三要素是&#xff1a;交换设备&#xff0c;传输设备&#xff0c;终端设备。 多处理机的工作方式有哪些&#xff0c;各自有什么特点&#xff1a; ①功…

matlab程控开关,基于单片机和FPGA设计的程控滤波器(MAX297+LTC1068)

以单片机和可编程逻辑器件(FPGA)为控制核心,设计了一个程控滤波器,实现了小信号程控放大、程控调整滤波器截止频率和幅频特性测试的功能。其中放大模块由可变增益放大器AD603实现,最大增益60dB,10dB步进可调,增益误差小于1%。程控滤波模块由MAX297低通滤波、TLC1068高通滤…