51单片机模拟PWM

合集下载

两种方法教你如何有效地利用51单片机产生PWM波

两种方法教你如何有效地利用51单片机产生PWM波
teus 软件仿真结果如下: 可见,用这种延时函数的方法就能简单地模拟出 pwm 输出。但是这种方 法的缺点也相当明显。当程序除了要输出 pwm 波还要执行其他操作比如键盘 扫描、显示等操作时,需要占用 CPU 一定的机器周期,这样就会影响 pwm 的准确度。现在很少会用到这种方法,接下来要介绍的是比较常用的方法。 2 定时器产生 pwm 这种方法利用了定时器溢出中断,在中断服务程序改变电平的高低,在程 序较复杂、多操作时仍能输出较准确的 pwm 波形。 2.1 注意事项 2.2.1 中断服务程序的内容。 一般来说中断服务程序只完成改变标志位、转换高低电平的功能,如果中
两种方法教你如何有效地利用 51 单片机产生 PWM

89C51 芯片没有自带 PWM 发生器,如果要用 51 来产生 PWM 波就必须 要用软件编程的方法来模拟。方法大概可以分为软件延时和定时器产生两种 方法。下面将逐一介绍。 1 软件延时法 利用软件延时函数,控制电平持续的时间,达到模拟 pwm 的效果。 程序如下: #include sbit pwm=P1; main() { while(1) { pwm=1; delayus(60);//置高电平后 延时 60us,占空比 60% pwm=0; delayus(40); } } void delayus(uint x) { while(x--);
断服务程序中有太多的操作会影响 pwm 波的输出,尤其是除法、取余、浮点 数运算会占用大量的机器周期,应在中断外完成运算。2.2.2 定时器装入初值 的问题。 装入初值不能太接近于定时器的溢出值。如我们使用定时器方式 1,最多 能计 65536 个数,假设我们转入的初值为 65534,那幺定时器计两个数就会 进入中断,这样会使程序紊乱而其他功能无法正常地执行,所以一般要留 50100 个数的裕量。 2.2 定时器工作方式 在定时器工作方式的选择上,可以选择定时器的工作方式 0、1、2 都可以, 本文采用的是工作方式 1,即 16 位定时器,这样可以获得较宽的调频范围。 2.3 定时器初值的计算 设占空比为 α,频率为 f 产生高电平时装入定时器高 8 位的值应为

51单片机——增强型PWM,使用自带PWM发生器

51单片机——增强型PWM,使用自带PWM发生器

51单片机——增强型PWM,使用自带PWM发生器0. 序之前用定时器做了模拟PWM输出,得到的1k左右波形还行,到10k往上波形就特别难看,又是跳变又是长短不一。

后来在参考手册上面看到stc15w4k系列自带pwm波形发生器,于是整了好久写出来了。

今天因为业务需求要改代码,回头一看,好家伙,都不知道自己写的啥了。

看了一会儿想起来,于是有了此文。

1. 简介如图,如下介绍,他直接把PWM输出到IO口上面,我使用的是这两个,于是就用了PWM3和PWM2_2两个。

2. 分析占坑,今天还要重构代码,改很多东西,暂时不分析了(2021.6.2)。

3. 代码代码比较简单,我是照着这个写的,XDM自己去瞅瞅啊,我当时看了一早上才看明白。

