当前位置:首页 » 编程语言 » c语言正弦信号发生器
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

c语言正弦信号发生器

发布时间: 2022-09-22 14:07:30

Ⅰ 产生三角波数据值的C程序,

/**************************************/
/* 信号发生器 (正弦波,方波,三角波) */
/*************************************/
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

sbit cs=P2^0; //tlc5615片选端口
sbit clk=P2^1; //tlc5615时钟线
sbit din=P2^2; //tlc5615传输端口

sbit key1=P1^0;
sbit key2=P1^1; //按键的单片机接口

uchar keydat;

uchar flag; //波形发生终止信号的标志位 一旦被置零立马停止发信号
uchar flagsqu; //方波高低电平控制为(运用定时器1中断控制)
uchar m,num;
uchar dat=0xff;

uchar code tosin[141]={ //正弦波的编码
0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0a,0x0b,0x0d,0x0e,0x10,0x11,0x13,0x15,0x16,
0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,
0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,0x40,0x43,0x45,
0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,
0x66,0x69,0x6c,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,
0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7e,
0x7f,0x80,0x7f,0x7e,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,
0x78,0x77,0x76,0x75,0x74,0x73,0x72,0x6f,0x6c,0x69,
0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,0x4e,0x4c,
0x48,0x45,0x43,0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,
0x2e,0x2b,0x29,0x27,0x25,0x22,0x20,0x1e,0x1c,0x1a,
0x18,0x16,0x15,0x13,0x11,0x10,0x0e,0x0d,0x0b,0x0a,
0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,
0x00};

void delay(uchar z) //延时函数
{
uchar x,y;
for(x=0;x<110;x++)
for(y=z;y>0;y--);

}
void prepare() //tlc5615的初始化
{
cs=1;
din=1;
clk=0;
cs=0; //cs的上升沿和下降沿必须在clk为低时进?
}
/* 用中断来产生方波
void Squtranslator()
{
TR1=1; //启动定时器1 控制高低电平的持续时间 占空比
do{
do{
_wave=0;
}while((!flagsqu) && flag==1);//如果一旦终止信号的
//产生可以立马退出循环
flagsqu=0;
do{
_wave=1;
}while((!flagsqu) && flag==1);
flagsqu=0;
}while(flag);
flag=1;
TR1=0;
}
*/

void Squtranslator() //方波函数
{
uchar j;
uchar dat1=0x7f;
while(flag)
{
do{
prepare();
dat=dat1;
for(j=0;j<12;j++)
{
din=(bit)(dat>>7); //将数据的最高位赋给din
clk=1;
dat=dat<<1; //一位位的传输
clk=0;
}
cs=1; //cs的上升沿和下降沿必须在clk为低时进行
delay(200); //使高低电平持续一段时间
if(dat1==0)
dat1=0x7f; //完成了0和0x7f之间的替换
else
dat1=0;
}while(flag);
}

}

void Tratranslator() //锯齿波的发生函数
{
uchar j;
uchar dat1=0x7f;
while(flag)
{
do{
prepare();
dat=dat1;
for(j=0;j<12;j++)
{
din=(bit)(dat>>7); //将数据的最高位赋给din
clk=1;
dat=dat<<1; //一位位的传输
clk=0;
}
cs=1; //cs的上升沿和下降沿必须在clk为低时进行
delay(2); //稍加延时
dat1--;
}while(flag && dat1); //一旦有终止信号就可以停止
do{
prepare();
dat=dat1;
for(j=0;j<12;j++)
{
din=(bit)(dat>>7); //将数据的最高位赋给din
clk=1;
dat=dat<<1; //一位位的传输
clk=0;
}
cs=1; //cs的上升沿和下降沿必须在clk为低时进行
delay(2); //稍加延时
dat1++;
}while(flag && (!(dat1==0x7f)));
}
}

