单片机pwm频率和周期可调
2020-02-20 来源:51hei
//------------------------------------------------------------------------------------
//程序功能简介:本程序产生15HZ~~~50KHZ的方波,并且实现频率和脉宽的独立调制,即可
//在改变频率的同时不改变脉宽,再改变脉宽的同时不改变频率;同时设置
//两个调节步长------在KEY键按下时,粗调,没有按下时,细调;
//程序思路: 本程序用到两个定时器------定时器0和定时器1,其中定时器0工作在定时方式下,
//决定方波的频率;定时器1,同样工作在定时方式下,用于设定脉宽;
//------------------------------------------------------------------------------------
#include #include #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; } } }