1.#include <STC15.H> //52头文件2.#include <PWM.H>3.4.u8 Tcount=0; //一个PWM周期内的:周期计数,占空比,方向5.sbit PWM = P2^1;//PWM4口6.sbit PWM2 = P2^7; //PWM2口7.sbit NPWM1 =P5^4; //关闭PWM异常口8.sbit NPWM2 =P5^4; //关闭PWM异常口9.void setPWMWide(u8 Wide); //设置脉宽10.11.#define CYCLE 0x800L//5khz //定义PWM周期(最大值为32767)12.#define DUTY1 20 //定义占空比为20%13.#define DUTY2 30 //定义占空比为30%14.#define DUTY3 50 //定义占空比为50%15.16.//主函数17.void InitPWM()18.{19.InterruptInit();//初始化中断配置20.}21.22.void setPWMWide(u8 Wide)23.{24.P_SW2 |= 0x80; //使能访问XSFR25.PWMIF=0x00;26.PWMFDCR = 0x00; //关闭PWM异常检测,P5.4和P5.5在IIC中使用,如果不关闭会一直进入异常导致无法设置PWM占空比27.PWMCFG = 0x00; //配置PWM的输出初始电平为低电平28.PWMCKS = 0x00; //选择PWM的时钟为Fosc/(0+1)29.PWMC = CYCLE; //设置PWM周期30.31.//板子PWM4 芯片PWM2_2 P2.732.// PWM2T1 = 0x0000; //设置PWM2第1次反转的PWM计数33.// PWM2T2 = CYCLE * DUTY / 100; //设置PWM2第2次反转的PWM计数34.PWM2T1 = 0x0000; //设置PWM2第1次反转的PWM计数35.PWM2T2 = CYCLE * (Wide) / 100; //设置PWM2第2次反转的PWM计数36.PWM2CR |= 0x08; //选择PWM2输出到P2.7,不使能PWM2中断37.38.PWM3T1 = 0x0000; //设置PWM2第1次反转的PWM计数39.PWM3T2 = CYCLE * (Wide) / 100; //设置PWM2第2次反转的PWM计数40.//占空比为(PWM2T2-PWM2T1)/PWMC41.PWM3CR = 0; //选择PWM2输出到P2.142.43.//使能44.PWMCR = 0x03; //使能PWM信号输出45.PWMCR |= 0x80; //使能PWM模块46.P_SW2 &= ~0x80;47.48.}49.50.void SetPWM(u8 level) //设置风扇等级 1 2 3 4是自动不用管风速51.{52.// PutChar(speedFlag);53.if(level==1) //1是9.8k54.{55.setPWMWide(DUTY1);56.}57.else if(level==2)58.{59.setPWMWide(DUTY2);60.}61.else if(level==3)62.{63.setPWMWide(DUTY3);64.}65.66.}67.68.69.//中断初始化配置70.void InterruptInit()71.{72.73.P2M1 &= 0<<1; //PWM4 P2.1 设置推挽74.P2M0 |= 1<<1;75.P2M1 &= 0<<7; //PWM4 P2.7 设置推挽76.P2M0 |= 1<<7;77.78.PWM=0;79.PWM2=0;80.81.P_SW2 |= 0x80; //使能访问XSFR82.PWMIF=0x00;83.PWMFDCR = 0x00; //关闭PWM异常检测,P5.4和P5.5在IIC中使用,如果不关闭会一直进入异常导致无法设置PWM占空比84.PWMCFG = 0x00; //配置PWM的输出初始电平为低电平85.PWMCKS = 0x00; //选择PWM的时钟为Fosc/(0+1)86.PWMC = CYCLE; //设置PWM周期87.88.//板子PWM4 芯片PWM2_2 P2.789.PWM2T1 = 0x0000; //设置PWM2第1次反转的PWM计数90.PWM2T2 = CYCLE * DUTY1 / 100; //设置PWM2第2次反转的PWM计数91.//占空比为(PWM2T2-PWM2T1)/PWMC92.PWM2CR |= 0x08; //选择PWM2输出到P2.7,不使能PWM2中断93.94.//板子PWM2 芯片PWM3 P2.195.PWM3T1 = 0x0000; //设置PWM2第1次反转的PWM计数96.PWM3T2 = CYCLE * DUTY1 / 100; //设置PWM2第2次反转的PWM计数97.//占空比为(PWM2T2-PWM2T1)/PWMC98.PWM3CR = 0; //选择PWM2输出到P2.199.100.//使能101.PWMCR = 0x03; //使能PWM信号输出102.PWMCR |= 0x80; //使能PWM模块103.P_SW2 &= ~0x80;104.105.}。

PWM电机调速原理及51单片机PWM程序经典

PWM电机调速原理及51单片机PWM程序经典

