當前位置:首頁 » 編程語言 » 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來輸出。