void PWM_init (void){//PWM初始化函数
CMOD=0x02; //设置PCA定时器,计数频率为晶振频率/2 当为12Mhz时,PWM输出频率约234Khz
//CMOD=0x00; //设置PCA定时器,计数频率为晶振频率/12 当为12Mhz时,PWM输出频率约39Khz
//CMOD=0x04; //设置PCA定时器,计数频率为定时器0的溢出率,如果让定时器0设为16位计数模式,其溢出频率可以在很大范围内调节,从而以产生很高或很低的PWM频率
CL=0x00;
CH=0x00;
CCAPM1=0x42; //PWM1设置PCA工作方式为PWM方式(0100 0010)
CCAP1L=0x00; //设置PWM1初始值与CCAP0H相同
CCAP1H=0x00; // PWM1初始时为0
CR=1; //启动PCA定时器
}
实际上要产生低频率的PWM波,不用其硬件PWM功能完全可以
用定时器中断方式即可实现
让定时器 200us中断一次(中断不算频繁呀) ,设一变量a,每次中断a加1,100次就是20ms,,另设一变量b,数值在1-100之间,每次中断比较a和 b的大小,如果a<b,则引脚 输出高电平,否则为低电平,这样通过改变b的值,就可实现频率为50HZ,占空比1-100%可调的PWM方波
用两个定时器的方法是用定时器T0来控制频率,定时器T1来控制占空比。大致的的编程思路是这样的:T0定时器中断让一个I0口输出高电平,在这个定时器T0的中断当中起动定时器T1,而这个T1是让IO口输出低电平,这样改变定时器T0的初值就可以改变频率,改变定时器T1的初值就可以改变占空比。
用一个定时器时(如定时器T0),首先你要确定PWM的周期T和占空比D,确定了这些以后,你可以用定时器产生一个时间基准t,比如定时器溢出n次的时间是PWM的高电平的时间,则DT=nt,类似的可以求出PWM低电平时间需要多少个时间基准n'。
因为这里我们是产生周期为1ms(1000HZ)的PWM,所以可设置中断的时间基准为001ms,,然后中断100次即为1ms。在中断子程序内,可设置一个变量如time,在中断子程序内,有三条重要的语句:1、当time>=100时,time清零(此语句保证频率为1000HZ),2、当time>n时(n应该在0-100之间变化开),让单片相应的I/O口输出高电平,当time<n时,让单片相应的I/O口输出低电平,此时占空比就为%n。
参考资料:
#include<at89x51h>
unsigned char PWM0=0x80,PWM1=0x80,PWM2=0x80;//PWM的百分比
void InitT0(void)
{
TMOD=0x02;//定时器0工作方式2 8位自动重装
TH0=0;//pwm频率为系统时钟/256
TL0=0;
TR0=1;//开始计时
ET0=1;//允许定时器中断
EA=1;//开启总中断
}
void main(void)
{
InitT0();//初始化T0定时器
while(1)
{
//添加处理代码
}
}
void Timer0(void) interrupt 1//用于PWM的定时器
{
static unsigned char counter=0;//记录中断次数
counter++;
if(counter >= PWM0) P1_0 = 0; else P1_0 = 1;
if(counter >= PWM1) P1_1 = 0; else P1_1 = 1;
if(counter >= PWM2) P1_2 = 0; else P1_2 = 1;
}
// PWM 控制 LED 灯渐亮渐灭程序
// 适用 ME300B 开发系统
// 晶振为110592M
// 利用定时器控制产生占空比可变的 PWM 波
// 按K1,PWM值增加,则占空比减小,LED 灯渐暗。
// 按K2,PWM值减小,则占空比增加,LED 灯渐亮。
// 当PWM值增加到最大值或减小到最小值时,蜂鸣器将报警。//#include < reg51h >
#include < intrinsh >sbit K1 =P1^4 ; //增加键
sbit K2 =P1^5 ; //减少键
sbit BEEP =P3^7 ; //蜂鸣器
unsigned char PWM=0x7f ; //赋初值void Beep();
void delayms(unsigned char ms);
void delay(unsigned char t);//
void main()
{ P1=0xff;
TMOD=0x21 ;
TH0=0xfc ; //1ms延时常数
TL0=0x66 ; //频率调节 TH1=PWM ; //脉宽调节
TL1=0 ; EA=1;
ET0=1;
ET1=1;
TR0=1 ; while(1)
{
do{
if(PWM!=0xff)
{PWM++ ;delayms(10);}
else Beep() ;
}
while(K1==0); do{
if(PWM!=0x02)
{PWM-- ;delayms(10);}
else Beep() ;
}
while(K2==0);
}
}//
// 定时器0中断服务程序
//
void timer0() interrupt 1
{
TR1=0 ;
TH0=0xfc ;
TL0=0x66 ;
TH1=PWM ;
TR1=1 ;
P0=0x00 ; //启动输出
}//
// 定时器1中断服务程序
//
void timer1() interrupt 3
{
TR1=0 ;
P0=0xff ; //结束输出
}//
//蜂鸣器子程序
//void Beep()
{
unsigned char i ;
for (i=0 ;i<100 ;i++)
{
delay(100) ;
BEEP=!BEEP ; //Beep取反
}
BEEP=1 ; //关闭蜂鸣器
delayms(100);
} //
// 延时子程序
//
void delay(unsigned char t)
{
while(t--) ;
}//
// 延时子程序
//
void delayms(unsigned char ms) {
unsigned char i ;
while(ms--)
{
for(i = 0 ; i < 120 ; i++) ;
}
}
这个挺简单的吧
不知道你的DSP设置情况,我就说下我怎么设置吧。我设置的DSP频率是150M,你要发的PWM波周期是20KHz,设置连续增减模式,计数的最大值应该设为150M/40k=3750,你在设置比较值,如果占空比是50%,就设一半。然后你设个计数值,确定是什么时候开通哪个PWM,定义个flag就可以 了,设置为012,到了你的PWM长度就加1,到3时清0,等于0开PWM1,1开PWM2,2开PWM3就ok了。
#include <reg52h> //头文件
#define uchar unsigned char
#define uint unsigned int
sbit KEY1= P3^4; //定义按钮
sbit KEY2= P3^5; //定义按钮
sbit PWM= P1^7;//PWM输出的管脚定义
#define PERIOD 1000 //pwm周期
#define MIN_POSITIVE 100 //最小占空比100/1000
#define MAX_POSITIVE 900 //最大占空比900/1000
#define STEP 10 //步长
uint POSITIVE=MIN_POSITIVE;
void delay(uint i)//延时函数
{
while(--i);
}
void init_timer0()//设置定时器
{
TMOD=0X01;
TL0=(POSITIVE-PERIOD)%256;//具体怎么实现的你看一下51单片机定时器的东西,TLO,THO。
TH0=(POSITIVE-PERIOD)/256;
ET0=1;
}
void init_timer1() // 初始化定时器
{
TMOD|=0X10;
TL1=(0-POSITIVE)%256;
TH1=(0-POSITIVE)/256;
ET1=1;
EA=1;
}
void TIMER0_ISR(void)interrupt 1 //中断响应函数
{
TL0=(POSITIVE-PERIOD)%256;
TH0=(POSITIVE-PERIOD)/256;
TR0=0;
TR1=1;
PWM=0;
}
void TIMER1_ISR(void)interrupt 3 //中断响应函数
{
TL1=(0-POSITIVE)%256;
TH1=(0-POSITIVE)/256;
TR1=0;
TR0=1;
PWM=1;
}
void key_scan() 按钮扫描函数
{
uint step=0;
step=(PERIOD-MIN_POSITIVE-100)/STEP;
KEY1=1;
KEY2=1;
if(KEY1==0||KEY2==0)
{
delay(100);
if(KEY1==0)
{
POSITIVE+=step;
if(POSITIVE>MAX_POSITIVE)
POSITIVE=MAX_POSITIVE;
}
if(KEY2==0)
{
POSITIVE-=step;
if(POSITIVE<MIN_POSITIVE)
POSITIVE=MIN_POSITIVE;
}
while(KEY1==0||KEY2==0);
}
}
void main() //主函数
{
init_timer0();
init_timer1();
TR0=1;
while(1)key_scan();
}
//这里的意思就是高电平使用一个定时器,低电平使用一个定时器,其实可以使用一个定时器就可以完成这个任务。他的左右只是1ms响应一个中断,然后计数。
//
#include <REGX51H>
#define TIMER0_COUNT 0xFC18 //每秒中端1000次
unsigned long int m,a;
static void timer0_isr(void) interrupt 1 using 1
{
TR0=0;
TL0=(TIMER0_COUNT & 0x00FF);
TH0=(TIMER0_COUNT >> 8);
TR0=1;
m++;
}
static void timer0_initialize(void)
{
EA=0; / 设定系统不接受所有的中断 /
m=0;
TR0=0; / 关闭Timer0 /
TMOD =0x01; / 设定计时器0为16位的工作模式 /
TL0=(TIMER0_COUNT & 0x00FF); / 设定TL0的数值 /
TH0=(TIMER0_COUNT >> 8); / 设定TH0的数值 /
PT0=0; / 设定计时器0有比较高的优先级 /
ET0=1; / 设定接受Timer0的中断 /
TR0=1; / 启动Timer0 /
EA=1; / 设定系统接受中断 /
}
void main (void)
{
timer0_initialize();
P2_0=0;
P2_1=1;
P3_0=0;
P3_1=1;
a=25;
while(1)
{
if(m==a)
{
P2_2=0;
P3_2=0;
}
if(m==50)
{
P2_2=1;
P3_2=1;
m=0;
}
}
}
//
这是我之前写的程序,你看看吧。希望对你有帮助,这个好理解点
以上就是关于STC单片机输出PWM信号,频率要25KHz,请大神指教,怎么实现,或者直接给我一个程序,谢谢!全部的内容,包括:STC单片机输出PWM信号,频率要25KHz,请大神指教,怎么实现,或者直接给我一个程序,谢谢!、如何利用51单片机输出PWM波、跪求单片机输出pwm波控制电调的程序!!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)