单片机产生可调PWM程序
两种方法教你如何有效地利用51单片机产生PWM波
两种方法教你如何有效地利用 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波的程序
51单片机定时器产生pwm波的程序PWM(Pulse Width Modulation)是一种调节脉冲信号宽度的技术,通过改变信号的高电平时间和低电平时间的比例来控制输出电压的大小。
在很多应用中,PWM技术被广泛应用于电机控制、LED调光、音频放大器等领域。
在使用51单片机生成PWM波之前,我们首先需要了解51单片机的定时器的工作原理。
51单片机内部集成了多个定时器,其中最常用的是定时器0和定时器1。
这两个定时器都是16位的,可以通过设定定时器的计数值和工作模式来控制定时器的工作。
在使用定时器0和定时器1生成PWM波之前,我们还需要明确一些概念。
占空比是指高电平时间与一个周期的比值,通常用百分比表示。
频率是指一个周期的时间,单位是赫兹(Hz)。
接下来我们以定时器1为例,介绍如何在51单片机上生成PWM波。
我们需要设置定时器1的工作模式。
定时器1的工作模式分为两种:8位自动重装载模式和16位工作模式。
在8位自动重装载模式下,定时器1的计数器值从0到255,然后自动重装载为初始值,重复计数。
在16位工作模式下,定时器1的计数器值从0到65535,然后自动重装载为初始值,重复计数。
在生成PWM波时,我们通常使用16位工作模式。
我们需要设置定时器1的计数值。
定时器1的计数值决定了PWM波的频率。
计数值越大,频率越低;计数值越小,频率越高。
我们可以根据具体的应用需求来设定计数值。
然后,我们需要设置定时器1的占空比。
占空比决定了PWM波的高电平时间与低电平时间的比例。
占空比为50%时,高电平时间和低电平时间相等;占空比小于50%时,低电平时间多于高电平时间;占空比大于50%时,高电平时间多于低电平时间。
我们可以通过改变定时器1的占空比来控制PWM波的输出电压的大小。
我们需要启动定时器1开始工作。
定时器1开始工作后,会自动根据设定的计数值和占空比生成相应的PWM波。
使用51单片机定时器生成PWM波的步骤如下:1. 设置定时器1的工作模式为16位工作模式;2. 设定定时器1的计数值,确定PWM波的频率;3. 设定定时器1的占空比,确定PWM波的输出电压的大小;4. 启动定时器1开始工作。
单片机PWM调光程序
单片机PWM调光程序一、概述PWM(Pulse Width Modulation,脉宽调制)是一种常用的调光技术,通过控制信号的脉冲宽度来调节输出电平的平均值,从而实现对光源亮度的调节。
本文将介绍如何编写单片机PWM调光程序,并提供一个基于XX单片机的示例代码。
二、硬件准备1. 单片机:XX单片机(型号)2. 光源:LED灯(型号)3. 光敏电阻:用于实时检测环境光强度的元件4. 电路连接:将单片机的PWM输出引脚连接到LED灯的控制引脚,将光敏电阻连接到单片机的模拟输入引脚三、软件设计1. 引入头文件:根据单片机型号,引入相应的头文件,例如"xx.h"。
2. 定义宏:定义LED灯的控制引脚和光敏电阻的模拟输入引脚。
3. 初始化:设置单片机的引脚模式和PWM参数,例如设置PWM频率、占空比等。
4. 光敏检测:通过模拟输入引脚读取光敏电阻的电压值,将其转换为环境光强度的数值。
5. PWM调光:根据光敏检测到的环境光强度数值,计算对应的PWM占空比,并将其输出到LED灯的控制引脚。
四、示例代码```c#include <xx.h> // 引入相应的头文件#define LED_PIN 1 // 定义LED灯的控制引脚#define LDR_PIN 2 // 定义光敏电阻的模拟输入引脚void init_pwm() {// 设置引脚模式为PWM输出pinMode(LED_PIN, PWM_OUTPUT);// 设置PWM参数pwmSetMode(PWM_MODE_MS);pwmSetClock(100); // 设置PWM频率为100HzpwmSetRange(1024); // 设置PWM占空比范围为0-1024 }int read_ldr() {// 读取光敏电阻的电压值int ldr_value = analogRead(LDR_PIN);// 根据电压值转换为环境光强度数值int light_intensity = map(ldr_value, 0, 1023, 0, 100);return light_intensity;}void adjust_brightness(int light_intensity) {// 根据环境光强度计算PWM占空比int pwm_duty_cycle = map(light_intensity, 0, 100, 0, 1023);// 输出PWM占空比到LED灯的控制引脚pwmWrite(LED_PIN, pwm_duty_cycle);}int main() {init_pwm(); // 初始化PWMwhile (1) {int light_intensity = read_ldr(); // 光敏检测adjust_brightness(light_intensity); // PWM调光}return 0;}```五、使用方法1. 将示例代码中的XX单片机型号替换为实际使用的单片机型号。
IAP15W4K58S4单片机PWM产生的方法及程序
IAP15W4K58S4单⽚机PWM产⽣的⽅法及程序IAP15W4K58S4单⽚机PWM产⽣的控制步进电机运动最近购⼊⼀块IAP15W4K58S4(图1)的STC单⽚机的最⼩系统,然后⽤它控制步进电机,步进电机驱动器为基于TB6600的MicroStep Driver(图2)驱动器。
为了能控制该驱动器,利⽤现有的单⽚机系统控制驱动器。
连接电路原理图如图3所⽰,图1 IAP15W4K58S4单⽚机最⼩系统图2 步进电机驱动器使IAP15W4K58S4单⽚机能够控制步进电机,⾸先需要产⽣PWM脉冲,本例⼦产⽣频率为1KHz,占空⽐为50%的脉冲,P2.2(P22)⼝。
⽣产PWM脉冲,单⽚机涉及到的寄存器(不考虑PWM中断)有P_SW2(端⼝配置寄存器)、PWMCFG(PWM配置寄存器,初始电平⾼低)、PWMCKS(PWM时钟选择寄存器)、由PWMCH(⾼7位)和PWMCL(低8位)组成的15位PWM计数器、由PWM n T1H、PWM n T1L和PWM n T2H、PWM n T2L组成的PWM脉冲翻转计数器(其中PWM n T1H、PWM n T1L组成第⼀次翻转15位计数器,其中PWM n T2H、PWM n T2L组成第⼆次翻转15位计数器,n取值范围为2、3、4、5、6、7)、PWM n CR(PWM n的控制寄存器,设置输出管脚选择和中断使能控制,n取值范围为2、3、4、5、6、7)和PWMCR(PWM控制寄存器,⽤于开启各个端⼝和PWM模块开关,该寄存器最后设置)。
由于⽣成PWM,需将I/O ⼝配置为准双向⼝或强推挽模式,所以还需配置P m M0和P m M1寄存器,m取值范围为0~3。
以上寄存器各个位配置可参考该单⽚机的数据⼿册,本项⽬的例程参考STC官⽅例程基础进⾏修改,如后⽂所述。
IAP15W4K58S4单⽚机的特殊功能寄存器区中要使⽤扩展的特殊功能寄存器需要配置P_SW2的bit7位,将其(bit7)置1。
如何利用单片机输出PWM波
如何利用51单片机输出PWM波1、理论知识PWM这个功能在飞思卡尔、STM32等高档的单片机内部有专用的模块,用此类芯片实现PWM功能时只需要通过设置相应的寄存器就可实现周期和占空比的控制;但是如果要用51单片机的话,也是可以的,但是比较的麻烦;此时需要用到内部定时器来实现,可用两个定时器实现,也可以用一个定时器实现;用两个定时器的方法是用定时器T0来控制频率,定时器T1来控制占空比;大致的的编程思路是这样的:T0定时器中断让一个I0口输出高电平,在这个定时器T0的中断当中起动定时器T1,而这个T1是让IO口输出低电平,这样改变定时器T0的初值就可以改变频率,改变定时器T1的初值就可以改变占空比;下面重点介绍用一个定时器的实现PWM的方法;因为市面上的智能小车所采用的电机大多数为TT减速电机,通过反复的实验,此电机最佳的工作频率为1000HZ太高容易发生哨叫,太低电机容易发生抖动,所以下面以周期为1ms1000HZ进行举例,要产生其它频率的PWM波,程序中只需作简单修改即可;用一个定时器时如定时器T0,首先你要确定PWM的周期T和占空比D,确定了这些以后,你可以用定时器产生一个时间基准t,比如定时器溢出n次的时间是PWM的高电平的时间,则DT=nt,类似的可以求出PWM低电平时间需要多少个时间基准n';因为这里我们是产生周期为1ms1000HZ的PWM,所以可设置中断的时间间隔为0.01ms,,然后中断100次即为1ms;在中断子程序内,可设置一个变量如time,在中断子程序内,有三条重要的语句:1、当time>=100时,time清零此语句保证频率为1000HZ,2、当time>n时n应该在0-100之间变化开,让单片相应的I/O口输出高电平,当time<n时,让单片相应的I/O口输出低电平,此时占空比就为%n;2、程序1,使单片机的I/O口输出固定频率的PWM波下面按上面的思路给出一个具体程序:///程序名:单片机输出固定频率的PWM波//晶振:11.00592 MHz CPU型号:STC89C52 //功能:P2^0口输出周期为1ms1000HZ,占空比为%80的PWM波///include<reg52.h>define uint unsigned intdefine uchar unsigned charsbit PWM1=P2^0;//接IN1 控制正转sbit PWM2=P2^1;//接IN2 控制反转uchar time;void main{TMOD=0x01;//定时器0工作方式1TH0=0xff;//65536-10/256;//赋初值定时TL0=0xf7;//65536-10%256;//0.01msEA=1;//开总中断ET0=1;//开定时器0中断TR0=1;//启动定时器0while1{}}void delayuint z{uint x,y;forx=z;x>0;x--fory=500;y>0;y--;}void tim0 interrupt 1{TR0=0;//赋初值时,关闭定时器TH0=0xff;//65536-10/256;//赋初值定时TL0=0xf7;//65536-10%256;//0.01msTR0=1;//打开定时器time++;iftime>=100 time=0;//1khziftime<=20 PWM1=0;//点空比%80else PWM1=1;PWM2=0;}程序说明:1、关于频率的确定:对于11.0592M晶振,PWM输出频率为1KHZ,此时设定时器0.01ms中断一次,时中断次数100次即为1KHZ 0.01ms100=1ms,即为1000HZ此时, 定时器计数器赋初值为TH0=FF,TL0=F7;2、关于占空比的确定:此时我们将来time的值从0-100之间进行改变,就可以将占空比从%0-%100之间进行变化,上面程序中t ime<=20时PWM1=0; else PWM1=1;意思就是%20的时间输出低电平,%80的时间输出高电平,即占空比为%80;如需得到其它占空比,如%60,只需将time的值改为40即可;程序为iftime<=40 PWM1=0;else PWM1=1;当然编写程序时也可以定义一个标志位如flag,根据flag的状态决定输出高平还是低电平,假设定义flag=1的时候输出高电平,用一个变量去记录定时器中断的次数,每次中断就让记录中断次数的变量+1,在中断程序里面判断这个变量的值是否到了n,如果到了说明高电平的时间够了,那么就改变flag为0,输出低电平,同时记录中断变量的值清零,每次中断的时候依旧+1,根据flag=0的情况跳去判断记录变量的值是否到了n'如果到了,说明PWM的低电平时间够了,那么就改flag=1,输出改高电平,同时记录次数变量清零,重新开始,如此循环便可得到你想要的PWM波形,这种方法我们这里不在举例,请自己去试着书写;3、程序2,使用单片机I/O口输出PWM波,并能通过按键控制正反转在程序中我们通常需要控制电机的正反转,如通过一个按键控制正反转,此时我们也可以设置一个标志位如flag;在主程序中当按键每次被按下时,flag相应取反;然后在子程序中当flag为1时,进行正转程序,当flag为0时执行反转程序;下面的程序功能为单片机I/O口P2^0、P2^1输出1000HZ,占空比为%50,并能过P3^7按键控制正电机的正反转;///程序名:PWM直流电机调速//晶振:11.00592 MHz CPU型号:STC89C52 //功能:直流电机的PWM波控制,可以通过按键控制正反转///include<reg52.h>define uint unsigned intdefine uchar unsigned charuchar time,count=50,flag=1;//低电平的占空比sbit PWM1=P2^0;//PWM 通道1,反转脉冲sbit PWM2=P2^1;//PWM 通道2,正转脉冲sbit key_turn=P3^7; //电机换向/函数声明/void delayxmsuint z;void Motor_turnvoid;void timer0_initvoid;/主函数/void mainvoid{timer0_init;while1{Motor_turn;}}/延时处理/void delayxmsuint z//延时xms程序{uint x,y;fory=z;x>0;x--fory=110;y>0;y--;}/电机正反向控制/void Motor_turnvoid{ifkey_turn==0{delayxms2;//此处时间不能太长,否者会的中断产生冲突ifkey_turn==0{flag=~flag;}whilekey_turn;}}/定时器0初始化/void timer0_initvoid{TMOD=0x01; //定时器0工作于方式1TH0=65536-10/256;TL0=65536-10%256;TR0=1;ET0=1;EA=1;}/定时0中断处理/void timer0_intvoid interrupt 1{TR0=0;//设置定时器初值期间,关闭定时器TH0=65536-10/256;TL0=65536-10%256;TR0=1;ifflag==1//电机正转{PWM1=0;time++;iftime<count{PWM2=1;}elsePWM2=0;iftime>=100{time=0;}}else //电机反转{PWM2=0;time++;iftime<count{PWM1=1;}elsePWM1=0;iftime>=100{time=0;}}}4、程序4、使单片机输出PWM,并能控制正反转和实现调速为了使大家彻底掌握此方面,下面再给出一个复杂一点的程序,实现的功能为通过一个按键控制正反转并通过另外两个按键使之可以在0到20级之间调速的程序;///程序名:PWM直流电机调速//晶振:11.00592 MHz CPU型号:STC89C52 //直流电机的PWM波控制,可以通过按键控制正反转并在0到20级之间调速///include<reg52.h>define uint unsigned intdefine uchar unsigned charuchar time,count=50,flag=1;//低电平的占空比sbit PWM1=P2^0;//PWM 通道1,反转脉冲sbit PWM2=P2^1;//PWM 通道2,正转脉冲sbit key_add=P3^5;//电机加速sbit key_dec=P3^6;//电机减速sbit key_turn=P3^7;//电机换向/函数声明/void delayxmsuint z;void Motor_turn;void Motor_add;void Motor_dec;void timer0_init;/主函数/void main{timer0_init;while1{Motor_turn;Motor_add;Motor_dec;}}/延时处理/void delayxmsuint z//延时xms程序{uint x,y;fory=z;x>0;x--fory=110;y>0;y--;}/电机正反向控制/void Motor_turn{ifkey_turn==0{delayxms2;//此处时间不能太长,否者会的中断产生冲突ifkey_turn==0{flag=~flag;}whilekey_turn;}}void Motor_add//电机加速{ifkey_add==0{delayxms2;//此处时间不能太长,否者会的中断产生冲突ifkey_add==0{count+=5;ifcount>=100{count=0;}}whilekey_add;}}void Motor_dec//电机加减速{ifkey_dec==0{delayxms2;//此处时间不能太长,否者会的中断产生冲突ifkey_dec==0{count-=5;ifcount>=100{count=0;}}whilekey_dec;}}/定时器0初始化/void timer0_init{TMOD=0x01; //定时器0工作于方式1TH0=65536-10/256;TL0=65536-10%256;TR0=1;ET0=1;EA=1;}/定时0中断处理/void timer0_int interrupt 1{TR0=0;//设置定时器初值期间,关闭定时器TH0=65536-10/256;TL0=65536-10%256;TR0=1;ifflag==1//电机正转{PWM1=0;time++;iftime<count{PWM2=1;}elsePWM2=0;iftime>=100{time=0;}}else //电机反转{PWM2=0;time++;iftime<count{PWM1=1;}elsePWM1=0;iftime>=100{time=0;}}}5、利用单片机输出PWM简单控制小车直行相信通过上面的讲解,大家已经能够很好的撑握如何利用51单片机产生PWM 波下面给出一个程序,通过单片机两个I/O口输出PWM波,让小车直行;include<reg52.h>define uint unsigned intdefine uchar unsigned charsbit PWM1=P2^0;//接IN1 控制正转sbit PWM2=P2^1;//接IN2 控制反转sbit PWM3=P2^2;//接IN3 控制正转sbit PWM4=P2^3;//接IN4 控制反转sbit PWM5=P2^4;//接IN3 控制正转sbit PWM6=P2^5;//接IN4 控制反转sbit PWM7=P2^6;//接IN3 控制正转sbit PWM8=P2^7;//接IN4 控制反转uchar time;void main{TMOD=0x01;//定时器0工作方式1TH0=0xff;//65536-10/256;//赋初值定时TL0=0xf7;//65536-10%256;//0.01msEA=1;//开总中断ET0=1;//开定时器0中断TR0=1;//启动定时器0while1{}}void delayuint z{uint x,y;forx=z;x>0;x--fory=500;y>0;y--;}void tim0 interrupt 1{TR0=0;//赋初值时,关闭定时器TH0=0xff;//65536-10/256;//赋初值定时TL0=0xf7;//65536-10%256;//0.01msTR0=1;//打开定时器time++;iftime>=100 time=0;//1khzPWM2=0;PWM4=0;iftime<=75 PWM1=1;else PWM1=0;iftime<=80 PWM3=1; else PWM3=0;PWM6=0;PWM8=0;iftime<=50 PWM5=1; else PWM5=0;iftime<=50 PWM7=1; else PWM7=0;}。
PWM调光程序xx
用STC12C5624AD写的PWM可调C程序//本程序用占空比可调节的PWM方波来控制大功率LED的亮度,PWM波占空比可从0到100// PWM 控制LED 灯渐亮渐灭程序// 晶振为12M// 利用STC12C5624AD单片机的PWM功能产生占空比可变的PWM 方波// 按K1,PWM值增加,则占空比减小,LED 灯渐暗。
// 按K2,PWM值减小,则占空比增加,LED 灯渐亮。
// 当PWM值增加到最大值或减小到最小值时,蜂鸣器将报警。
#include<reg52.h>sfr CCON=0xD8;sfr CMOD=0xD9;sfr CL=0xE9;sfr CH=0xD8;sfr CCAP0L=0xEA;sfr CCAP0H=0xFA;sfr CCAPM0=0xDA;unsigned char PWM=0x7f; //PWM初值unsigned char flag=0;sbit K1 =P3^0; //增加键sbit K2 =P3^1 ; //减少键sbit BEEP=P2^5; //蜂鸣器sbit CR=0xDE;void Beep();void delayms(unsigned char ms);void delay(unsigned char t);void main(void){CMOD=0x02; //PCA计数脉冲选择为fos/2CL=0x00;CH=0x00;CCAP0L=0xC0;CCAP0H=PWM;CCAPM0=0x42;CR=1;while(1){if(K1==1&&K2==1)flag=0;if(K1==0){delay(50);if(K1==0&&flag==0){if(PWM<0xf5){CR=0; PWM+=10; delayms(10); CR=1;}else{ PWM=0xff;Beep();}flag=1;}}if(K2==0){delay(50);if(K2==0&&flag==0){if(PWM>0x0a){CR=0; PWM-=10 ;delayms(10); CR=1; }else {PWM=0x00;Beep();}}flag=1;}CCAP0H=PWM;}}/*********************************************************/ //蜂鸣器子程序/*********************************************************/ void Beep(){unsigned char i ;for (i=0 ;i<100 ;i++){delayms(3) ;BEEP=0 ; //Beep取反}BEEP=1 ; //关闭蜂鸣器delayms(100);}/*********************************************************/// 延时子程序1/*********************************************************/ void delay(unsigned char t){while(t--) ;}/*********************************************************/ // 延时子程序2/*********************************************************/ void delayms(unsigned char ms){unsigned char i ;while(ms--){for(i = 0 ; i < 120 ; i++) ;}}。
单片机PWM调光程序
单片机PWM调光程序随着科技的不断发展,单片机作为一种重要的电子元器件,被广泛应用于各个领域。
其中,PWM调光程序是单片机应用中的一个重要方面。
本文将探讨单片机PWM调光程序的原理和实现方法。
一、PWM调光的原理PWM调光是通过改变信号的占空比来控制电源输出的电压或电流,从而实现对光源亮度的调节。
在PWM调光中,通过快速的开关操作,使电源以高频率的脉冲信号供电,通过改变脉冲信号的占空比来控制电源输出的平均电压或电流。
当脉冲信号的占空比为100%时,电源输出的电压或电流为最大值;当占空比为0%时,电源输出的电压或电流为最小值。
二、单片机PWM调光的实现方法1. 硬件实现方法单片机PWM调光的硬件实现方法主要涉及到三个方面的元器件:单片机、脉冲宽度调制模块和光源。
首先,需要选择一款支持PWM输出的单片机,如常见的51系列单片机或STM32系列单片机。
其次,需要使用脉冲宽度调制模块来生成PWM信号。
脉冲宽度调制模块可以是单片机内部的硬件模块,也可以是外部的PWM芯片。
最后,需要将PWM信号输出到光源,通过光源的亮度调节来实现PWM调光。
2. 软件实现方法单片机PWM调光的软件实现方法主要是通过编写程序来控制单片机输出的PWM信号。
首先,需要初始化单片机的定时器和IO口,设置PWM输出的频率和占空比。
然后,在主程序中,通过改变占空比的值来实现对光源亮度的调节。
具体的实现方法可以根据不同的单片机型号和开发环境进行调整。
三、单片机PWM调光的应用单片机PWM调光广泛应用于各个领域,如照明、舞台灯光、电子显示屏等。
在照明领域,通过PWM调光可以实现对灯具亮度的精确控制,满足不同场景下的照明需求。
在舞台灯光中,通过PWM调光可以实现灯光的渐变效果,增强舞台效果。
在电子显示屏中,通过PWM调光可以实现对显示屏亮度的调节,提高显示效果。
四、单片机PWM调光的优势相比于传统的调光方法,单片机PWM调光具有以下几个优势。
单片机PWM调光程序
单片机PWM调光程序内容:通过PWM(脉宽调制)调节LED的亮度------------------------------------------------*/#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义sbit LED0=P1^0;// 用sbit 关键字定义LED到P1.0端口,LED是自己任意定义且容易记忆的符号void Delay(unsigned int t); //函数声明/*------------------------------------------------主函数------------------------------------------------*/void main (void){unsigned int CYCLE=600,PWM_LOW=0;//定义周期并赋值while (1) //主循环{LED0=1;Delay(60000); //特意加延时,可以看到熄灭的过程for(PWM_LOW=1;PWM_LOW<CYCLE;PWM_LOW++){ //PWM_LOW表示低//电平时间,这个循环中低电平时长从1累加到CYCLE(周期)的值,即600次LED0=0; //点亮LEDDelay(PWM_LOW);//延时长度,600次循环中从1加至599LED0=1; //熄灭LEDDelay(CYCLE-PWM_LOW);//延时长度,600次循环中从599减至1}LED0=0;for(PWM_LOW=CYCLE-1;PWM_LOW>0;PWM_LOW--){ //与逐渐变亮相反的过程LED0=0;Delay(PWM_LOW);LED0=1;Delay(CYCLE-PWM_LOW);}//主循环中添加其他需要一直工作的程序}}/*------------------------------------------------延时函数,含有输入参数unsigned int t,无返回值unsigned int 是定义无符号整形变量,其值的范围是0~65535------------------------------------------------*/void Delay(unsigned int t){while(--t);}。
PWM直流电机调速单片机程序
*******************************************************************/ /* 程序名:PWM直流电机调速 *//* 晶振:11.00592 MHz CPU型号:AT89C51 *//* 直流电机的PWM波控制,可以直接的调速从0到20级的调速 *//*****************************************************************/ #include<reg51.h>#define TH0_TL0 (65536-1000)//设定中断的间隔时长unsigned char count0 = 50;//低电平的占空比unsigned char count1 = 0;//高电平的占空比bit Flag = 1;//电机正反转标志位,1正转,0反转sbit Key_add=P2 ^ 0; //电机减速sbit Key_dec=P2 ^ 1; //电机加速sbit Key_turn=P2 ^ 2; //电机换向sbit PWM1=P2^6;//PWM 通道 1,反转脉冲sbit PWM2=P2^7;//PWM 通道 2,正转脉冲unsigned char Time_delay;/************函数声明**************/void Delay(unsigned char x);void Motor_speed_high(void);void Motor_speed_low(void);void Motor_turn(void);void Timer0_init(void);/****************延时处理**********************/void Delay(unsigned char x){Time_delay = x;while(Time_delay != 0);//等待中断,可减少PWM输出时间间隔}/*******按键处理加pwm占空比,电机加速**********/void Motor_speed_high(void)//{if(Key_add==0){Delay(10);if(Key_add==0){count0 += 5;if(count0 >= 100){count0 = 100;}}while(!Key_add);//等待键松开}}/******按键处理减pwm占空比,电机减速*****/ void Motor_speed_low(void){if(Key_dec==0){Delay(10);if(Key_dec==0){count0 -= 5;if(count0 <= 0){count0 = 0;}}while(!Key_dec );}}/************电机正反向控制**************/ void Motor_turn(void){if(Key_turn == 0){Delay(10);if(Key_turn == 0){Flag = ~Flag;}while(!Key_turn);}/***********定时器0初始化***********/void Timer0_init(void){TMOD=0x01; //定时器0工作于方式1TH0=TH0_TL0/256;TL0=TH0_TL0%256;TR0=1;ET0=1;EA=1;}/*********主函数********************/void main(void){Timer0_init();while(1){Motor_turn();Motor_speed_high();Motor_speed_low();}}/**************定时0中断处理******************/ void Timer0_int(void) interrupt 1 using 1{TR0 = 0;//设置定时器初值期间,关闭定时器TL0 = TH0_TL0 % 256;TH0 = TH0_TL0 / 256 ;//定时器装初值TR0 = 1;if(Time_delay != 0)//延时函数用{Time_delay--;}if(Flag == 1)//电机正转{PWM1 = 0;if(++count1 < count0)PWM2 = 1;}elsePWM2 = 0;if(count1 >= 100){count1=0;}}else //电机反转{PWM2 = 0;if(++count1 < count0){PWM1 = 1;}elsePWM1 = 0;if(count1 >= 100){count1=0;}}}//-----------------------------------------------------------------------------#include <c8051f330.h> // SFR declarations#include <math.h>// Function Prototypes//-----------------------------------------------------------------------------#define CMD_RESET 0xA4 //HD7279复位#define DECODE1 0xc8 //方式0译码sbit cs=P1^3;sbit clk=P1^2;sbit dat=P1^1;sbit key=P1^0;sbit led_D1003=P0^7;sbit sw1=P1^7;sbit sw2=P1^6;sbit sw3=P1^5;sbit sw4=P1^4;void long_delay(void); //延时函数void short_delay(void);void delay10ms(unsigned char);void write7279(unsigned char,unsigned char); //HD7279写指令void send_byte(unsigned char);void delay(unsigned char);void disp1(unsigned int);void OSCILLATOR_Init (void);void PORT_Init (void);void PCA0_Init (void);void Timer0_Init(void);void Ext_Interrupt_Init (void);//-----------------------------------------------------------------------------// Global Variables//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------// main() Routine//-----------------------------------------------------------------------------unsigned int CEX0_Compare_Value; // Holds current PCA compare valueunsigned int tmr,Speed_evaluate;unsigned char num,num1,num2,num3,a;unsigned int Speed,pi,Speed2;unsigned int Speed1[10];typedef struct {double SetPoint; /* 设定目标Desired Value */double Proportion; /* 比例常数Proportional Const */double Integral; /* 积分常数Integral Const */double Derivative; /* 微分常数Derivative Const */double LastError; /* 前一项误差*/double PrevError; /* 前第二项误差*/double SumError; /* 误差和*/} PID;double PIDCalc( PID *pp, double NextPoint ){double dError,Error,Pout;Error = pp->SetPoint - NextPoint; /* ?????? */pp->SumError += Error; /* ??????/dError = pp->LastError - pp->PrevError; /* ???? */pp->PrevError = pp->LastError;pp->LastError = Error; /* ??????? */Pout= pp->Proportion * Error + pp->Integral * pp->SumError +pp->Derivative * dError ;if(Pout>1100)Pout=1000;if(Pout<100)Pout=100;return (Pout);}PID sPID; //定义PID结构体变量double rOut; //PID响应输出unsigned char rIn; //设置PID反馈值double x;double sumout;unsigned char dd;//设置PID输出void main (void){sPID.Proportion = 0.44; //设置PsPID.Integral = 0.70; //设置IsPID.Derivative = 0.0; //设置D//sPID.SetPoint = CEX0_Compare_Value;//sPID.SetPoint = CEX0_Compare_Value; //设置PID输出PCA0MD = 0x00; // Disable watchdog timerled_D1003=0;PORT_Init (); // Initialize crossbar and GPIO OSCILLATOR_Init (); // Initialize oscillatorPCA0_Init (); // Initialize PCA0IP=0x82; //定时器中断0高于外部中断0Timer0_Init();Ext_Interrupt_Init ();for (tmr=0;tmr<0x2000;tmr++);send_byte(CMD_RESET);//HD7279复位// Globally enable interrupts EA = 1;sPID.SetPoint=70;while (1){delay10ms(100);//键盘程序------------------------------------------------------------- if(sw1==0) //按键1是否按下{if(sw1==0)//再次检查按键{num++; //若按键按下,num加1if(num==1) //到9归0{num=0;}while(sw1==0);//按键释放}// delay10ms(100);}write7279(DECODE1+4,num); //将num写入HD7279第1位 delay10ms(1);if(sw2==0){if(sw2==0){num1++;if(num1==2){num1=0;}while(!sw2);}// delay10ms(100);}write7279(DECODE1+5,num1);//将num1写入HD7279第2位delay10ms(1);if(sw3==0){if(sw3==0){num2++;if(num2==10){num2=0;}while(!sw3);}// delay10ms(100);}write7279(DECODE1+6,num2);//将num1写入HD7279第2位delay10ms(1);if(sw4==0){if(sw4==0){num3++;if(num3==10){num3=0;}while(!sw4);}// delay10ms(100);}write7279(DECODE1+7,num3);//将num1写入HD7279第2位delay10ms(1);Speed_evaluate=num*1000+num1*100+num2*10+num3;sPID.SetPoint=Speed_evaluate;//控制程序-----------------------------------------------------------------//---------------------------------------------------------------------------}}void OSCILLATOR_Init (void){OSCICN = 0x83; // Set internal oscillator torun// at its maximum frequencyCLKSEL = 0x00;}void PORT_Init (void){XBR0 = 0x00;XBR1 = 0x41;// Enable crossbar and weak pull-upsP0MDOUT |= 0x10; // Set CEX0 (P0.4) to push-pull P0SKIP |=0x0F; //P1SKIP = 0x00;P1MDOUT= 0x0f;}void PCA0_Init (void){PCA0CN = 0x00; // Stop counter; clear all flagsPCA0MD = 0x01; // Use Ettern ime basePCA0CPM0 = 0xCB; // Module 0 = 16-bit PWM mode and// enable Module 0 Match and Interrupt// Flags// Configure initial PWM duty cycle = 50%CEX0_Compare_Value = 65536 - (65536 * 0.15);PCA0CPL0 = (CEX0_Compare_Value & 0x00FF);PCA0CPH0 = (CEX0_Compare_Value & 0xFF00)>>8;EIE1 |= 0x10; // Enable PCA interrupts// Start PCA counterCR = 1;}void Ext_Interrupt_Init (void){TCON |= 0x05; // /INT 0 and /INT 1 are edge triggeredIT01CF = 0x10; // /INT0 active low; /INT0 on P0.0;// /INT1 active low; /INT1 on P0.1EX0 = 1; // Enable /INT0 interrupts}void Timer0_Init(void){TH0 = 0 ; // Init Timer0 High registerTL0 = 0 ; // Init Timer0 Low registerTMOD |= 0x01; // Timer0 in 16-bit mode方式1CKCON |= 0x02; // Timer0 uses a 1:48 prescalerET0 = 1; // Timer0 interrupt enabledTCON|=0x10;// Timer0 ON}// PCA0_ISR//-----------------------------------------------------------------------------void PCA0_ISR (void) interrupt 11{CCF0 = 0; // Clear module 0 interrupt flag.PCA0CPL0 = (CEX0_Compare_Value & 0x00FF);PCA0CPH0 = (CEX0_Compare_Value & 0xFF00)>>8;}void Timer0_ISR (void) interrupt 1 {int j,sum;TF0=0;// Clear interrupt flag.a++;if (a==4){Speed1[pi]=Speed;if(pi>=3){ EX0 = 0;for(j=0;j<=3;j++){sum=sum+Speed1[j];}Speed2=sum/4;disp1(Speed2);Speed=0;pi=0;EX0 = 1;}a=0;sum=0;if(pi>=3)pi=0;elsepi++;TH0 = 0; // Reinit Timer0 High register TL0 = 0; // Reinit Timer0 Low registerif(abs( sPID.SetPoint-Speed2)<=5) {CEX0_Compare_Value=CEX0_Compare_Value;}else{rIn =Speed2; for(dd=0;dd<50;dd++)x=rIn;//x = 5.0 * (double)rIn / 256.0;rOut = PIDCalc ( &sPID,x );// sumout=rOut*256/5;if(rOut==100)sumout=0;elsesumout= (0.85/1000.0)*rOut;//CEX0_Compare_Value=CEX0_Compare_Value-sumout;CEX0_Compare_Value = 65536 - (65536 * ( sumout+0.15));}}else{TH0 = 0; // Reinit Timer0 High registerTL0 = 0; // Reinit Timer0 Low register}}void INT0_ISR (void) interrupt 0{IE0=0; // // Clear interrupt flag.Speed++;}void write7279(unsigned char cmd, unsigned char dta) {send_byte(cmd);send_byte(dta);}void send_byte( unsigned char out_byte){unsigned char i;cs=0;long_delay();for (i=0;i<8;i++){if (out_byte&0x80){dat=1;}else{dat=0;}clk=1;short_delay();clk=0;short_delay();out_byte=out_byte*2; }dat=0;}void long_delay(void){unsigned char i;for (i=0;i<0x30;i++);}void short_delay(void){unsigned char i;for (i=0;i<8;i++);}void delay10ms(unsigned char time) {unsigned char i;unsigned int j;for (i=0;i<time;i++){for (j=0;j<0x390;j++);}}void disp1(unsigned int date){unsigned char d0, d1, d2 , d3; d0=date / 1000;d1=(date-d0*1000)/100;d2=(date-d0*1000-d1*100)/10 ;d3= date-d0*1000-d1*100-d2*10;write7279(DECODE1,d0);delay10ms(1);write7279(DECODE1+1,d1);delay10ms(1);write7279(DECODE1+2,d2);delay10ms(1);write7279(DECODE1+3,d3);delay10ms(1);}。
51单片机实现PWM波占空比可调
51单片机实现PWM波占空比可调单片机实现PWM波占空比可调的方法有很多种,下面将详细介绍一种常见的实现方式。
PWM(脉冲宽度调制)是一种常用的数字信号调制技术,可以通过改变脉冲的高电平时间来控制电平的占空比,从而实现对信号的调节。
在单片机中,可以使用定时器/计数器模块来生成PWM波,并通过改变计数器的值来调整占空比。
以AT89C51单片机为例,以下是实现PWM功能的步骤:1.设置定时器模式:选择合适的定时器模式来生成所需的PWM信号。
AT89C51单片机有定时器/计数器模块,可以选择模式2,该模式下定时器有自动重装载功能,能够方便地实现周期性的PWM波。
3. 设置PWM参数:根据需要调节的占空比,计算出所需的高电平时间和低电平时间。
通常,PWM波的高电平时间与低电平时间之和等于一个周期的时间(定时器的重装载值)。
例如,如果需要一个占空比为60%的PWM波,周期为20ms,则高电平时间为「20ms * 60% = 12ms」,低电平时间为「20ms - 12ms = 8ms」。
4.设置PWM引脚:选择一个合适的IO口作为PWM波的输出引脚,并在程序中设置该引脚为输出模式。
5.编写中断服务程序(ISR):针对定时器溢出中断(TOF)编写中断服务程序。
每当定时器溢出时,PWM波应该翻转输出引脚的电平,以实现所需的占空比。
6.初始化定时器和中断:在程序初始化阶段,将定时器设为所需的模式,设置中断向量表中的对应中断服务函数,并开启定时器中断。
7.主循环中设置占空比:在主循环中,通过改变定时器的初值来实现不同占空比的调节。
将计算得到的高电平时间和低电平时间分别赋值给定时器初值,即可实现占空比的调整。
通过上述步骤,我们可以实现占空比可调的PWM波。
在实际应用中,可以根据需要进行适当的优化和改进,例如增加输入口的设置,使得用户可以通过外部按键或旋钮来实时调整占空比,从而更加灵活地控制PWM波的输出。
总结:通过合适的定时器模式、初值设置和中断服务程序编写,配合适当的IO口配置和占空比计算,我们可以在单片机中实现占空比可调的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口设置为输出模式。
单片机PWM调光程序
RCT_RELAYER=0x00;//充电
//P27=0x00;//电源指示灯
delay_ms(100);//延时100ms
relay_check();//继电器监测
POW_RELAYER=0x00;//24V合闭
stepdelay(2);
stepdelay(2);
//P0=sp0[0];
LED3 = 1;
LED3 = LED3^0;
LED2 = LED2^0;
LED1 = LED1^0;
P14_MOSL = P14_MOSL^1;
P13_MOSL = P13_MOSL^0;
P13_MOSH = P13_MOSH^0;
P11_MOSL = P11_MOSL^0;
P11_MOSH = P11_MOSH^0;
{
shutdown();
}
}
if(~ONOFF_MCU&DET_MCU)//无5V进来
{
//keyDelay();
//if(~ONOFF_MCU)
{
delay_ms(80);
if(~ONOFF_MCU&DET_MCU)//无3.3V进来
{
//keyDelay();
//if(DET_MCU)
shutdown();
#include <reg52.h>
#include "DZ10.h"
//定义变量////////
//unsigned char dummyp3;
//unsigned char dimvertion;
unsigned char sp0[15];
//unsigned char sp2[15];
用单片机实现频率可调的PWM控制信号
用单片机实现频率可调的PWM控制信号作者:林广峰来源:《科技传播》2010年第12期摘要本文介绍了一种用51系列单片机的定时器来实现频率可调的PWM信号,提供了一种可靠、有效、灵活的方法,信号准确、稳定,频率和占空比调节方便、直观,电路简单、集成度高,成本低,最高可实现几十KHz频率和占空比可调的PWM信号。
可作为各种需要PWM控制的信号源发生器。
关键词单片机;定时器;频率;PWM;占空比中图分类号TP368.1文献标识码A 文章编号 1674-6708(2010)21-0220-020 引言在嵌入式系统及控制系统中,经常需要产生特定频率和PWM的方波脉冲信号,以便实现精确的控制过程。
在实际应用中,为了达到最佳的控制,往往需要对驱动控制信号的频率和占空比都能够按要求进行调节,也就是需要实现可调频率的PWM控制。
在传统电路中,用555来实现的是比较经典的电路,但通过R、C来调节脉冲时,频率和占空比可调的范围不大,器件的误差带来的影响较大,调节时不直观,调节参数具有一定的离散性,不利于批量生产。
对于需要经常改变参数的情况更不方便。
随着数字技术的不断发展,单片机的性能越来越强,价格也越来越低,51系列作为非常成熟的8位单片机,在国内得到了广泛的应用。
采用51系列单片机除了能完成所需的控制功能外,完全能够实现对方波信号的频率和占空比的调节,不再需要额外的信号发生电路,采用软件控制这种方法,电路简单,调节方便,显示直观,误差小,一致性好,可靠性高。
1 实现原理脉冲宽度调制(PWM)是英文“Pulse Width Modulation”的缩写,它是通过调节方波的占空比来实现的,只要占空比的步进精度足够,就可以通过PWM来实现数字输出信号对模拟电路的有效控制,比如灯光的亮度、流量的控制、开关电源电压的控制等等。
脉冲宽度调制在工业控制、电源变换、测试测量、通信等领域都有广泛的应用。
在一些文献中,产生各种波形信号,采用的是软件延时的方式,但这种方式占用了单片机的处理时间,且精度不易控制,尤其是在调节时计算比较复杂,本文采用的是定时器中断方式,单片机通过中断来产生对应的脉冲信号,还可以同时进行其他输入、输出控制功能,定时器的精度较高,调节时也仅需通过软件调整对应的设置值即可。
单片机输出PWM温控程序C语言代码
单片机PWM温控C语言程序部分代码#include <reg52.h>#include <at89x52.h>#include <keyscan.h>extern void scan_full(void);extern unsigned char key_scan(void);extern bit key_ok;unsigned char pwm_set,key_value;unsigned char count;sbit PWM=P3^6; //将PWM定义为P3口的第六位?bit up,down,set_flag;unsigned char code BCD[]={0x3f,0x06,0x5b,0x4f, //此处是将0-F转换成0x66,0x6d,0x7d,0x07, //相应的BCD码0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delay1(unsigned char t){while(t--);}void pwm(void) interrupt 5//定时器2产生PWM波形{TF2=0; //定时器2的溢出标志要软件清除,//但当RCLK或TCLK为1时由硬件清除if((count>=pwm_set)&amt;&amt;(count<10))PWM=1;elsePWM=0;count++;if(count==10)count=0x00;}void key_pwm(unsigned char x)//把键值转化为PWM设置值{switch(x) //把矩阵键盘转化为独立键盘{case 1:up=1;break;case 2:down=1;break;case 3:set_flag=!set_flag;break;default:break;}//设置PWM参数:pwm_setif(up&amt;&amt;set_flag){pwm_set++;up=0;if(pwm_set>=10)pwm_set=0x00;}if(down&amt;&amt;set_flag){pwm_set--;down=0;if(pwm_set==0xff) //减到-1?pwm_set=9;}if(!set_flag){up=0;down=0;}}void main(void){TH2=0xb1; //定时20MSTL2=0xe0;RCAP2H=0xb1;//定时器2溢出会把该单元内容送到TH2和TL2 RCAP2L=0xe0;EA=1;ET2=1;TR2=1;while(1){scan_full(); //看是否有键按下if(key_ok) //有键按下,则判断到底是哪个键按下{key_value=key_scan();//键值送key_value暂存P0=~BCD[key_value]; /*此三句是将键值显示出来*/P2=0xfe;delay1(200);key_pwm(key_value); //调用键值转PWM设置参数函数key_value=0x00; //清除键值,以免一次按下,多次响应}P0=~BCD[pwm_set]; /***此三句是将pwm_set值显示出来*/P2=0xfd;delay1(200);}}#include <reg52.h>//#include <at89x52.h>//unsigned char code BCD[]={0x3f,0x06,0x5b,0x4f, //此处是将0-F转换成//相应的BCD码 :// 0x66,0x6d,0x7d,0x07,// 0x7f,0x6f,0x77,0x7c,// 0x39,0x5e,0x79,0x71};//unsigned char code KEY[]={0x00,0x00,0x01,0x02,0x03,//此处是为使程序通用,当键值不是按// 0x04,0x05,0x06,0x07,//这个排列时,把此表更改即可// 0x08,0x09,0x0a,0x0b,//最前面的那个0x00是为了查表方便,// 0x0c,0x0d,0x0e,0x0f};//因为键值是从1开始的sfr key_port=0x90; //定义P1口为键盘扫描口bit key_ok=0; //有键按下的标志/*************延时子程序*****************调用一次用时18微秒,t每加1,用时增加6微秒*/void delay(unsigned char t){while(t--);}unsigned char r_left(unsigned char x)//循环左移一位{x<<=1;x++;return(x);}/*************粗判有无键按下**************有键按下则将key_ok置1************/void scan_full(void){unsigned char temp;key_port=0xf0; //低半字节为行线,高半字节为列线temp=P1;if(temp!=0xf0)key_ok=1;elsekey_ok=0;}/************键盘扫描程序*****************************功能:返回键值,当无键按下时,返回0*************/unsigned char key_scan(void){unsigned char temp,count=0x01,key_value;//按键返回值unsigned char x_scan=0xfe,y_scan=0xef;//行、列扫描码unsigned char i,j,y; //行数和列数while(1){scan_full(); //粗判是否有键按下if(key_ok==1){key_ok=0;delay(200); //延时去抖动scan_full(); //再次粗判是否有键按下if(key_ok==1){for(i=0;i<4;i++) //扫描4行{key_port=x_scan;for(j=0;j<4;j++) //每行4列{temp=key_port;temp=temp&amt;0xf0;y=y_scan&amt;0xf0;if(temp==y){while(key_ok!=0)//等待按键松开{scan_full();}key_value=count;return(key_value);//找到键值,马上返回}else{count++;y_scan=r_left(y_scan);}}y_scan=0xef; //扫描完一列,重新对列扫描量赋初值x_scan=r_left(x_scan);//行扫描码左移一位,扫描下一行}}}return(key_value);//没键按下,返回0}}//unsigned char key(void)//{// unsigned char x;// unsigned char y;// x=key_scan();// return(x);// y=KEY[x];// return y;//}。
51单片机软件产生PWM驱动直流电机,频率占空比可调
51单片机软件产生PWM驱动直流电机,频
率占空比可调
做了一个实例,以前都是用AVR直接硬件生成PWM,方便快捷,几条语句的问题,驱动能力还强,从来没仔
细想过如何用51单片机软件方法做一个,现在非要用51单片机做,那就直接开始制作,首先硬件焊接,软件编程,只说程序部分,程序采用占空比可调,频率可调的
思路,需要用到2个定时器,1个定时器输出占空比信号数据,另个定时器标定频率,具体的程序稍后放出,其
实也不太难,问题1:如何做到定时器内的软件时间低
于定时器定时中断时间,频率低无所谓,频率要是到了20khz,这个问题就有些困难,有些if语句进入循环后
可以到20ms,这个问题解决采用51单片机特有的中断嵌套解决。
问题2 :如何做到外部中断、定时器0、定时器1中断优先级分级?解决方法就是分别在各自的服务程序中处理
好中断优先级。
视频:。
51单片机产生PWM波
69.2
2
71,30
1058
69.6
3
73,30
1038
70.2
4
74,31
1019
69.9
5
76,32
992
69.0
6
76,31
1001
70.0
频率相对误差(%) 6.8 5.8 3.8 1.9 0.8 0.1
总结:定时器理论初值为(65536-100)时,中断一次的时间为 100Us,
而执行一条语句时间为 1~4Us,这样会使 T 变大,f 减小,误差较大;
main() {
Init(); while(1) {
if(num<=8)output=1; else output=0; } }
//使占空比为 7:3
void Timer_0(void) interrupt 1 //中断函数
{
TH0=(65536-n)/256; //(65536-n)为定时器初值
TL0=(65536-n)%256;
51 单片机产生PWM方波
//利用定时器产生频率为 1KHz,占空比为 7:3 的 PWM 方波
#include<reg52.h> //头文件
sbit output=P1^1; //输出端
unsigned char num=1; //辅助计时
void Init(void) //初始化函数 {
TMOD=0x01; TH0=(65536-n)/256; //(65536-n)为定时器初值 TL0=(65536-n)%256; EA=1; ET0=1; TR0=1; }
频率相对误差(%) 12 3.7 1.4 0.8 0.2
基于单片机与 PWM 技术的可调灯光系统程序设计
目录一、系统总体设计: (1)1、设计背景: (1)2、设计思路 (1)3、工作原理 (1)二、系统结构分析 (1)1、程序流程图 (1)2、部分结构 (2)三、九级PWM亮度调节程序 (3)1、实验代码 (3)2、程序运行结果 (5)四、无级PWM亮度调节 (5)1、原理 (5)2、代码 (6)3、程序运行结果 (8)五、设计感想与体会 (8)一、系统总体设计:1、设计背景:现当今,单片机的应用无处不在。
利用单片机控制灯具的实例也不胜枚举,可控制灯具的芯片也相当之多,而利用单片机控制灯具,达到人们预想效果的方法最为广泛。
它有功能多、价格优、外部电路简单的特点,深受单片机爱好者及灯具控制制造商的青昧,用80C51 单片机及少数外部电路控制灯光,使灯具产生明暗效果。
2、设计思路本次课设基于AMC51单片机综合开发系统,利用单片机的定时中断生成不同的PWM波形,通过调整PWM的周期、PWM的占空比从而控制输出平均电压,进而达到对电灯进行光度亮暗的控制调节的效果,实现对电灯的PWM调光控制。
3、工作原理对于控制电灯由亮到暗或由暗到亮,采用的是脉宽PWM法。
它是把每一脉冲宽度均相等的脉冲列作PWM波形,通过改变脉冲占空比可以调压,采用适当控制方法即可使电压与频率协调变化。
可以通过调整PWM的占空比而达到控制电流的目的。
二、系统结构分析1、程序流程图T0中断(产生基波) T1中断(控制脉宽)2、部分结构(i)按键扫描:按键时触点会存在按键抖动,故在写程序时需要加入去抖动程序。
(ii)脉冲宽度调制(PWM):是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
在本程序中,通过PWM波去控制灯泡的亮度主要是通过改变灯泡在一个周期内(即2000u s)灯泡亮的时间,即可感受到不同占空比下灯泡的亮度对人眼的不同视觉效应。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/**************************************************/
#include<reg51.h>
void delay(unsigned char t);
sb1^1; //减少键
/**************************************************/
//晶振12M
//利用定时器控制产生频率10MHZ占空比的可变PWM波形
//按K1,PWM值增加,则占空比增加。
//按K2,PWM值减小,则占空比减小。
//按K3,复位,频率10KHZ的占空比为50%的波形
{
delay(10);
if(K3==1)
{
PWA=0xce;
while(K3==1);
}
}
}
}
/**************************************************/
//定时器0中断服务程序
}
if(K2==1) //减少脉宽
{
if(PWM!=0x0A)
{
deiay(10);
if(K2==1)
{
PWM--;
while(K2==1);
}
}
}
if(K3==1) //脉宽复位
//延时之程序
/*************************************************/
void delay(unsigned char t)
{
while(t--);
}
/*************************************************/
void timer0()interrupt 1
{
TR0=0;
TH1=PWM; //赋脉宽值
TL1=PWM;
TR1=1;
TR0=1;
KEY=0; //输出高脉宽
}
/**************************************************/
sbit K3=P1^2; //复位
sbit KEY=P2^3; //PWM输出
unsigned char PWM=0xce; //赋初值脉宽50%
/*************************************************/
void main()
{
//定时器1中断服务程序
/*************************************************/
void timer0()interrupt 3
{
TR0=0;
KEY=1; //输出高脉宽
}
/**************************************************/
TMOD=0x22; //T0、T1方式2
TH0=0x9c; //产生频率10KHZ 即周期100us
TL0=0x9c; //频率调节
TH1=PWM; //脉宽调节
TL1=PWM;
EA=1; //开定时器中断T0、T1
ET0=1;
ET1=1; //开定时器T0关定时器T1
TR0=1;
TR1=0;
while(1)
{
if(K1==1) //增加脉宽
{
if(PWM!=0xfa)
{
delay(10);
if(K1==1)
{
PWM++;
while(K1=1);
}
}