PWM电机调速原理及51单片机PWM程序经典pwm电机调速原理对于电机的转速调整,我们是采用脉宽调制(pwm)办法,控制电机的时候,电源并非连续地向电机供电,而是在一个特定的频率下以方波脉冲的形式提供电能。

不同占空比的方波信号能对电机起到调速作用,这是因为电机实际上是一个大电感,它有阻碍输入电流和电压突变的能力,因此脉冲输入信号被平均分配到作用时间上,这样,改变在始能端pe2和pd5上输入方波的占空比就能改变加在电机两端的电压大小,从而改变了转速。

此电路中用微处理机去同时实现脉宽调制,通常的方法存有两种:(1)用软件方式来实现,即通过执行软件延时循环程序交替改变端口某个二进制位输出逻辑状态去产生脉宽调制信号,设置相同的延时时间获得相同的充电电流。

(2)硬件实验自动产生pwm信号,不挤占cpu处置的时间。

这就要用到atmega8515l的在pwm模式下的计数器1,具体内容可参考相关书籍。

51单片机pwm程序产生两个pwm,要求两个pwm波形占空都为80/256,两个波形之间要错开,不能同时为高电平!高电平之间相差48/256,pwm这个功能在pic单片机上就存有,但是如果你就要用51单片机的话,也就是可以的,但是比较的麻烦.可以用定时器t0去掌控频率,定时器t1去掌控充电电流:大致的的编程思路就是这样的:t0定时器中断就是使一个i0口输入高电平,在这个定时器t0的中断当中再生制动定时器t1,而这个t1就是使io口输入低电平,这样发生改变定时器t0的初值就可以发生改变频率,发生改变定时器t1的初值就可以发生改变充电电流。

*程序思路说明:****关于频率和占空比的确定,对于12m晶振,假定pwm输出频率为1khz,这样定时中断次数**预设为c=10,即0.01ms中断一次,则th0=ff,tl0=f6;由于预设中断时间为0.01ms,这样**可以设定占空比可从1-100变化。

即0.01ms*100=1ms******************************************************************************* /#include#defineucharunsignedchar/******************************************************************************th0和tl0是计数器0的高8位和低8位计数器,计算办法:tl0=(65536-c)%6;**th0=(65536-c)/256,其中c为所要计数的次数即为多长时间产生一次中断;tmod就是计数器**工作模式挑选,0x01则表示采用模式1,它存有16十一位计数器,最小计数脉冲为65536,最久时**间为1ms*65536=65.536ms******************************************************************************* /#definev_th00xff#definev_tl00xf6#definev_tmod0x01voidinit_sys(void);/*系统初始化函数*/voiddelay5ms(void);unsignedcharzkb1,zkb2;voidmain(void){init_sys();zkb1=40;/*占空比初始值设定*/zkb2=70;/*占空比初始值设定*/while(1){if(!p1_1)//如果按了+键,减少充电电流{delay5ms();if(!p1_1){zkb1++;zkb2=100-zkb1;}}if(!p1_2)//如果按了-键,增加充电电流{delay5ms();if(!p1_2){zkb1--;zkb2=100-zkb1;/*对占空比值限定范围*/if(zkb1>99)zkb1=1;if(zkb1<1)zkb1=99;}}/*******************************************************函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/voidinit_sys(void)/*系统初始化函数*/{/*定时器初始化*/tmod=\th0=v_th0;tl0=v_tl0;tr0=1;et0=1;ea=\}//延时voiddelay5ms(void){unsignedinttempcyc=1000;while(tempcyc--);}/*中断函数*/voidtimer0(void)interrupt1using2{staticucharclick=\/*中断次数计数器变量*/th0=v_th0;/*恢复定时器初始值*/tl0=v_tl0;++click;if(click>=100)click=\if(click<=zkb1)/*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/p1_3=0;elsep1_3=1;if(click<=zkb2)p1_4=0;elsep1_4=1;}<1.下面就是avr的程序,51产生pwm波麻烦,可以用avr。

51单片机led水滴效果PWM波(渐变带拖尾效果)

