基于单片机和DAC0832做的低频信号发生器

我的要求是做个4V峰峰值的正弦波 频率必须可调1HZ~10KHZ 前面部分没问题 但是我还是不明白那个频率可调怎么调 采用按键处理的时候该怎么弄? 频率可调的时候必须在数码管上显示出来 请各位指点一下 哈 谢谢!
这个要求滴还是蛮严格的 我们的硬件电路能满足还是尽量用硬件电路上的设施 不能外加任何东西 这个要求是采用最小系统单片机来完成的

做综合设计的吗?
给你个程序自己看看

#include"at89x51.h"
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/************************* 全局变量定义部分 **************************/
//硬件设计接口不同,要修改下一行
uchar code acLEDCS[]={0x7f,0xbf,0xdf,0xef};
uchar code acLedSegCode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x58,0x5e};/* 段码 */
uchar acLED[4]; /* 显示缓冲区 */
char cScanIndex; /* 位选指针0~3 */
uchar cKey;
sbit cKey1=P2^2;
sbit cKey2=P2^1;
sbit cKey3=P2^0;
uchar cKeyCode;
uchar cLongDelay;
uchar Out[32];
bit bStill; /* 是否松键标志 */
uint nDelayKey=0; /* 键盘延时变量,为定时中断间隔时间的整数倍 */
uchar cMode=0;
uchar Num;
uchar cF=100;
uchar code tosin[32]={
0x80,0x99,0xb1,0xc7,0xda,0xea,0xf6,0xfd,
0xff,0xfd,0xf5,0xe9,0xd8,0xc5,0xae,0x96,
0x80,0x66,0x4e,0x38,0x25,0x15,0x09,0x02,
0x00,0x02,0x0a,0x16,0x27,0x3a,0x51,0x69
};
union UniT
{
uint m_nT;
uchar m_ucT[2];
}idata uT;
/*************************** 函数声明部分 ***************************/
void Display1(void);
void Display2(void);
void Scankey(void);
void DisposeKEY(void);

/******************** 按键处理程序 ******************/

