/------------------------------------------------------------------------------------
//程序功能簡介:本程序產生15HZ~~~50KHZ的方波,并且實現頻率和脈寬的獨立調制,即可
//在改變頻率的同時不改變脈寬,再改變脈寬的同時不改變頻率;同時設置
//兩個調節步長------在KEY鍵按下時,粗調,沒有按下時,細調;
//程序思路: 本程序用到兩個定時器------定時器0和定時器1,其中定時器0工作在定時方式下,
//決定方波的頻率;定時器1,同樣工作在定時方式下,用于設定脈寬;
//------------------------------------------------------------------------------------
#include <reg52.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
#define ALL 65536 //定時器工作方式1時,最大基數長度 65536;
#define F_osc 12000000 //晶振頻率12M;
sbit KEY_F_UP=P0^2; //頻率上調按鈕;
sbit KEY_F_DOWN=P0^3; //頻率下調按鈕;
sbit KEY_W_UP=P0^4; //脈寬上調按鈕;
sbit KEY_W_DOWN=P0^5; //脈寬下調按鈕;
sbit KEY=P0^6; //粗細調節按鈕-----按下為粗調,否則為細調;
sbit OUTPUT=P1^0; //波形輸出;
uchar TIMER0_H,TIMER0_L,TIMER1_H,TIMER1_L;//定時器0和定時器1的初值設置;
uchar PERCENT=50; //初始占空比;
uchar FLAG_F=0,FLAG_W=0;//頻率調節標志和脈寬調制標志;
uint FREQ=50000; //初始頻率;
float temp; //臨時全局變量,用于數據傳遞;
void delay(uchar t); //延時函數,用于按鍵去抖;
void init(); //初始化函數,用于定時器的初始化;
void calculate_F();
//頻率計算函數,當頻率變化,計算出定時器0初值;
void calculate_W();
//脈寬計算函數,脈寬變化時,計算出定時器1初值;
void key_scan(); //按鍵掃描函數;
void timer0(); //定時器0中斷函數;
void timer1(); //定時器1中斷函數;
void delay(uchar t)
{
uchar i,j;
while(t--) //每個脈沖為1us
{
for(i=0;i<100;i++)
for(j=0;j<100;j++);
}
}
void calculate_F()
{
TIMER0_H = (uint)temp/256;
TIMER0_L = (uint)temp%256;
}
void calculate_W()
{
float TEMP;
TEMP = (1 - PERCENT/100.0)*ALL + temp*PERCENT/100.0;
TIMER1_H = (uint)TEMP/256;
TIMER1_L = (uint)TEMP%256;
}
void key_scan()
{
delay(4);
if(!KEY_F_UP) //頻率上調鍵按下;
{
FLAG_F=1; //置標志位;
if(!KEY)
FREQ+=10;
else
FREQ++;
if(FREQ>50000)
FREQ=1;
}
else if(!KEY_F_DOWN) //頻率下調鍵按下;
{
FLAG_F=1; //置標志位;
if(!KEY)
FREQ-=10;
else
FREQ--;
if(FREQ<1)
FREQ=50000;
}
else if(!KEY_W_UP) //脈寬上調鍵按下;
{
FLAG_W=1; //置標志位;
if(!KEY)
PERCENT+=5;
else
PERCENT++;
if(PERCENT>49)
PERCENT=1;
}
else if(!KEY_W_DOWN) //脈寬下調鍵按下;
{
FLAG_W=1; //置標志位;
if(!KEY)
PERCENT-=5;
else
PERCENT--;
if(PERCENT<1)
PERCENT=49;
}
else ;
}
void timer0() interrupt 1 //決定頻率
{
TH0=TIMER0_H;
TL0=TIMER0_L;
TR1=1; //開定時器1;
OUTPUT=1;
}
void timer1() interrupt 3 //決定脈寬
{
TH1=TIMER1_H;
TL1=TIMER1_L;
TR1=0; //關定時器1,一定要這一步,因為定時器1的定時短于定時器0;
OUTPUT=0;
}
void init()
{
TMOD=0x11; //定時器0和定時器1都工作在方式1,16位計數器;
calculate_F(); //初始為1KHZ,占空比為50%;
calculate_W();
TH0=TIMER0_H;
TL0=TIMER0_L;
TH1=TIMER1_H;
TL1=TIMER1_L;
ET0=1;
ET1=1;
EA=1;
TR0=1;
TR1=1;
}
main()
{
init();
while(1)
{
key_scan();
if(FLAG_F) //改變頻率時要注意要進行脈寬的重新設置;
{
calculate_F();
calculate_W();
FLAG_F=0;
}
if(FLAG_W) // 脈寬改變,頻率不改變;
{
calculate_W();
FLAG_W=0;
}
}
} |