51单片机led水滴效果PWM波(渐变带拖尾效果)

51单片机led水滴效果(渐变带拖尾效果)实现和讲解简介学习嵌入式第一个例子通常都是控制一个LED亮灭,然后是花样繁多的流水灯,但不管灯的花样如何变化,单个LED的亮度没有变化,只有亮、灭两个状态,本章我们实现如何控制LED的亮度。

1 什么是PWM脉冲宽度调制(Pulse Width Modulation,简称PWM),是利用微处理器的数字输出来对模拟电路进行控制的一种技术。

在本章的应用中可以认为PWM就是一种方波。

比如图1:是周期为10ms,占空比为60%的PWM。

占空比:高电平在一个周期之内所占的时间比率。

2 硬件设计在例说51单片机的第三章,我们讲过如何控制开发板上LED的亮灭。

首先译码器输出端LEDS6为低,T10导通,给8个LED供电,然后通过缓冲器8个输出端BD0~BD7的控制LED的亮灭(低亮高灭)。

如果BD口输出高低不断变化,则LED会闪烁;如果这种高低电平变化非常快,由于人的视觉暂留现象,LED就会出现不同的亮度。

3 软件设计3.1 PWM能否控制亮度下面我们就用实践验证PWM是否能够控制LED的亮度,测试代码如下:程序清单L1:验证PWM能否控制LED的亮度1 #include <reg52.h>2 #include "my_type.h"3 #include "hw_config.h"456 void main(void)7 {8 u8 i = 0;910 //使能独立LED的供电,即LEDS6输出低电平11 LEDEN = 0;12 ADDR0 = 0;13 ADDR1 = 1;14 ADDR2 = 1;15 ADDR3 = 1;1617 //第一个LED亮18 P0 = 0xFE;1920 while(1)21 {22 for(i=0; i<250; i++)23 {24 if(i<10)25 {26 P0 &= 0xFD; //第二个灯亮27 }28 else29 {30 P0 |= 0x02; //第二个灯灭31 }32 }33 }34 }L1(22-32):这段代码实现P0.1输出占空比为96%的方波,而P0.0恒为低。

51单片机产生PWM控制小车速度的两种方法

51单片机产生PWM控制小车速度的两种方法

51单片机产生PWM控制小车速度的两种方法首先你的先知道什么是PWM。

PWM是一种脉宽调制技术。

简单的说就是在一个周期内高电平所占用的时间,通过改变脉冲的周期可以调频,改变脉冲的宽度或占空比可以调节驱动上的电压。

将产生的PWM信号接到L298N的ENA和ENB端调节不同的占空比从而调节速度第一种方法用单片机的定时器模拟出PWM。

假如你用定时器延时100ms,在50ms之前某一个引脚为低电平,50ms之后该引脚为高电平,这样高电平占用的时间为1/2,此时该引脚就会产生50%的占空比信号。

程序如下:#include<reg52.h>unsigned chartimer1;sbit PWM=P1^1;void system_Ini(){TMOD|= 0x11;TH1 = 0xfe; //11.0592TL1 = 0x33;TR1 =1;IE=0x8A;}main(){ system_Ini() ;定时器初始化while(1){ if(timer1>100) timer1=0;if(timer1<=30) pwm=0;//产生30%的占空比else PWM=1;}}另一种方法就是利用简单的延时产生PWM方波信号#include<reg52.h>unsigned char count=0;sbit PWM_1=PI^1;//利用P1^1产生PWMvoid mian(){while(1)for(count=0;count<=100;count++) //让单片机记100个数{If(count<=50){ PWM_1=1;}//前一半时间为高电平elsePWM_1=0//后一半时间为低电平这样就产生了50%的占空比}PWM不仅能够控制小车速度还可以控制小灯的亮灭程度,朋友们可以去试试。

水平有限,如果觉得对您有用请您推荐您的朋友关注我们,还请大神们轻喷。

基于C51单片机的直流电机PWM调速控制(包含原理图及C源代码)

