先来了解一下DAC083x的一些基本介绍:
在DAC0830的芯片手册中可以了解到,输出IOUT1是与施加的参考电压和数字输入字的乘积成正比的电流。 为了实现应用的多功能性,第二个输出IOUT2作为电流提供,与数字输入的补码成正比。
数字输入为所施加的8位二进制字(0至255)的十进制等效值(以10为基数),VREF是引脚8上的电压,而15kΩ是R的内部电阻R的标称值 -2R梯形网络。而在DAC083x系列的芯片手册中,也可以很方便的找到参考电路,如下:
按照这个参考电路,以及看了一些网上其他人设计的电路,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可以控制正弦波的周期,也就是后面需要做的按键调频功能。这个先不用管,现在就可以看到仿真中的正弦波效果:
看到了正弦效果之后,就可以按照上面说的,检测按键,来调节正弦波的周期,先来画几个按键:
将按键检测写成一个函数,并且做好分类与注释,先填写好周期按键的相关内容,如下:
/**********************************
按键检测函数
***********************************/
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调频视频
龙猫的视频
· 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 播放
完整代码如下:文章来源:https://www.toymoban.com/news/detail-468825.html
#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模板网!