【Proteus】使用DAC0832输出可调正弦波

这篇具有很好参考价值的文章主要介绍了【Proteus】使用DAC0832输出可调正弦波。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

先来了解一下DAC083x的一些基本介绍:

在DAC0830的芯片手册中可以了解到,输出IOUT1是与施加的参考电压和数字输入字的乘积成正比的电流。 为了实现应用的多功能性,第二个输出IOUT2作为电流提供,与数字输入的补码成正比。

【Proteus】使用DAC0832输出可调正弦波

数字输入为所施加的8位二进制字(0至255)的十进制等效值(以10为基数),VREF是引脚8上的电压,而15kΩ是R的内部电阻R的标称值 -2R梯形网络。而在DAC083x系列的芯片手册中,也可以很方便的找到参考电路,如下:

【Proteus】使用DAC0832输出可调正弦波

按照这个参考电路,以及看了一些网上其他人设计的电路,DAC0832部分的电路如下:

【Proteus】使用DAC0832输出可调正弦波

完整的电路如图:

【Proteus】使用DAC0832输出可调正弦波

在手册中对于DAC芯片的时序介绍比较详细,不过程序写起来并不会那么复杂,因为我们只需要在初始化之后往数据口里传数据就可以了,初始化也很简单,就直接把一些端口给0:

/**********************************
外设初始化函数
***********************************/
void da_init()	  
{
   DA_WR = 0;
   DA_CS = 0;
   DA_DATA = 0;
   key0 = 1;   //按键置高
   key1 = 1;   //按键置高
   key2 = 1;   //按键置高
   key3 = 1;   //按键置高
}

先用代码实现正弦数据的产生,先不用管幅值的调节,直接就最大幅值12V,也就是正弦数据中的255对应12V,0对应-12V。

我们使用C语言中的math库生成sin函数,有个地方需要注意,math库中的sin函数输入数据是弧度制的,假如说,我们需要30度的sin值,那么需要将30度转换成弧度制:30 * PI / 180。现在我们需要循环一个周期的sin值,那么就使用一个变量,一直自加,从0加到360度,然后求出对应的sin值,然后再将sin值转换到0-255之间传输到DAC芯片就可以了:

/**********************************
波形发生函数
***********************************/
void wave()
{
	float sinAngle = 0.0f;

	Angle ++;   //角度自加
	if (Angle >= 360)
		Angle = 0;	
	sinAngle = sin(((float)Angle * PI / 180.0f));   //求角度对应的正弦值  返回[-1,1] 
	DA_DATA	 = (int)(((sinAngle + 1.0f) / 2.0f) * 255.0f);
}

上面代码中需要注意的是sinAngle即是求取出来的正弦值,范围是[-1,1],而DAC芯片的输入是0-255,因此需要将正弦值整体加1,整体上移,然后除以2得到比例,然后再乘以255,便可以直接赋值给DAC芯片。

现在我们有了生成正弦值的函数,那么就要控制正弦值输入给DAC的时间,使用一个定时器来计时,在定时器中断中控制调用wave函数来控制生成正弦波的时间间隔,

定时器初始化程序如下:

/**********************************
定时器初始化函数
***********************************/
void init()	  
{
   TMOD = 0x01;	//设置定时器工作方式,第二位为定时器0
   TH0 = (65536 - T)/256; //定时器0高8位  定时时间1ms
   TL0 = (65536 - T)%256; //定时器0低8位
   TR0 = 1;	   //打开定时器
   ET0 = 1;	   //开定时器中断
   EA = 1;     //开总中断
}

定时器中断程序如下:

void T0_time() interrupt 1
{
	TH0 = (65536 - T)/256; //定时器0高8位  定时时间1ms
        TL0 = (65536 - T)%256; //定时器0低8位
	time ++;
	if (time > (cycle_T / T))   //0.1ms
	{
	   time = 0;
	   wave();	  //波形发生函数
	}	
}

这里我配置的定时器中断时间是1ms,也就是T,即1ms进一次中断,通过调节cycle_T可以控制正弦波的周期,也就是后面需要做的按键调频功能。这个先不用管,现在就可以看到仿真中的正弦波效果:

【Proteus】使用DAC0832输出可调正弦波

看到了正弦效果之后,就可以按照上面说的,检测按键,来调节正弦波的周期,先来画几个按键:

【Proteus】使用DAC0832输出可调正弦波

将按键检测写成一个函数,并且做好分类与注释,先填写好周期按键的相关内容,如下:

/**********************************
按键检测函数
***********************************/
void key_check()
{
   /*按键端口置高*/
   key0 = 1;
   key1 = 1;
   key2 = 1;
   key3 = 1;

   /*增大周期*/
   if(key0 == 0)
   {
   		delayms(5);	 //按键消抖
		if(key0 == 0)   
		{
		  cycle_T = cycle_T + 2000;   //每次增加2000us
		  /*限幅*/
		  if (cycle_T > CYCLE_MAX)
		  {
		  	cycle_T	=  CYCLE_MAX;
		  }
		}
		while(!key0);	//等待按键松开
   }
   /*减小周期*/
   if(key1 == 0)
   {
   		delayms(5);	 //按键消抖
		if(key1 == 0)   
		{
		  cycle_T = cycle_T - 2000;   //每次减小2000us
		  /*限幅*/
		  if (cycle_T < CYCLE_MIN)
		  {
		  	cycle_T	=  CYCLE_MIN;
		  }
		}
		while(!key1);	//等待按键松开
   }
   /*增大幅值*/
   if(key2 == 0)
   {
   		delayms(5);	 //按键消抖
		if(key2 == 0)   
		{

		}
		while(!key2);	//等待按键松开
   }
   /*减小幅值*/
   if(key3 == 0)
   {
   		delayms(5);	 //按键消抖
		if(key3 == 0)   
		{

		}
		while(!key3);	//等待按键松开
   }

}

这里我每按一次按键,就调节那个cycle_T的值,并且对这个值做了一次限幅,避免出现一些溢出之类的情况。

之后就可以看到按键调频的效果,如下:

DAC调频视频

【Proteus】使用DAC0832输出可调正弦波

龙猫的视频

 · 97 播放

之后是修改幅值,修改幅值其实就是修改传输到DAC的0-255的区间范围,如果是占满0-255就是最大幅值,那样的话,就可以修改wave函数,使用另外一个单独变量Amp来确定幅值,除此之外,我们需要确定一个最大幅值为12V,Amp不能超过12,修改如下:

/**********************************
波形发生函数
***********************************/
void wave()
{
	float sinAngle = 0.0f;

	Angle ++;   //角度自加
	if (Angle >= 360)
		Angle = 0;	
	sinAngle = sin(((float)Angle * PI / 180.0f));   //求角度对应的正弦值  返回[-1,1] 
	sinAngle = sinAngle * Amp / AMP_MAX;     //按照幅值范围等比例放大缩小
	DA_DATA	 = (int)(((sinAngle + 1.0f) / 2.0f) * 255.0f);
}

需要定义三个宏:

#define AMP_DEFAULT      5.0f    //默认幅值  单位:V
#define AMP_MAX          12.0f   //最大幅值为12
#define AMP_MIN          0.0f    //最小幅值

之后修改按键的部分:

 /*增大幅值*/
   if(key2 == 0)
   {
   		delayms(5);	 //按键消抖
		if(key2 == 0)   
		{
		  Amp = Amp + 1.0f;
		  if (Amp >= AMP_MAX)
		  	 Amp = AMP_MAX;
		}
		while(!key2);	//等待按键松开
   }
   /*减小幅值*/
   if(key3 == 0)
   {
   	delayms(5);	 //按键消抖
		if(key3 == 0)   
		{
		  Amp = Amp - 1.0f;
		  if (Amp <= AMP_MIN)
		  	 Amp = AMP_MIN;
		}
		while(!key3);	//等待按键松开
   }

之后就可以看到效果啦:

DAC调幅视频

龙猫的视频

 · 116 播放

完整代码如下:

#include <reg52.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
#define DA_DATA  P1    //DAC0832数据口
#define AMP_DEFAULT      5.0f    //默认幅值  单位:V
#define AMP_MAX          12.0f   //最大幅值为12
#define AMP_MIN          0.0f    //最小幅值
#define T                1000     //计时周期  单位:us
#define CYCLE_DEFAULT    1000    //默认正弦周期   单位:us
#define CYCLE_MAX        20000    //最大周期
#define CYCLE_MIN		 1000
#define PI               3.1415926f 

/****************************变量*******************************/
uint Angle = 0;   //角度  0-360
int time = 0;	    //计时
int cycle_T = 0;    //正弦周期
float Amp = 0.0f;

//定义DAC0832接口
sbit DA_WR = P2^1;	 //写输入信号
sbit DA_CS = P2^0;   //片选信号