基于C51单片机的直流电机PWM调速控制(包含原理图及C源代码)

基于C51单片机的直流电机PWM调速控制--SQ这是最近一阶段自己学习所获,现分享与大家。

这里采用A T89C52单片机做主控制芯片,实现两路直流电机的PWM调速控制,另外还可以实现转向、显示运行时间、显示档位等注:考虑小直流电机自身因素,调速范围仅设有四级电路原理图:C语言程序源代码:/******************** 硬件资源分配*********************/数码管:显示电机状态(启停、正反、速度)、运行时间、是否转弯按键:K4 启动/暂停K3 正反转/转弯允许K2 加速/左转/运行时间清零K1 减速/右转/停止定时器:T0 数码管动态显示,输出PWMT1 运行时间记录********************************************************//*******主程序文件PWM.c******/#include <reg52.h>#include "Afx.h"#include "Config.c"#define CIRCLE 5 //脉冲周期//按键定义uchar key,key_tmp=0, _key_tmp=0;//显示定义uchar LedState=0xF0; //LED显示标志,0xF0不显示,Ox00显示uchar code LED_code_d[4]={0xe0,0xd0,0xb0,0x70}; //分别选通1、2、3、4位uchar dispbuf[4]={0,0,0,0}; //待显示数组uchar dispbitcnt=0; //选通、显示的位uchar mstcnt=0;uchar Centi_s=0,Sec=0,Min=0; //分、秒、1%秒//程序运行状态标志bit MotState=0; //电机启停标志bit DirState=0; //方向标志0前,1后uchar State1=-1;uchar State2=-1;uchar State3=0;uchar State4=-1;uchar LSpeed=0;uchar RSpeed=0;//其他uint RunTime=0;uint RTime_cnt=0;uint LWidth;uint RWidth; //脉宽uint Widcnt=1;uint Dispcnt;//函数声明void key_scan(void);void DisBuf(void);void K4(void);void K3(void);void K2(void);void K1(void);void disp( uchar H, uchar n );void main(void){P1|=0xF0;EA=1;ET0=1;ET1=1;TMOD=0x11;TH0=0xFC;TL0=0x66; //T0,1ms定时初值TH1=0xDB;TL1=0xFF; //T1,10ms定时初值TR0=1;Widcnt=1;while(1){key_scan();switch(key){case 0x80: K1(); break;case 0x40: K2(); break;case 0x20: K3(); break;case 0x10: K4(); break;default:break;}key=0;DisBuf();LWidth=LSpeed;RWidth=RSpeed;}}//按键扫描**模拟触发器防抖void key_scan(void){key_tmp=(~P3)&0xf0;if(key_tmp&&!_key_tmp) //有键按下{key=(~P3)&0xf0;}_key_tmp=key_tmp ;}//按键功能处理/逻辑控制void K4(void){if(State4==-1){State4=1;TR1=1;dispbuf[3]=1;LedState=0x00; //打开LEDMotState=1; //打开电机LSpeed=1;RSpeed=1; //初速设为1}else if(State4==1){State4=0;TR1=0;MotState=0; //关闭电机}else if(State4==0){MotState=1;if(State3==0){State4=1;TR1=1;}else if(State3==1){LSpeed=2;RSpeed=2;}}}void K3(void){if(State4==1)DirState=!DirState;if(State4==0){if(State3==0){State3=1; //可以转向标志1可以,0不可以TR1=1;dispbuf[3]=9;MotState=1;LSpeed=2;RSpeed=2;}else if(State3==1){State3=0;TR1=0;dispbuf[3]=0;MotState=0;}}}void K2(void){if(State4==1&&LSpeed<4&&RSpeed<4){LSpeed++;RSpeed++;}else if(State4==0){if(State3==0){//State4=-1;//LedState=0xF0;MotState=0;Sec=0;Min=0;}else if(State3==1&&LSpeed<4&&RSpeed<4){//TurnState=0;LSpeed=2;RSpeed++;}}}void K1(void){if(State4==1&&LSpeed>1&&RSpeed>1){LSpeed--;RSpeed--;}else if(State4==0){if(State3==0){State4=-1;LedState=0xF0;MotState=0;}else if(State3==1&&LSpeed<4&&RSpeed<4){//TurnState=1;LSpeed++;RSpeed=2;}}}//显示预处理void DisBuf(void){if(RTime_cnt==100){Sec++;RTime_cnt=0;}if(Sec==60){Min++;Sec=0;}if(State4==1){dispbuf[0]=Sec%10;dispbuf[1]=Sec/10;dispbuf[2]=Min;if(!DirState) //正转dispbuf[3]=LSpeed;if(DirState) //反转dispbuf[3]=LSpeed+4;}if(State4==0){if(State3==0){dispbuf[0]=Sec%10;dispbuf[1]=Sec/10;dispbuf[2]=Min;dispbuf[3]=0;}if(State3==1){dispbuf[0]=RSpeed;dispbuf[1]=LSpeed;dispbuf[2]=Min;dispbuf[3]=9;}}}//LED驱动void disp( uchar H, uchar n ){P1=n;P1|=LedState ;P1|=LED_code_d[H];}//T0中断**显示/方波输出void Time_0() interrupt 1{TH0=0xFC;TL0=0x66;Widcnt++;Dispcnt++;//电机驱动/方波输出if(Widcnt>CIRCLE){Widcnt=1;}if(Widcnt<=LWidth)LMot_P=!DirState&&MotState;elseLMot_P=DirState&&MotState;LMot_M=DirState&&MotState;if(Widcnt<=RWidth)RMot_P=!DirState&&MotState;elseRMot_P=DirState&&MotState;RMot_M=DirState&&MotState;//显示if(Dispcnt==5){disp(dispbitcnt,dispbuf[dispbitcnt]);dispbitcnt++;if(dispbitcnt==4){dispbitcnt=0;}Dispcnt=0;}}//T1中断**运行时间void Time_1() interrupt 3{TH1=0xDB;TL1=0xFF;RTime_cnt++;}/******配置文件Afx.h******/#ifndef _AFX_#define _AFX_typedef unsigned char uchar;typedef unsigned int uint;typedef unsigned long ulong;#endif/******IO配置文件Config.c******/#ifndef _Config_#define _Config_#include "Afx.h"#include <reg52.h>//显示定义sbit led=P3^2;//电机引脚定义sbit LMot_P=P2^2; sbit LMot_M=P2^3; sbit RMot_P=P2^0; sbit RMot_M=P2^1;#endif。

