基于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

基于DAC0832的程控衰减器相关推荐

  1. dac单缓冲方式C语言设计,课程设计基于DAC0832单缓冲工作波形发生器.doc

    课程设计基于DAC0832单缓冲工作波形发生器.doc 成绩 课程论文 题 目:基于DAC0832单缓冲工作波形发生器 学生姓名: 学生学号: 系别:电子工程学院 专业:通信工程 年级:2014 任课 ...

  2. 基于DAC0832的直流电机控制系统

    使用DAC0832来控制直流电机 输入数字量0X00~0XFF对应输出0~5V的电压值 运用模拟电路知识设计电路实现电机正反转,数码管实时显示速度值以及正反转. 四位数码管前一位显示正反转.1表示正转 ...

  3. 基于8086简易电子琴系统仿真设计-基于8086红外自动门控制系统设计-基于单片机8x8矩阵键盘两机串口通信-基于单片机8层电梯控制系统仿真设计-基于单片机ADC0809和DAC0832模数和数模设计

    1189基于8086简易电子琴系统仿真设计-设计资料 编写一实现电子琴的程序,并实现若干扩展功能. 基本功能:用键盘输入对应的七个音阶,通过实验箱的喇叭发出声音,并通过七段数码管显示输入音阶: 扩展功 ...

  4. 基于51单片机的DAC0832波形发生器

    输出1HZ正弦波.三角波.方波.锯齿波 使用LCD1602显示 DAC0832的D0~D7数据输入口,IOUT1.IOUT2互补输出口,RFB反馈端口. VREF基准电压值(一般是5V).用定时器控制 ...

  5. 51单片机c语言dac0832产生波形,基于51单片机的DAC0832波形发生器设计

    波形发生器是一种常用的信号源,广泛的应用于电子电路.自动控制系统和教学实验等领域,是现代测试领域内应用最为广泛的通用仪器之一.在研制.生产.测试和维修各种电子元件.部件以及整机设备时,都需要有信号源. ...

  6. 单片机方波da转换c语言程序,基于51单片机的波形发生器DA转换(dac0832)

    代码如下: #include"reg51.h" #define uchar unsigned char sbit ksaw=P2^0; //锯齿波按键. sbit ktran=P2 ...

  7. 基于FPGA NIOS处理器的数码音乐相册

    题记:这是一篇学生时代的学习记录随笔,现在发送出来大家参考参考,同时也测试一下Live Writer写博客的便利,直接复制粘贴即可,很方便. 这个实验可以充分学习FPGA  以及SOPC的利用,做成一 ...

  8. 基于单片机超声波视力保护系统设计-基于51单片机8音键电子琴仿真设计-基于8086八路模拟信号采集均值显示系统设计-基于8086八路数据电压温度采集系统-基于8086波形发生器仿真设计【毕设课设分享】

    539基于单片机超声波视力保护系统设计-设计资料 硬件构成:单片机+最小系统+LCD1602液晶显示模块+超声波模块+DS18B20温度采集模块+光线检测模块+ADC0832模块+蜂鸣器模块+LED指 ...

  9. 基于51单片机信号发生器仿真设计

    本设计 基于51单片机信号发生器仿真设计 (仿真+程序源码+设计说明书) 仿真原版本:proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0015 目录标题 ...

最新文章

  1. CEPH核心理论 相关导图(持续更新)
  2. python开发需要掌握的知识_(深度学习)Python必须掌握基础知识,python,必会,知识点...
  3. Linux I2C子系统分析-I2C设备驱动
  4. 没有眼睛的街头卖艺人
  5. Dom4j完整教程详解
  6. 简述java在安卓开发中的应用_Java 自定义注解在安卓开发中的简单运用
  7. Qt文档阅读笔记-OpenGL Window Example的解析笔记
  8. elementUI日期选择器:仅设置可选择时间区间
  9. 背不下《道德经》,至少背下这10句精华!
  10. 经典的CSS代码(转)
  11. VsCode字体颜色修改和背景图片修改 字体高亮
  12. EasyPR 环境配置
  13. android 音乐均衡器,App+1 | 不懂均衡器调校也能量身定制,无需折腾的 Android 音效提升工具...
  14. u8服务器配置维护,u8客户端连接服务器配置
  15. linux yum安装scp,CentOS安装scp命令的软件包openssh-clients
  16. 黑马程序员——结缘黑马
  17. invoker java_Java Invoker.toString方法代码示例
  18. Scratch技巧—-使用克隆技术实现菜单按钮
  19. 如何成为优秀计算机学者 - 高文老师
  20. 编写三个系别的学生类:英语系,计算机系,文学系(要求通过继承学生抽象类)各系来显示以下成绩:

热门文章

  1. 超有爱的并查集 ------ 转
  2. 微信小程序把玩(十四)button组件
  3. 多多情报通:拼多多宝贝排名靠前为什么没流量和访客?
  4. java中的纸牌游戏_JAVA课程设计纸牌游戏
  5. 【观察】亚信科技:“三新”收入再翻番背后,是全栈数智化能力的释放
  6. 数字货币正确的交易理念——第四章:操作形态的重要意义
  7. 购物商城app的特点有哪些
  8. 用php制作中奖系统,基于PHP随机抽奖小程序,很简单!
  9. Webpack基础应用篇 -[9]管理资源(下)
  10. 一键刷机三星I9220