void DisposeKEY(void)
{
if (cKey1==0) { if(cF<134)cF++;else cF = 1;nDelayKey = 2000;}
else if (cKey2==0){if(cF>1)cF--;else cF = 135;nDelayKey = 2000;}
else if (cKey3==0){if(bStill==0) { cMode++;cMode &= 3; bStill = 1;}}
//switch(cKey)
//{
//case 0x30: /* 例如:KeyADD */
// if(cF<134)cF++;
// else cF = 1;
// nDelayKey = 2000; /* 按住键不动,可连续产生键值,相当于连续按键 */
// break;
// case 0x28: /* 例如:KeySUB */
// if(cF>1)cF--;
// else cF = 135;
// nDelayKey = 2000;
// break;
// case 0x18:
// if(bStill==0)
// {
// cMode++; /* 假设有4种显示状态 */
// cMode &= 3;
// bStill = 1; /* 如果没松键就不会再改变显示方式 */
// }
// break;
// default:break;
// }

Display2();
cKey = 0;
}
void Display2(void)
{
uchar i;
acLED[0]=acLedSegCode[cMode+10]; /* LED显示第1位 */
acLED[1]=acLedSegCode[cF/100]; /* LED显示第2位 */
acLED[2]=acLedSegCode[cF/10%10]; /* LED显示第3位 */
acLED[3]=acLedSegCode[cF%10]; /* LED显示第4位 */
uT.m_nT=38-5760/cF;

switch(cMode)
{
case 0:
for(i=0;i<16;i++)Out[i] = 255; //方波
for(i=16;i<32;i++)Out[i] = 0;
break;
case 1:
for(i=0;i<32;i++)Out[i] = tosin[i]; //正弦波
break;
case 2:
for(i=0;i<16;i++)Out[i] = i << 4; //三角波
for(i=16;i<32;i++)Out[i] = 255-i<<4;
break;
case 3:
for(i=0;i<32;i++)Out[i] = i<<3; //锯齿波
break;
}
}
/************************** 主函数 *****************************/
void main(void)
{
P3_7=0;
/**************** 定时器初始化 *******************/
TMOD= 0x12; /* 定义定时器0工作于方式2(8位自动重装),定时器1工作于方式1(16位定时器) */
uT.m_nT=18-2880/cF;
TH1 =uT.m_ucT[0];
TL1 =uT.m_ucT[1];
TR1 = 1;
ET1 = 1;
IP = 0x04; /* T1中断优先 */

TH0 = -200; /* 8位自动重装定时器约每100uS中断1次,9216次为1秒 */
TL0 = -200;
TR0 = 1;
ET0 = 1;

EA = 1; /* 开总中断 */

while(1)
{
if(cKey)
{
DisposeKEY(); /* 响应按键操作 */
}
}
}
/****************** 多任务时序控制时钟中断 *********************/
void IntT0(void) interrupt 1 /* 定时器0中断,完成1秒定时和LED延时 */
{
P0 = 0; /* 先清显示再换位选 */
P2 = acLEDCS[cScanIndex]; /* 送位选数据 */
P0 = acLED[cScanIndex++]; /* 送显示数据,位选指针移位 */
cScanIndex &= 3; /* 位选指针回位 */

/************************* 扫描按键程序 ******************/
if(nDelayKey==0)
{
cKey = P2 & 0x0e; // 取键值P2.3、P2.2、P2.1
if(cKey != 0x0e)nDelayKey=100;// 设置延迟时间削颤
else
{
bStill = 0;
} // 松键
}
else // 有按键利用DelayKey按键消颤
{
nDelayKey--;
if(nDelayKey==0)
{
cKeyCode = P2 &0x0e;
if(cKey != cKeyCode)
{
cKeyCode = 0;
}
}
}

}
/****************** 可控制定时时间间隔的时钟中断 *********************/
void IntT1(void) interrupt 3 /* 定时器1中断,记录T1计时溢出次数 */
{
TL1 =uT.m_ucT[1];
TH1 =uT.m_ucT[0];
P1 = Out[Num++];
Num &= 31;
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2020-01-28
做综合设计的吗?
给你个程序自己看看
#include"at89x51.h"
#define
uchar
unsigned
char
#define
uint
unsigned
int
#define
ulong
unsigned
long
/*************************
全局变量定义部分
**************************/
//硬件设计接口不同,要修改下一行
uchar
code
acLEDCS[]={0x7f,0xbf,0xdf,0xef};
uchar
code
acLedSegCode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x58,0x5e};/*
段码
*/
uchar
acLED[4];
/*
显示缓冲区
*/
char
cScanIndex;
/*
位选指针0~3
*/
uchar
cKey;
sbit
cKey1=P2^2;
sbit
cKey2=P2^1;
sbit
cKey3=P2^0;
uchar
cKeyCode;
uchar
cLongDelay;
uchar
Out[32];
bit
bStill;
/*
是否松键标志
*/
uint
nDelayKey=0;
/*
键盘延时变量,为定时中断间隔时间的整数倍
*/
uchar
cMode=0;
uchar
Num;
uchar
cF=100;
uchar
code
tosin[32]={
0x80,0x99,0xb1,0xc7,0xda,0xea,0xf6,0xfd,
0xff,0xfd,0xf5,0xe9,0xd8,0xc5,0xae,0x96,
0x80,0x66,0x4e,0x38,0x25,0x15,0x09,0x02,
0x00,0x02,0x0a,0x16,0x27,0x3a,0x51,0x69
};
union
UniT
{
uint
m_nT;
uchar
m_ucT[2];
}idata
uT;
/***************************
函数声明部分
***************************/
void
Display1(void);
void
Display2(void);
void
Scankey(void);
void
DisposeKEY(void);
/********************
按键处理程序
******************/
void
DisposeKEY(void)
{
if
(cKey1==0)
{
if(cF<134)cF++;else
cF
=
1;nDelayKey
=
2000;}
else
if
(cKey2==0){if(cF>1)cF--;else
cF
=
135;nDelayKey
=
2000;}
else
if
(cKey3==0){if(bStill==0)
{
cMode++;cMode
&=
3;
bStill
=
1;}}
//switch(cKey)
//{
//case
0x30:
/*
例如:KeyADD
*/
//
if(cF<134)cF++;
//
else
cF
=
1;
//
nDelayKey
=
2000;
/*
按住键不动,可连续产生键值,相当于连续按键
*/
//
break;
//
case
0x28:
/*
例如:KeySUB
*/
//
if(cF>1)cF--;
//
else
cF
=
135;
//
nDelayKey
=
2000;
//
break;
//
case
0x18:
//
if(bStill==0)
//
{
//
cMode++;
/*
假设有4种显示状态
*/
//
cMode
&=
3;
//
bStill
=
1;
/*
如果没松键就不会再改变显示方式
*/
//
}
//
break;
//
default:break;
//
}
Display2();
cKey
=
0;
}
void
Display2(void)
{
uchar
i;
acLED[0]=acLedSegCode[cMode+10];
/*
LED显示第1位
*/
acLED[1]=acLedSegCode[cF/100];
/*
LED显示第2位
*/
acLED[2]=acLedSegCode[cF/10%10];
/*
LED显示第3位
*/
acLED[3]=acLedSegCode[cF%10];
/*
LED显示第4位
*/
uT.m_nT=38-5760/cF;
switch(cMode)
{
case
0:
for(i=0;i<16;i++)Out[i]
=
255;
//方波
for(i=16;i<32;i++)Out[i]
=
0;
break;
case
1:
for(i=0;i<32;i++)Out[i]
=
tosin[i];
//正弦波
break;
case
2:
for(i=0;i<16;i++)Out[i]
=
i
<<
4;
//三角波
for(i=16;i<32;i++)Out[i]
=
255-i<<4;
break;
case
3:
for(i=0;i<32;i++)Out[i]
=
i<<3;
//锯齿波
break;
}
}
/**************************
主函数
*****************************/
void
main(void)
{
P3_7=0;
/****************
定时器初始化
*******************/
TMOD=
0x12;
/*
定义定时器0工作于方式2(8位自动重装),定时器1工作于方式1(16位定时器)
*/
uT.m_nT=18-2880/cF;
TH1
=uT.m_ucT[0];
TL1
=uT.m_ucT[1];
TR1
=
1;
ET1
=
1;
IP
=
0x04;
/*
T1中断优先
*/
TH0
=
-200;
/*
8位自动重装定时器约每100uS中断1次,9216次为1秒
*/
TL0
=
-200;
TR0
=
1;
ET0
=
1;
EA
=
1;
/*
开总中断
*/
while(1)
{
if(cKey)
{
DisposeKEY();
/*
响应按键操作
*/
}
}
}
/******************
多任务时序控制时钟中断
*********************/
void
IntT0(void)
interrupt
1
/*
定时器0中断,完成1秒定时和LED延时
*/
{
P0
=
0;
/*
先清显示再换位选
*/
P2
=
acLEDCS[cScanIndex];
/*
送位选数据
*/
P0
=
acLED[cScanIndex++];
/*
送显示数据,位选指针移位
*/
cScanIndex
&=
3;
/*
位选指针回位
*/
/*************************
扫描按键程序
******************/
if(nDelayKey==0)
{
cKey
=
P2
&
0x0e;
//
取键值P2.3、P2.2、P2.1
if(cKey
!=
0x0e)nDelayKey=100;//
设置延迟时间削颤
else
{
bStill
=
0;
}
//
松键
}
else
//
有按键利用DelayKey按键消颤
{
nDelayKey--;
if(nDelayKey==0)
{
cKeyCode
=
P2
&0x0e;
if(cKey
!=
cKeyCode)
{
cKeyCode
=
0;
}
}
}
}
/******************
可控制定时时间间隔的时钟中断
*********************/
void
IntT1(void)
interrupt
3
/*
定时器1中断,记录T1计时溢出次数
*/
{
TL1
=uT.m_ucT[1];
TH1
=uT.m_ucT[0];
P1
=
Out[Num++];
Num
&=
31;
}
第2个回答  2009-05-02
频率可调:我觉得用一个滑动变阻器来调节,单片机通过AD采集滑动变阻器阻值,换算出目标频率,然后就是单片机处理了
第3个回答  2013-03-28
我做的信号发生器,怎么用proteus仿真可以,但是把硬件做好后,用示波器看就不行了啊
相似回答