关于51系列单片机利用定时器生成频率占空比可调的PWM

关于51系列单片机利用定时器生成频率占空比可调的PWM

关于51系列单片机利用定时器生成频率占空比可调的PWM关于51系列单片机利用定时器生成频率占空比可调的PWM利用51单片机(无PWM模块)的软件模拟生成PWM,其频率和占空比都是可调的,在去年电子竞赛的时候一直没有自己尝试过,现在到了13的五月,要准备电子竞赛了,想把一些比较基础的东西自己亲手调一调。

在刘海波老师的单片机课,听过老师的方法生成PWM,当时就是一惊!自己从来没有这么做过。

原理比较简单,下面分别阐述:自己的想法,要用到两个定时器,一个用于控制占空比,一个用于控制周期,即频率例如:t0控制高电平(或者)维持的时间,t1控制低电平(或者高电平)维持的时间,两者的时间的之和就是该PWM的周期,考虑到单片机上电引脚的电平的问题,此时生成的PWm的最好是先高后低。

往往第一个周期是不对的。

以下下就详细说明:单片机上电为高电平,开始t0定时器和相关中断设置,等到t0定时时间T0到了,进入中断程序,变为低电平,同时关掉t0和开启t1,即是TR0=0,TR1=1;同理t1定时时间T1到了,进入中断程序,变为低电平,同时关掉t1和开启t0,即是TR0=1,TR1=0;即是即是采用定时器t0、t1轮流定时,一个定时器控制一种电平的时间,t0为高电平定时的时间,t1为低电平定时的时间。