//定义按键接口
sbit key0 = P2^2;  //增大周期
sbit key1 = P2^3;  //减小周期
sbit key2 = P2^4;  //增大幅值
sbit key3 = P2^5;  //减小幅值

//延时
void delayms(int x)
 {  uint i,j;
    for(i=x;i>0;i--)
	  for(j=110;j>0;j--);
 }

/**********************************
外设初始化函数
***********************************/
void da_init()	  
{
   DA_WR = 0;
   DA_CS = 0;
   DA_DATA = 0;
   key0 = 1;   //按键置高
   key1 = 1;   //按键置高
   key2 = 1;   //按键置高
   key3 = 1;   //按键置高
}
/**********************************
定时器初始化函数
***********************************/
void init()	  
{
   TMOD = 0x01;	//设置定时器工作方式,第二位为定时器0
   TH0 = (65536 - T)/256; //定时器0高8位  定时时间1ms
   TL0 = (65536 - T)%256; //定时器0低8位
   TR0 = 1;	   //打开定时器
   ET0 = 1;	   //开定时器中断
   EA = 1;     //开总中断
}

/**********************************
按键检测函数
***********************************/
void key_check()
{
   /*按键端口置高*/
   key0 = 1;
   key1 = 1;
   key2 = 1;
   key3 = 1;

   /*增大周期*/
   if(key0 == 0)
   {
   		delayms(5);	 //按键消抖
		if(key0 == 0)   
		{
		  cycle_T = cycle_T + 2000;   //每次增加2000us
		  /*限幅*/
		  if (cycle_T > CYCLE_MAX)
		  {
		  	cycle_T	=  CYCLE_MAX;
		  }
		}
		while(!key0);	//等待按键松开
   }
   /*减小周期*/
   if(key1 == 0)
   {
   		delayms(5);	 //按键消抖
		if(key1 == 0)   
		{
		  cycle_T = cycle_T - 2000;   //每次减小2000us
		  /*限幅*/
		  if (cycle_T < CYCLE_MIN)
		  {
		  	cycle_T	=  CYCLE_MIN;
		  }
		}
		while(!key1);	//等待按键松开
   }
   /*增大幅值*/
   if(key2 == 0)
   {
   		delayms(5);	 //按键消抖
		if(key2 == 0)   
		{
		  Amp = Amp + 1.0f;
		  if (Amp >= AMP_MAX)
		  	 Amp = AMP_MAX;
		}
		while(!key2);	//等待按键松开
   }
   /*减小幅值*/
   if(key3 == 0)
   {
   		delayms(5);	 //按键消抖
		if(key3 == 0)   
		{
		  Amp = Amp - 1.0f;
		  if (Amp <= AMP_MIN)
		  	 Amp = AMP_MIN;
		}
		while(!key3);	//等待按键松开
   }

} 

/**********************************
波形发生函数
***********************************/
void wave()
{
	float sinAngle = 0.0f;

	Angle ++;   //角度自加
	if (Angle >= 360)
		Angle = 0;	
	sinAngle = sin(((float)Angle * PI / 180.0f));   //求角度对应的正弦值  返回[-1,1] 
	sinAngle = sinAngle * Amp / AMP_MAX;     //按照幅值范围等比例放大缩小
	DA_DATA	 = (int)(((sinAngle + 1.0f) / 2.0f) * 255.0f);
}

void main()
{  
   init(); //定时器初始化
   cycle_T = CYCLE_DEFAULT;  //初始化为默认正弦周期
   Amp = AMP_DEFAULT;       //初始化为默认幅值     
   da_init();    //DA初始化
   while(1)
   {  
     key_check();
   }
}

void T0_time() interrupt 1
{
	TH0 = (65536 - T)/256; //定时器0高8位  定时时间1ms
    TL0 = (65536 - T)%256; //定时器0低8位
	time ++;
	if (time > (cycle_T / T))   //0.1ms
	{
	   time = 0;
	   wave();	  //波形发生函数
	}	
}

点个赞喽!文章来源地址https://www.toymoban.com/news/detail-468825.html