void Sintranslator(uchar wave[],uchar num )//正弦波的转换函数
{
uchar i,j;
uchar dat1;
do{
for(i=0;i<num;i++)
{
prepare();
dat1=wave[i]; //打开片选 开始工作
for(j=0;j<12;j++)
{
din=(bit)(dat1>>7); //将数据的最高位赋给din
clk=1;
dat1=dat1<<1; //一位位的传输
clk=0;
if(flag==0)break;
}
cs=1; //cs的上升沿和下降沿必须在clk为低时进行
delay(1); //稍加延时
if(flag==0)break;
}
}while(flag); //等待控制键的暂停
}

void keyscan() //切换功能按键返回键值函数
{
uchar i;
for(i=0;i<4;i++)
{
if(key1==0)
{
delay(10);
if(key1==0)
{
keydat++;
do{}while(!key1); //松手检测
if(keydat==4)keydat=1;//加满回零处理
}
}
}
}
void keycountrl() //切断输出控制函数
{
if(key2==0)
{
delay(10);
if(key2==0)
{
flag=0;
do{}while(!key2); //松手检测
}
}
}
void main ()
{
uchar temp;
TMOD=0x01; //确定定时器的工作方式
TH0=(65536-50000)/256; //给定时器0赋予初值
TL0=(65536-50000)%256;
EA=1; //开总中断
ET0=1; //开启定时器0中断
TR0=1;
while(1)
{
do{
switch(keydat)
{
case

Ⅱ 请求牛人解答 DAC0832正弦信号发生器程序

1.这个程序频率值是怎么设定的?
就是通过key_up ,key_dw来设定的,type【】里面的数已经按照不同频率的正弦波,算出不同点的值(用于da转换),用查表的方法来设定频率值(到底要的是哪一个频率值,通过counter的大小选择type里的某一串数送给da来决定)
2. while(1)
{
if(key_up == 0) if(step<4096) step++;
if(key_dw == 0) if(step>1) step--;
while((!key_up)||(!key_dw));
}
这是什么意思?4096这些是什么意思。。。
key_up ,key_dw 这两个端口应该是接按键了吧,采用查询的方法判断键是否按下,
while((!key_up)||(!key_dw));按键按下后等待按键释放!4069的意思,比如说你要访问一组数组,数组只有10个元素,你能访问第十一个元素吗?去学一下什么是type型的数,就知道为何是4069了。
3.程序看不太懂,急需大致讲解。
单片机和c语言你要是一点也不会,我肯定给你讲不懂的,你要是会的话,多看几遍肯定就会了
希望能帮到你!
#include<reg51.h>
#include<absacc.h> //定义绝对地址访问的头文件
#define dac1 XBYTE[0xdfff] // X 轴0832一级琐存地址
unsigned char code type[256]={ //一堆数,一堆不同频率正弦波的正弦值
0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb0,0xb3,0xb6,0xb9, 0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,
0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf4,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,
0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe3,0xe1,0xde,0xdc,0xda,0xd8,0xd6,0xd3,
0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,
0x99,0x96,0x92,0x8f,0x8c,0x89,0x86,0x83,0x80,0x7d,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x64,0x61,0x5e,
0x5b,0x58,0x55,0x52,0x4f,0x4c,0x49,0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,
0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x14,0x12,0x10,0xf,0xd,0xc,0xb,0x9,0x8,0x7,0x6,0x5,0x4,
0x3,0x3,0x2,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x2,0x3,0x3,0x4,0x5,0x6,0x7,
0x8,0x9,0xa,0xc,0xd,0xe,0x10,0x12,0x13,0x15,0x17,0x18,0x1a,0x1c,0x1e,0x20,0x23,0x25,0x27,0x29,0x2c,
0x2e,0x30,0x33,0x35,0x38,0x3b,0x3d,0x40,0x43,0x46,0x48,0x4b,0x4e,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,
0x66,0x69,0x6c,0x6f,0x73,0x76,0x79,0x7c};
unsigned char i,j;
unsigned int counter,step;
sbit key_up = P3^2;
sbit key_dw = P3^3; //按键定义
//定时器0初始化
void Init_Timer0(void)
{
TMOD = (TMOD & 0XF0) | 0X01;
TH0 = 0xff;
TL0 = 0xff;
TR0 =1;
ET0 =1;
}

main()
{
Init_Timer0();
step=2;
EA = 1;
while(1) //判断按键
{
if(key_up == 0) if(step<4096) step++;
if(key_dw == 0) if(step>1) step--;
while((!key_up)||(!key_dw));
}
}

// 系统OS定时中断服务
void OS_Timer0(void) interrupt 1 using 2 //定时子程序
{
TH0 = 0xff;
TL0 = 0xff;
counter = counter + step;
dac1=type[(unsigned int)counter>>8]; //根据键值,选择某一个频率的正弦波,送入da转换!
}

Ⅲ 简易函数信号发生器C语言编写

我没做过正弦波和三角波,我认为正弦波做的话用带DA功能的单片机,但是你没说正弦波的频率和赋值,三角波也可以用DA做,方波就很简单了用拉高活拉低口线就可以了。你直接用单片机做,不用外围电路吗??

Ⅳ 51 单片机和DAC0832输出方波、矩形波和正弦波由液晶1602显示的C语言程序

显示频率,幅度可调,可产生四种波形,正弦波,方波,锯齿波,三角波,希望你能喜欢,给你发了一张效果图,喜欢的话别忘了采纳我的回答啊

#include<reg52.h>

#defineucharunsignedchar

#defineuintunsignedint

#defineDAdataP0 //DA数据端口

sbitDA_S1=P2^0;//控制DAC0832的8位输入寄存器,仅当都为0时,可以输出数据(处于直通状态),否则,输出将被锁存

sbitDA_S2=P2^1;//控制DAC0832的8位DAC寄存器,仅当都为0时,可以输出数据(处于直通状态),否则,输出将被锁存

sbitkey=P3^2;

ucharwavecount;//'抽点'计数

ucharTHtemp,TLtemp;//传递频率的中间变量

ucharjudge=1;//在方波输出函数中用于简单判别作用

ucharwaveform; //当其为0、1、2时,分别代表三种波

ucharcodefreq_unit[3]={10,50,200};//三种波的频率单位

ucharidatawavefreq[3]={1,1,1}; //给每种波定义一个数组单元,用于存放单位频率的个数

ucharcodelcd_hang1[]={"SineWave""TriangleWave""SquareWave""SelectWave:""pressNo.1key!"};

ucharidatalcd_hang2[16]={"f=Hz"};

ucharcodewaveTH[]={

0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

0xec,0xf6,0xf9,0xfb,0xfc,0xfc,0xfd,0xfd,0xfd,0xfe};

ucharcodewaveTL[]={

0x06,0x8a,0x10,0x4e,0x78,0x93,0xa8,0xb3,0xbe,0xc6,//正弦波频率调整中间值

0xac,0xde,0x48,0x7a,0x99,0xaf,0xbb,0xc8,0xd0,0xde, //三角波频率调整中间值

0x88,0x50,0x90,0x32,0x34,0xbe,0x4a,0xa3,0xe5,0x2c};

/*************************************************************************************************/

ucharcodetriangle_tab[]={ //每隔数字8,采取一次

0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,

0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0,0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8,0xff,

0xf8,0xf0,0xe8,0xe0,0xd8,0xd0,0xc8,0xc0,0xb8,0xb0,0xa8,0xa0,0x98,0x90,0x88,0x80,

0x78,0x70,0x68,0x60,0x58,0x50,0x48,0x40,0x38,0x30,0x28,0x20,0x18,0x10,0x08,0x00};

ucharcodesine_tab[256]={

//输出电压从0到最大值(正弦波1/4部分)

0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb1,0xb4,0xb7,0xba,0xbc,

0xbf,0xc2,0xc5,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,0xda,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,

0xee,0xef,0xf1,0xf2,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,

//输出电压从最大值到0(正弦波1/4部分)

0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf2,0xf1,0xef,

0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,

0xbf,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,

//输出电压从0到最小值(正弦波1/4部分)

0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,0x4e,0x4c,0x48,0x45,0x43,

0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2e,0x2b,0x29,0x27,0x25,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16,0x15,0x13,

0x11,0x10,0x0e,0x0d,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,

//输出电压从最小值到0(正弦波1/4部分)

0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,

0x11,0x13,0x15,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,

0x40,0x43,0x45,0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66,0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80};

voiddelay(ucharz)

{

uintx,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);

}

voidtriangle_out() //三角波输出

{

DAdata=triangle_tab[wavecount++];

if(wavecount>64)wavecount=0;

DA_S1=0;//打开8位输入寄存器

DA_S1=1;//关闭8位输入寄存器

}

voidsine_out() //正弦波输出

{

DAdata=sine_tab[wavecount++];

DA_S1=0;//打开8位输入寄存器

DA_S1=1;//关闭8位输入寄存器

}

voidsquare_out()//方波输出

{

judge=~judge;

if(judge==1)DAdata=0xff;

elseDAdata=0x00;

DA_S1=0;//打开8位输入寄存器

DA_S1=1;//关闭8位输入寄存器

}

/************1602液晶的相关函数*************/

#definelcd_portsP1

sbitrs=P2^2;

sbitrw=P2^3;

sbitlcden=P2^4;

voidwrite_com(ucharcom)

{

rs=0; //置零,表示写指令

lcden=0;

lcd_ports=com;

delay(5);

lcden=1;

delay(5);

lcden=0;

}

voidwrite_date(uchardate)

{

rs=1; //置1,表示写数据(在指令所指的地方写数据)

lcden=0;

lcd_ports=date;

delay(5);

lcden=1;

delay(5);

lcden=0;

}

voiddisp_lcd(ucharaddr,uchar*temp1)

{

ucharnum;

write_com(addr);

delay(1);//延时一会儿???

for(num=0;num<16;num++)

{

write_date(temp1[num]);//或者这样写write_date(*(temp1+num));

delay(1);

}

}

voidinit_lcd()

{

//ucharnum;

lcden=0;//可有可无???

rw=0;//初始化一定要设置为零,表示写数据

write_com(0x38);//使液晶显示点阵,为下面做准备

write_com(0x0c);//初始设置

write_com(0x06);//初始设置

write_com(0x01);//清零

write_com(0x80);//使指针指向第一行第一格

disp_lcd(0x80,&lcd_hang1[3*16]);//在第一行显示

disp_lcd(0xc0,&lcd_hang1[4*16]);//在第二行显示

}

/********************1602液晶函数声明结束*********************/

voidmain()

{

uchari=0;

DA_S2=0;//使DAC寄存器处于直通状态

DAdata=0;

DA_S1=1;//关闭8位输入寄存器

init_lcd();

waveform=0;

TMOD=0x01;//设置定时器0为16位工作方式

IT0=1;//设置外部中断0为下降沿触发

ET0=1;//开定时器中断

EX0=1;

EA=1;

while(1)

{

//DAout(0xff); //可输出TTL波形

//DAout(0x80);

//T_temp=32;

}

}

voidtimer0()interrupt1

{

TH0=THtemp;

TL0=TLtemp;

if(waveform==0)sine_out();

elseif(waveform==1)triangle_out();

elseif(waveform==2)square_out();

}

voidkey_int0()interrupt0

{

ucharkeytemp;

uinttotal_freq;//总频率

EA=0;TR0=0;//关总中断与定时器

delay(5);//延时够吗???

if(key==0)//确实有按键按下而引发中断

{

keytemp=P3&0xf0;//获取P3口高四位的值

switch(keytemp)

{

case0xe0: //选择波形

waveform++;

if(waveform>2)waveform=0;

break;

case0xd0://频率按规定单位依次增加

wavefreq[waveform]++;

if(wavefreq[waveform]>10)wavefreq[waveform]=1;///*这边要用“>10”,因为它比“=11”可靠

break; //性更高,使加数有个上限,不会一直加下去*/

case0xb0://频率按规定单位依次衰减

wavefreq[waveform]--;

if(wavefreq[waveform]<1)wavefreq[waveform]=10;//这边要用“<1”,因为它比“=0”可靠性更高

break;

case0x70://TTL输出

DA_S2=1;//使DAC寄存器关闭

break;

}

THtemp=waveTH[waveform*10+(wavefreq[waveform]-1)];//方括号中选取第几个数后,并把该值赋给T_temp

TLtemp=waveTL[waveform*10+(wavefreq[waveform]-1)];

total_freq=wavefreq[waveform]*freq_unit[waveform];//求输出频率(个数*单位)

lcd_hang2[5]=total_freq%10+0x30;//在液晶中显示个位,(0x30在液晶显示中表示数字0)

total_freq/=10;lcd_hang2[4]=total_freq%10+0x30;//在液晶中显示时十位

total_freq/=10;lcd_hang2[3]=total_freq%10+0x30;//在液晶中显示时百位

total_freq/=10;lcd_hang2[2]=total_freq%10+0x30;//在液晶中显示时千位

disp_lcd(0x80,&lcd_hang1[waveform*16]);//在第一行显示

disp_lcd(0xc0,lcd_hang2);//在第二行显示

}

wavecount=0;//'抽点'计数清零

while(!key);

EA=1;TR0=1;//开启总中断与定时器

}

Ⅳ 用一8位DA转换器设计一正弦信号发生器,要求实现任一频率正弦信号的输出。

首先,要用matlab算出一个正弦表,我想matlab你一定学过。
得到正弦表以后,放在程序里面,假如你采了100个样的话,就是把一个正弦波完整的周期分成了100份,轮流把这100个数通过单片机送给dac0832就是了。
任一频率,这个说的不够准确,应该给出一定的范围,以51的速度,能出20K的正弦波就已经很够意思了~~~
频率可调,这个简单,100个数,你可以把一个正弦波的周期(当然是你想要的周期时间长度),分成100份,就是除以100,然后用51的定时器定时出这么长的时间,然后让定时器出发中断,在中断服务程序中送出相应的数据(100个数据中的一个,设定一个全局变量,每执行一次中断自动让它加1,加到100变成0,继续加,循环)
这个不难的,自己多努努力,会成功的。

Ⅵ 51单片机信号发生器的正弦波程序

首先,我要声明一点,单片机的浮点数处理能力非常弱的,你这个程序,基础可以用数组查表的方法来做,当然,你这么错不是不行,初学者可以用来做实验,但是高手可不会这么错。
言归正传,我来给你讲解一下这个do里面的思路。我们分步来看,先看sin(x),从 -3.1415---+3.1415
sin(x)的数值是多少?答案是0到-1再到0再到1再到0,这么个过程,这是高中的数学知识,如果你不明白,我就没有办法了。
搞明白了sin(x)的变化范围,我们就不难明白,如果不加以限制的,直接用 255*sin(x),那么,这个结果就会出现负数,变化范围是 0----(-255)---(0)----(255)---0,因为你需要把这个数值赋值给P1口,那么,你知道如果把一个负数赋值给 P1口是什么结果吗?因为负数在单片机里是用补码表示的,所以,把一个负数表示成无符号的数,它是很大的,所以P1口就会乱。
所以,为了避免负数,就要把sin(x)里产生的负数抵消去,怎么抵消?我们知道,sin(x)最小值是 -1,所以,只要 (1 + sin(x)),那么,这个结果就永远不可能小于0,这个的变化范围是
1----0----1----2----1
最大的数值是2,最小的是0
然后乘以 255再给P1口送去,我们又知道,P1口最大只能到 255,而你的式子(1 + sin(x))
最大是2,(1 + sin(x))*255最大得到的是 510,那为了不失真,所以,要把(1 + sin(x))*255再除以一个2,就得到你上面的结果了。
如果你是用的DA转换器,通过示波器,你可以看到一个如下公式的波形:
f = 2.5*sin(2*3.1415926*f) + 2.5
这样的函数波形。

Ⅶ 单片机C语言版正弦波信号发生器怎么做

#include<at89x51.h>
//unsigned char TIME0_H=0xec,TIME0_L=0x78; //定时器0的初值设置;全局变量
#include<sinx.h>
#include<0832.h>
void main()
{
TMOD=0X01;
TH0=0xff;
TL0=0xd9;
IT0=1; //设置中断触发方式,下降沿
EA=1;
EX0=1;
ET0=1;
IP=0X01; //键盘中断级别高
TR0=1;
while(1)
{
// square();
;
}
}

#ifndef __0832_h__
#define __0832_h__
//#define INPUT XBYTE[0xbfff] //即cs 与xfer 轮流低电平。
//#define DACR XBYTE[0x7fff] //单通道输出,单缓冲就行了。
unsigned char i,sqar_num=128; //最大值100,默认值50
unsigned char cho=0; //0:正弦波。1:方波。2:三角波。3:锯齿波。
unsigned char num=0;
unsigned char TIME0_H=0xff,TIME0_L=0xd9; //定时器0的初值设置;全局变量.对应正弦波,锯齿波50HZ
sbit chg= P1^0; //三角波100Hz.
sbit freq_u=P1^1;
sbit freq_d=P1^2;
sbit ty_u=P1^3;
sbit ty_d=P1^4;
sbit cs =P3^7;
bit flag=0;
unsigned int FREQ=50;//初始化频率,50HZ
//调节部分——频率
void freq_ud(void)
{
unsigned int temp;
if(freq_d==0)
{ FREQ--; }
else if(freq_u==0)
{ FREQ++; }
if(cho==1|cho==3) //锯齿波256次中断一周期,特殊处理下。否则他的频率是100(+\-)n*2Hz.
{
temp=0xffff-3906/FREQ; //方波,三角波默认为100hz,切换后频率也为50HZ 65336-10^6/(256*FREQ)
TIME0_H=temp/256;
TIME0_L=temp%256;
}
else if(cho==0|cho==3){ //正弦波 三角波默认周期50hz 65536-10^6//(512*FREQ)
temp=0xffff-1953/FREQ;
TIME0_H=temp/256;
TIME0_L=temp%256;
}
}
//调节部分——方波的占空比
void ty_ud(void) //方波也采用512次中断构成一个周期。
{
if(ty_d==0&sqar_num>0)
sqar_num--;
else if(ty_u==0&sqar_num<255)
sqar_num++;
}
//波形发生函数
void sint(void)
{
if(!flag)
{
cs=0;P2=sin_num[num++];cs=1;
if(num==0){num=255;flag=1;}
}
else if(flag)
{
cs=0;P2=sin_num[num--];cs=1;
if(num==255){num=0;flag=0;}
}
}
void square(void)
{
if(i++<sqar_num) {cs=0;P2=0XFF;cs=1;}
else{cs=0;P2=0X00;cs=1;}
}
void triangle(void)
{
cs=0;P2=num++;cs=1;
}
void stw(void)
{
if(~flag)
{
cs=0;P2=num++;cs=1;
if(num==0){num=255;flag=1;}
}
else if(flag)
{
cs=0;P2=num--;cs=1;
if(num==255){num=1;flag=0;}
}
}
//按键中断处理程序。
void it0() interrupt 0
{
if(chg==0) { if(++cho==4) {cho=0;num=0;} } //num=0;所有数据从新开始,保证波形的完整性
else if(freq_u==0|freq_d==0)
{freq_ud();}
else if (cho==1&(ty_d==0|ty_u==0))
{ty_ud();}
else ;
}
//定时器中断处理程序。
void intt0() interrupt 1
{
//TH0=0x00;TL0=0x00;sinx();
switch(cho)
{
case 0:{TH0=TIME0_H;TL0=TIME0_L;sint() ;break;} //正弦波//每半周期256取样。
case 1:{TH0=TIME0_H;TL0=TIME0_L;square(); break;} //方波 //为了提高方波的最高频率,只有牺牲占空比的最小可调值。分100份 每次1%。
case 2:{TH0=TIME0_H;TL0=TIME0_L;triangle();break;} //三角波
case 3:{TH0=TIME0_H;TL0=TIME0_L;stw(); break;} //锯齿波
default: ;
}
}
#endif

//正弦表;每半个周期256个取值,最大限度保证波形不失真。
//各个值通过MATLAB算出,并四设五如取整。具体程序如下
#ifndef __sinx_h__
#define __sinx_h__
unsigned char code sin_num[]={
0,0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2,
2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
10, 10, 11, 12, 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 20, 21,
22, 23, 24, 25, 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37,
38, 39, 40, 41, 42, 44, 45, 46, 47, 49, 50, 51, 52, 54, 55, 56,
57, 59, 60, 61, 63, 64, 66, 67, 68, 70, 71, 73, 74, 75, 77, 78,
80, 81, 83, 84, 86, 87, 89, 90, 92, 93, 95, 96, 98, 99, 101,102,
104, 106, 107, 109, 110, 112, 113, 115, 116, 118, 120, 121, 123, 124, 126, 128,
129, 131, 132, 134, 135, 137, 139, 140, 142, 143, 145, 146, 148, 149, 151, 153,
154, 156, 157, 159, 160, 162, 163, 165, 166, 168, 169, 171, 172, 174, 175, 177,
178, 180, 181, 182, 184, 185, 187, 188, 189, 191, 192, 194, 195, 196, 198, 199,
200, 201, 203, 204, 205, 206, 208, 209, 210, 211, 213, 214, 215, 216, 217, 218,
219, 220, 221, 223, 224, 225, 226, 227, 228, 229, 230, 230, 231, 232, 233, 234,
235, 236, 237, 237, 238, 239, 240, 240, 241, 242, 243, 243, 244, 245, 245, 246,
246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253,
253, 253, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255
};
#endif
//MATLAB程序:
//x=linspace(-pi/2,pi/2,255);%如果过采用1位采用,很多值是重的。虽然实际中并不会。
//y=(sin(x)+1)/2.0*255;
//%uint32(y)%强制类型转换。
//%fprintf('%.f\n',uint32(y));%控制输出类型
//round(y)%四舍五入函数

Ⅷ 单片机C语言版信号发生器

单片机信号发生器,一般是通过控制单片机的IO的高低电平来实现的,具体为
1,可以通过先配置一个管脚为输出,然后给这个管脚写0,输出就为低电平,然后写1,这个管脚就输出为高电平。如果你的单片机是3.3v供电的话,那么高电平一般为3.3V,低电平一般为0v。
2,如果要产生一个方波的话,需要先输出1,然后延迟一段时间,然后再输出0,然后再延迟一段时间,然后输出1.... 要如此反复的话,可以用while(1), 然后在while(1)里面写入你的置高,延迟,置低的代码,具体伪代码可以为
配置对应输出管脚为输出; //因为管脚可以配置为输出和输入,所以需要先配置为输出
while(1)
{
对对应输出管脚置高;
sleep(半个周期的时间);
对对应输出管脚置低;
sleep(半个周期的时间);
}
3, 如果你牵涉到高级应用的话,比如要输出一个正弦波,那么需要外加信号产生芯片,比如DDS芯片。
4,如果还需要更加复杂的信号,任意波形的,可以用一个片内DA按照你的意思输出对应的电平,或者片外DA来输出。