T= T0+ T1 q(占空比)= T0/T,注意:这个方法在系统的初始化的时候,必须将t0的定时器开启,否则,全部无法进行还有一种方法是开始t0定时器、t1定时器同时开启,其中t0定时的时间T0是高电平的时间,t1定时的时间T1是整个PWM的周期。

开始t0定时器、t1定时器同时开启,当然,T0的时间肯定要比T1的大,当t0定时的时间T0到了,进入t0中断程序,引脚又高电平变到低电平,同时将t0定时器关掉;当t1定时的时间T1到了,进入t1中断程序,引脚又低电平变到高电平,同时将t0定时器开启。

T= T1 q(占空比)= T0/T,以上两种方法都是利用两个定时器分别控制不同电平的时间,占用了51的几乎全部定时器,并且计算起来比较麻烦,要计算两个定时器的值,占空比的计算也相对困难。

51系列单片机输出PWM的两种方法

51系列单片机输出PWM的两种方法

51系列单片机输出PWM的两种方法51系列单片机(如STC89C52、AT89C51等)是一种常用的8位微处理器,具有较高的性价比和广泛的应用领域。

PWM(Pulse Width Modulation)是一种常用的模拟信号生成技术,在很多领域中都有广泛应用,比如电机控制、LED调光等。

在51系列单片机中,有两种常用的方法可以实现PWM输出,分别是软件实现PWM和硬件实现PWM。

下面将详细介绍这两种方法及其实现方式。

1.软件实现PWM软件实现PWM是通过定时器和IO口的相互配合来产生PWM信号。

具体实现的步骤如下:步骤1:设置定时器的工作模式和计数器初值。

选择一个合适的定时器,比如定时器0,然后设置定时器工作模式和计数器初值。

定时器的工作模式选择“模式1”或“模式2”,并根据需求设置计数器初值。

步骤2:设置IO口的工作模式。

选择一个合适的IO口,比如PWM输出口(如P1.2),然后将该IO口设置为输出模式。

步骤3:编写软件控制代码。

在主循环中,通过改变IO口的电平状态来实现PWM输出。

根据定时器的计数值,可以确定PWM信号的占空比大小。

当定时器计数值小于一些阈值时,将IO口置高电平;当定时器计数值大于该阈值时,将IO口置低电平。

通过改变该阈值,可以实现不同的PWM占空比。

通过上述步骤,就可以实现软件控制的PWM输出。

需要注意的是,软件实现PWM的精度较低,同时也会占用较多的处理器时间。

2.硬件实现PWM硬件实现PWM是通过专门的PWM模块或专用的计时电路来实现PWM输出。

具体实现的步骤如下:步骤1:选择一个合适的PWM模块或计时电路。

可以选择专门的PWM模块(如PCA模块)或计时电路(如555计时芯片),根据需求选择合适的硬件模块。

步骤2:设置PWM模块或计时电路的相关参数。

根据需求设置PWM频率、占空比等参数。

步骤3:连接并配置IO口。

将PWM模块或计时电路的输出引脚连接到需要输出PWM信号的IO口,然后将该IO口设置为输出模式。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

51单片机模拟PWM
吴水林的学习笔记
怎样用单片机模拟PWM
版本:v2
在讲解PWM 之前,让我们来了解几个和PWM 相关的词汇。

1. 频率:
频率f 是周期T 的倒数,即f =1/T。

而像中国使用的电是一种正弦交流电,其频
率是50Hz,也就是它一秒钟内做了50 次周期性变化。

2. 周期(period):
事物在运动、变化的发展过程中,某些特征多次重复出现,其接续两次出现所经过的时间。

通常用T 表示。

频率(f)的倒数。

即T = 1 / f.物体完成一个完整的振动所需要的
时间,以T0 表示。

单位一般是用“秒”来表示,也常用毫秒(ms)或微秒(us)做
单位。

1s=1000ms,1s=1000000us。

例如一个单摆,它的周期就是重锤从左运动到
右,再从右运动回左边起点所需要的时间。