到了这里,关于【Proteus】使用DAC0832输出可调正弦波的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【单片机基础】使用51单片机制作函数信号发生器(DAC0832使用仿真)

    单片机作为一个数字电路系统,当需要采集外界模拟量的使用需要进行AD转换,将模拟量转换成数字量,供单片机使用。51单片机需要外部配置一个AD转换芯片来进行模拟量的采集,如我之前写了一篇ADC0832的使用。高级的单片机如STC12和STM32已经集成了AD转换功能,只需简单配置

    2024年02月08日
    浏览(34)
  • Proteus仿真stm32f103r6输出PWM/正弦波

    Proteus仿真stm32f103r6输出PWM/正弦波  

    2024年01月23日
    浏览(37)
  • FPGA 20个例程篇:20.USB2.0/RS232/LAN控制并行DAC输出任意频率正弦波、梯形波、三角波、方波(五)

           如表1所示是dds_ip_transform模块信号列表,在正弦波模块中我们需要把上游指令解析模块中发来的频率控制字和指示信号即dds_din_freq和dds_din_freq_vld、相位控制字和指示信号即dds_din_phase和dds_din_phase_vld、复位信号即ddsip_sclr写入到DDS IP核中,如图1所示是正弦波模块的代码设

    2024年02月01日
    浏览(39)
  • FPGA 20个例程篇:20.USB2.0/RS232/LAN控制并行DAC输出任意频率正弦波、梯形波、三角波、方波(二)

         通过上面的介绍相信大家对数字变频已经有了一个较为整体性的认识,下面笔者来对照XILINX的DDS IP核对数字变频技术展开更进一步的说明,做到了理论和实践很好地结合,这样大家再带入Modelsim进行仿真测试就不仅掌握了数字变频的理论知识,也明白了其IP核的使用方法

    2024年02月22日
    浏览(32)
  • FPGA 20个例程篇:20.USB2.0/RS232/LAN控制并行DAC输出任意频率正弦波、梯形波、三角波、方波(三)

            如图1所示是USB2.0/RS232/ETH控制并行DAC输出任意频率正弦波、梯形波、三角波、方波的整体设计示意图,可以看到上位机通过RS232串口、ETH千兆网口以及USB2.0接口和FPGA建立通信,通过不同的接口发送报文,FPGA在指令解析模块中把相关设置和参数再下发到任意波(方波、

    2023年04月15日
    浏览(30)
  • FPGA 20个例程篇:20.USB2.0/RS232/LAN控制并行DAC输出任意频率正弦波、梯形波、三角波、方波(四)

            接着同样地我们也需要完成对千兆网口ETH模块和USB2.0模块的编写,实际上和UART串口模块的设计思想大同小异,也同样地需要完成两项关键功能即识别并解析报文、接收并发送数据,千兆网口ETH和USB2.0的底层驱动在前面的例程中也详细说明了,所以在这里笔者不想再重

    2024年02月04日
    浏览(39)
  • DAC0832

    芯片简介: DAC0832是采样频率为八位的D/A转换芯片,集成电路内有两级输入寄存器,使DAC0832芯片具备双缓冲、单缓冲和直通三种输入方式。D/A转换结果采用 电流 形式输出。若需要相应的模拟电压信号,可通过一个 高输入阻抗的线性运算放大器 实现。运放的反馈电阻可通过

    2024年02月10日
    浏览(26)
  • 基于51单片机的DAC0832波形发生器

    输出1HZ正弦波、三角波、方波、锯齿波 使用LCD1602显示 DAC0832的D0~D7数据输入口,IOUT1、IOUT2互补输出口,RFB反馈端口、 VREF基准电压值(一般是5V)。用定时器控制段码表输出速度来控制波形的频率。 (定时数值)*10^(-6)*256=波形频率。 ( 1 )锯齿波的实现原理:   锯齿波的实现

    2024年02月06日
    浏览(76)
  • 【51单片机】DAC0832制作信号发生器(方波,三角波,锯齿波)

    将模拟量转换为数字量称为模数转换(A/D转换), 模拟量是连续的 ,比如电压、电流等,可以连续变化的量; 数字量是离散的 ,对应于计算机中的位,每一个位只能是0或1,是不存在中间状态的。通过模数转换原件将模拟量转化为数字量输入计算机,以便计算机进行计算、

    2024年02月06日
    浏览(27)
  • (DDS)正弦波形发生器——幅值、频率、相位可调(一)

    设计一个幅值、频率、相位均可调的正弦波发生器。 频率每次增加1kHz。 相位每次增加 2*PI/256 幅值每次增加两倍 DDS的核心原理。 分别使用两种方式完成频率可调(a、b),并且进行对比(c),最后对b进行优化(d)。 完成赋值、频率、相位可调的正弦波形发生器。(见文章

    2023年04月08日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包