3. 占空比(Duty Cycle):
在一串理想的脉冲序列中(如方波),正脉冲的持续时间与脉冲总周期的比值。

例如:脉冲宽度1μs,信号周期4μs 的脉冲序列占空比为0.25。

知道了以上的一些基本知识。

那我们怎样确定最占空比呢?最小占空比!在此我们为了
叙述的方便,就把最小占空比宽度定为频率周期的1%.
// 如125Hz 方波的周期时间: 1s=1000ms, T = 1000ms/125 = 8ms = 8000us
// 最小占空比宽度就是8000us 乘以1%,就是80us.
首先我们就对相关数据进行定义:
#define PWM_PERIOD 100 // 100%占空比时标数
sbit PwmOut = P1^0; // 占空比输出I\0
unsigned char PwmPeriodCont; // PWM 占空比计数器
struct Pwm
{
// PwmPeriod=PwmH+PwmL
// DutyCycle(100%)=PwmH/PwmPeriod*100%
//unsigned PwmPeriod;
unsigned char PwmH;
unsigned char PwmL; // 此变量无作为,只是为了便于理解
};
struct Pwm A;
吴水林的学习笔记
下面,我们就用单片机的一个定时器,以最小占空比(80uS)作为标准时标进行中断。

那我们就用51 的定时器1 作为1%占空比的时标,计算如下:
在51 单片机中。

我们可以作如下处理:
/*------------------------------------------------------------------------------------------------*-
* 函数名称: Pwm_init ()
* 函数功能: 设定1%占空比时标。

* 说明:
*
* 当前版本: 1.0 * 取代版本:
* 作者: 吴水林* 原作者:
* 完成日期: 2009-05-31 * 完成日期:
-*------------------------------------------------------------------------------------------------*/ void Pwm_init(void)
{ // 22.1184MHz
TMOD = 0x20; // 定时器1 模式2
TL1 = 0x6c; // 125Hz
TH1 = 0x6c;
ET1 = 1;
TR1 = 1;
//EA = 1;
// 必须清0,不然第一次占空比比例错误
PwmPeriodCont = 0;
}
吴水林的学习笔记
/*------------------------------------------------------------------------------------------------*- * 函数名称: PwmSr()
* 函数功能: 1%占空比时标
* 说明: 占空比从0% ~ 100%可调,进步1%
*
* 当前版本: 1.0 * 取代版本:
* 作者: 吴水林* 原作者:
* 完成日期: 2009-05-31 * 完成日期:
-*------------------------------------------------------------------------------------------------*/ void PwmSr(void) interrupt 3
{
PwmPeriodCont++;
if (PwmPeriodCont <= A.PwmH)
{ // 高电平从0 到...A.PwmH,如果A.PwmH=100,则占空比为100% PwmPin = 1;
}
if ((PwmPeriodCont > A.PwmH)&&(PwmPeriodCont <= PWM_PERIOD)) { // 当占空比小于100 时,程序才能运行到此,剩下的为低电平时间PwmPin = 0;
}
// 限制占空比小于等于100%
if (PWM_PERIOD == PwmPeriodCont)
{ // 当程序运行到此时,一个频率周期完成
PwmPeriodCont=0;
}
}
以上处理我们还不能控制PWM 的占空比,因为正脉冲的宽度(A.PwmH)还是一个未知量。

我们要通过改变A.PwmH 中的值来改变PWM 的占空比。

注意:NewPwmValue 值只能是0 ~ 100 之间的数.
void Set_Pwm(const unsigned char NewPwmValue)
{
if ( NewPwmValue > PWM_PERIOD)
{
//A.PwmH = 0;
return;
}
A.PwmH = NewPwmValue;
A.PwmL = PWM_PERIOD - A.PwmH;
}
吴水林的学习笔记
所以,我们可以通过void Set_Pwm(const unsigned char NewPwmValue)这个函数来设定PWM 的占空比,如我们在程序中调用:
Set_Pwm(25);
那么就可以将PWM 占空比设定在25%上,下图是软件的仿真结果:。

相关文档
最新文档