单片机如何使用pwm_stm32输出pwm与51单片机输出pwm - CSDN
  • 利用51单片机输出pwm

    2017-06-07 09:57:52
    51单片机是可以输出PWM的,比较的麻烦。此时需要用到内部定时器来实现,可用两个定时器实现,也可以用一个定时器实现。  用两个定时器的方法是用定时器T0来控制频率,定时器T1来控制占空比。大致的的编程思路是这样...
     51单片机是可以输出PWM的,比较的麻烦。此时需要用到内部定时器来实现,可用两个定时器实现,也可以用一个定时器实现。

      用两个定时器的方法是用定时器T0来控制频率,定时器T1来控制占空比。大致的的编程思路是这样的:T0定时器中断让一个I0口输出高电平,在这个定时器T0的中断当中起动定时器T1,而这个T1是让IO口输出低电平,这样改变定时器T0的初值就可以改变频率,改变定时器T1的初值就可以改变占空比。

      下面重点介绍用一个定时器的实现PWM的方法。以周期为1ms(1kHZ)为例,要产生其它频率的PWM波,程序中只需作简单修改即可。用一个定时器时(如定时器T0),首先要确定PWM的周期T和占空比D,确定了这些以后,就可以用定时器产生一个时间基准t,比如定时器溢出n次的时间是PWM的高电平的时间,则D*T=n*t,类似的可以求出PWM低电平时间需要多少个时间基准n。

      因为这里我们是产生周期为1ms(1kHZ)的PWM,所以可设置中断的时间基准为0.01ms,,然后中断100次即为1ms。在中断子程序内,可设置一个变量如time,在中断子程序内,有三条重要的语句:

       1、当time>=100时,time清零(此语句保证频率为1kHZ);

       2、当time>n时(n应该在0-100之间变化开),让单片相应的I/O口输出低电平;

       3、当time<=n时,让单片相应的I/O口输出高电平,此时占空比就为%n。

     下面程序产生30%占空比的pwm:

    #include<reg51.h>
    #define uint unsigned int
    #define uchar unsigned char
    
    sbit PWM=P2^0;//  P2.0输出pwm
    uchar time;  // 定义占空比的变量
    
    void main()
    {
    	TMOD=0x01;//定时器0工作方式1
    	TH0=0xff;//(65536-10)/256;//赋初值定时
    	TL0=0xf7;//(65536-10)%256;//0.01ms
    	EA=1;//开总中断
    	ET0=1;//开定时器0中断
    	TR0=1;//启动定时器0 
    	while(1)
    	{			
    	}			
    }
    
    void tim0() interrupt 1
    {
    	TR0=0;//赋初值时,关闭定时器
    	TH0=0xff;//(65536-10)/256;//赋初值定时
    	TL0=0xf7;//(65536-10)%256;//0.01ms
    	TR0=1;//打开定时器
    
    	time++;
    	if(time>=100)  //1khz
    	  time=0;   
    	if(time<=30)   //占空比%30,可改
    	  PWM=1;  
    	else PWM=0;
    }


       最后的到波形,在示波器上显示如下图所示:


       如果想修改占空比,直接在程序里面修改下面这句即可。
       if(time<=30)//占空比%30,可改占空比

       当然我们可以加入其它的手段来动态改变占空比,比如按键,上位机等。
    按键动态调节占空比可参考我另一篇博客:http://blog.csdn.net/dmfylb/article/details/72605221


    展开全文
  • 51单片机使用PWM渐变方法控制流水灯亮灭C语言案例示范,自写。
  • 单片机_PWM输出原理详解 理论篇   博主自己的经历告诉我,PWM波的理解和应用确实还是挺重要的,这里专门花一期详细介绍一下 什么是PWM?   PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是...

    单片机_PWM输出原理详解

    理论篇
      博主自己的经历告诉我,PWM波的理解和应用确实还是挺重要的,这里专门花一期详细介绍一下

    • 什么是PWM?

      PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码。
      通俗的说,就是控制在一个周期内,控制高电平多长时间,低电平多长时间(前面文章种有说过IO口就只有两种状态,0和1,对应就是0和5V或者0和3.3V)。也就是说通过调节高低电平时间的变化来调节信号、能量等的变化。
    图为周期4毫秒的PWM波形
      图为周期4毫秒的PWM波形

    • 两个重要的概念,频率、占空比

      频率是指每秒钟信号从高电平到低电平再回到高电平的次数,为一个PWM波周期的倒数。上图中频率=1/(0.003+0.001)=250 HZ
      占空比是指高电平持续时间比一个周期持续的时间。上图中占空比=1/(1+3)=25%,所以可以通过控制占空比,来控制输出的等效电压。
      所以对于方波的话,频率和占空比就确定了一个波。

    • 怎么能产生一个PWM波?

      方法1利用芯片内部模块输出PWM信号,STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样, STM32 最多可以同时产生 30 路 PWM 输出! 但是!!!同一个定时器TIM只能产生一个频率的PWM波,你只能改变占空比。 具体例程见一下实战篇STM32部分。
      方法2利用IO口高低电平转变输出PWM信号,比如上图中先把电平置1,维持1ms,然后将电平拉低,维持3ms,再将电平置高,如此循环往复下去,就可以产生一个周期4毫秒占空比为25%的PWM波了。具体方法就是给IO口加一个定时器,用定时器中断来实现及时切换高低电平。 具体历程见以下51单片机部分。

    • 定时器

      要想使用51单片机来产生一路PWM,根据上述的方法2,首先你应该知道什么是定时器?定时器是怎么工作的?

      定时器:和计数器说的是一个东西,因为它既能计时也能计数。定时器的实质是,由机器频率向一个16位寄存器累加,累加满溢出时触发中断。为了产生一个我们想要的时间间隔。比如说1s,所以我们要在这个寄存器里设定一个初值,以至于让它在这个初值上累加可以产生一个1s的倍数。这样我们就得到了稳定的时间间隔。
      这个寄存器分为TH(高八位)和TL(低八位)。所以我们需要把计算好的初值分成两部分分别放入TH和TL。

      过程
      首先,我们通过单片机的晶振频率得知其时钟周期,再尤其乘以12得到机器周期。每一个机器周期在寄存器内+1,直到加满溢出产生中断。

      举例说明
      若单片机频率为12Mhz,其时钟周期就是1/12μs,机器周期为1μs,也就是每1μs寄存器+1。16位的寄存器加到溢出最多需要(2^16)-1=65535μs,溢出也需要一个机器周期,所以总共要65536μs。但这个值太别扭,和我们要的1s没什么关系。我们最好让它记50000μs产生一次中断,所以其初值就设为65536-50000=15536。但我们还要将这个值分别放在高八位和低八位,所以要将这个十进制数,转换为4位十六进制数再分开赋值。十进制计算法:TH = 15536/256; TL = 15536%256;,进制计算问题这里不细讨论。这样的话,每50ms就会产生一次中断。我们只要用程序判断其中断20次就记1s。
      定时器部分摘自:https://www.jianshu.com/p/90ea43a7b4fd

    • PWM的应用

    1 输出模拟电压(通过电压的高低来控制如LED的亮度,直流电机的速度等)
      PWM对模拟信号电平进行数字编码的方法,计算机只能输出0或5V的数字电压值而不能输出模拟电压,而我们如果想获得一个模拟电压值(介于0 - 5V的电压值),则需通过使用高分辨率计数器,改变方波的占空比来对一个模拟信号的电平进行编码。电压是以一种连接(1)或断开(0)的重复脉冲序列被夹到模拟负载上去的,连接即是直流供电输出,断开即是直流供电断开。通过对连接和断开时间的控制,只要带宽足够,可以输出任意不大于最大电压值的模拟电压。

      输出电压=(接通时间/脉冲时间)*最大电压值12

    PWM输出等效电压
       PWM输出等效电压
    解释部分引自 http://www.eeworld.com.cn/mcu/article_2018061939827.html

    2 控制舵机
      大一大二期间做项目经常用到的一个元件就是舵机,而舵机的控制就是通过一个固定周期但是不同占空比来控制舵机摆角的位置的。
      舵机的控制一般需要一个20ms左右的时基脉冲(频率为50HZ),该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分,总间隔为2ms。以180度角度伺服为例,那么对应的控制关系是这样的:
    0.5ms--------------0度;
    1.0ms------------45度;
    1.5ms------------90度;
    2.0ms-----------135度;
    2.5ms-----------180度;
    在这里插入图片描述
    此图可以表现脉冲宽度(也可以转换成占空比)和舵机摆臂的位置图
    3 控制步进电机
      之前在做项目的过程中,一般涉及到精确控制位移的时候,这个时候往复式驱动原件(舵机)就不适合了,所以就会经常用到步进电机。
      步进电机把电脉冲信号变换成角位移以控制转子转动的微特电机。在自动控制装置中作为执行元件。每输入一个脉冲信号,步进电动机前进一步,故又称脉冲电动机。 !!!这里注意一点,直接控制单片机的话是脉冲控制,就是进来一个脉冲信号,步进电机转动一个步进角(一般为1.8°)。所以控制步进电机速度的方式就是通过控制 频率 (占空比一般都是50%)但是!!!现在可以通过接入步进电机驱动板的方式(比如博主之前使用的一款步进电机驱动板Tb6560)细分步进角。比如细分为2,一个脉冲步进电机就转动半个脉冲(0.9°)

    PS:这里由于篇幅原因,舵机、步进电机的控制代码就不上传了,网上一搜一大堆,也可以联系博主私法给你喽!


    实战篇

      这里使用51和STM32实现呼吸灯的功能,同样原理也可以控制直流电机,舵机是频率一定的情况下控制占空比来控制摆臂的方向,而步进电机是通过控制频率的方式来控制速度。

    51部分
      例程使用51单片机将P1.0接一个二极管。运用PWM输出等效模拟电压完成呼吸灯功能。引

    unsigned char PWM_COUNT;  //计数
    unsigned int  HUXI_COUNT;    //占空比更新时间
    unsigned char PWM_VLAUE;    //占空比比对值
    bit direc_flag;             //占空比更新方向
    
    void timer0_init()
    {
        TMOD=0x02;          //模式设置,00010000,定时器0,工作于模式2(M1=1,M0=0)
        TH0=0x47;               //定时器溢出值设置,每隔200us发起一次中断。
        TL0=0X47;
        TR0=1;                  //定时器0开始计时
        ET0=1;                  //开定时器0中断
        EA=1;                       //开总中断
        PWM_COUNT =0;
    }
    
    void time0() interrupt 1
    {   
        PWM_COUNT++;
        HUXI_COUNT++;
        if(PWM_COUNT == PWM_VLAUE)      //判断是否到了点亮LED的时候
            LED = 1;                    //点亮LED
        if(PWM_COUNT == 10)             //当前周期结束
        {
            LED = 0;                    //熄灭LED
            PWM_COUNT = 0;              //重新计时
        }
    
        if((HUXI_COUNT == 600) && (direc_flag == 0))
        {                               //占空比增加10%
            HUXI_COUNT = 0;
            PWM_VLAUE++;
            if(PWM_VLAUE == 9)          //占空比更改方向
                direc_flag = 1; 
        }
    
        if((HUXI_COUNT == 600) && (direc_flag == 1))
        {                               //占空比减少10%
            HUXI_COUNT = 0;
            PWM_VLAUE--;
            if(PWM_VLAUE == 1)          //占空比更改方向
                direc_flag = 0; 
        }   
    }
    void main()
    {
        HUXI_COUNT = 0;
        PWM_COUNT = 0;
        PWM_VLAUE = 5;
        direc_flag = 0;
        LED = 1;            //默认LED熄灭   
        timer0_init();      //定时器0初始化
        while(1);
    }
    

      例程部分引自 http://www.eeworld.com.cn/mcu/article_2018061939827.html 有删改

    32部分
      转自正点原子库函数手册PWM部分教程
      这里用到了 TIM3 的部分重映射功能(重映射:可以理解成把管脚的外设功能映射到另一个管脚,具体哪个引脚可以映射见参考手册), 例程把 TIM3_CH2 直接映射到了 PB5 上。

    //TIM3 PWM 部分初始化
    //PWM 输出初始化
    //arr:自动重装值
    //psc:时钟预分频数
    void TIM3_PWM_Init(u16 arr,u16 psc)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
        TIM_OCInitTypeDef TIM_OCInitStructure;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //①使能定时器 3 时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|
        RCC_APB2Periph_AFIO, ENABLE); //①使能 GPIO 和 AFIO 复用功能时钟
        GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //②重映射 TIM3_CH2->PB5
        //设置该引脚为复用输出功能,输出 TIM3 CH2 的 PWM 脉冲波形 GPIOB.5
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure); //①初始化 GPIO
        //初始化 TIM3
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在自动重装载周期值
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //③初始化 TIMx
        //初始化 TIM3 Channel2 PWM 模式
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
        TIM_OC2Init(TIM3, &TIM_OCInitStructure); //④初始化外设 TIM3 OC2
        TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器
        TIM_Cmd(TIM3, ENABLE); //⑤使能 TIM3
    }
    
    
    int main(void)
    {
        u16 led0pwmval=0;
        u8 dir=1;
        delay_init(); //延时函数初始化
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置 NVIC 中断分组 2
        uart_init(115200); //串口初始化波特率为 115200
        LED_Init(); //LED 端口初始化
        TIM3_PWM_Init(899,0); //不分频,PWM 频率=72000/900=80Khz
        while(1)
        {
    	    delay_ms(10);
    	    if(dir)led0pwmval++;
    	    else led0pwmval--;
    	    if(led0pwmval>300)dir=0;
    	    if(led0pwmval==0)dir=1;
    	    TIM_SetCompare2(TIM3,led0pwmval);
        }
    }
    //实验现象:我们将看 DS0 不停的由暗变到亮,然后又从亮变到暗。每个过程持续时间大概为 3 秒钟左右。
    

    皮一下,欢迎交流啊! 共同学习,共同进步。
    在这里插入图片描述

    展开全文
  • 在本科学习中,学生所做的小车多数为使用lm298n或者tb6612来驱动简单的直流电机,我们需要单片机输出pwm波来控制直流电机转速。 直流电机的PWM调速原理为:通过调节驱动电压脉冲宽度的方式,并与电路中一些相应的...

    目录

    【pwm是如何控制电机转速】

    【89C51系列单片机产生pwm波】

    【STC12C5A60S2系列单片机输出PWM】


    【pwm是如何控制电机转速】

    在本科学习中,学生所做的小车多数为使用lm298n或者tb6612来驱动简单的直流电机,我们需要单片机输出pwm波来控制直流电机转速。

    直流电机的PWM调速原理为:通过调节驱动电压脉冲宽度的方式,并与电路中一些相应的储能元件配合,改变了输送到电枢电压的幅值,从而达到改变直流电机转速的目的。

    【89C51系列单片机产生pwm波】

    89c51单片机没有自带pwm发生器,如果想要使用传统的51单片机产生pwm,只能通过软件模拟的方法来产生pwm。

    软件模拟可以分为软件延时和定时器两种方法。

    1、软件延时输出pwm

    使用延时函数产生频率为1kHz的pwm方波(@12MHz晶振)

    #include <reg52.h>
    
    sbit pwm = P1^0;
    
    void delay100us(unsigned int x)
    {
    	unsigned char i;
    	while(--x)
    	{
    		i = 20;
    		while (--i);
    	}
    }
    
    int main(void)
    {
    	while(1)
    	{
    		pwm = 1;
    		delay100us(6);
    		pwm = 0;
    		delay100us(4);
    	}
    }

    proteus仿真结果

    使用简单的延时函数即可简单地模拟出pwm波。但是这种方法缺点很明显,就是在输出pwm时占用大量机器周期,此时若进行其他操作时会影响pwm的准确度。所以这种方法我们很少使用。

    2、定时器产生pwm

    使用定时器的溢出中断,在中断服务程序中改变IO口的电平高低,可以在多操作情况下输出比较准确的pwm波形。

    比如我们使用定时器0。

    定时器工作模式:我们设置定时器0工作模式为方式1,16位自动重载模式,这样可以获得较宽的调频范围。

    定时器中断:16位自动重载模式下最多可以记65536个数,一旦超出这个数值,便会进入中断。定时器初值可以使用定时器计算器计算,方便快捷。

    使用定时器0产生占空比可调,频率为100Hz的pwm波。

    #include <reg52.h>
    
    sbit pwm = P1^0;
    
    unsigned int PWM = 50;	//pwm占空比为50%,可调占空比
    unsigned char time = 0;
    
    void Time0Init(void)
    {
    	TMOD = 0X01;	//定时器工作在方式1(16位定时器)
    	TH0 = 0XFF;		//12M晶振下定时0.01ms
    	TL0 = 0X9c;
    	ET0 = 1;			//开定时器1中断
    	EA = 1;
    	TR0 = 1;			//开启定时器
    }
    
    void Timer0(void) interrupt 1
    {
    	TH0 = 0XFF;		//重装初值
    	TL0 = 0X9c;
    	time++;
    }
    
    void main(void)
    {
    	Time0Init();
    	while(1)
    	{
    		if(time >= 100)	//PWM周期为100*0.1ms
    			time = 0;
    		if(time < PWM)		
    			pwm = 1;
    		else if(time >= PWM)
    			pwm = 0;
    	}
    }

    proteus仿真结果

    由仿真结果来看,所得波形还是不算很精准,实际应用过程中还会有很多误差,但是这样已经比延时函数产生pwm的结果可靠的多。

    【STC12C5A60S2系列单片机输出PWM】

    我在做循迹小车时使用的是stc12c5a60s2单片机。stc12c5a60s2单片机集成了两路可编程计数器阵列(PCA)模块,可用于软件定时器、外部脉冲的捕捉、高速输出以及脉宽调制(PWM)输出。

    使用stc12c5a60s2单片机的PCA模块可通过程序设定,使其工作于8位PWM模式,通过P13和P14输出。

    如下图所示:

    PWM输出频率取决于PCA定时器的时钟源。

     由于所有模块共用仅有的PCA定时器,所以它们的输出频率相同。各个模块的输出占空比是独立变化的,与使用的捕获寄存器[EPCnL, CCAPnL]有关。当寄存器CL的值小于[EPCnL,CCAPnL]时,输出为低;当寄存器CL的值等于或大于[EPCnL, CCAPnL]时,输出为高。当CL的值由FF变为00溢出时,[EPCnH, CCAPnH]的内容装载到[EPCnL, CCAPnL]中。这样就可实现无干扰地更新PWM。要使能PWM模式,模块CCAPMn寄存器的PWMn和ECOMn位必须置位。

     PCA时钟输入源频率由于PWM是8位的,所以

    PWM频率 = PCA时钟输入源频率 / 256

    PCA时钟输入源可以从以下8种中选择一种: SYSclk,   SYSclk/2,  SYSclk/4,SYSclk/6,SYSclk/8,SYSclk/12, 定时器0的溢出,ECI/P3.4输入。

    当某个I/O口作为PWM使用时,该口状态:

    PWM之前口的状态 PWM输出时口的状态
    弱上拉/准双向 强推挽输出/强上拉输出,要加输出限流电阻1K-10K
    强推挽输出/强上拉输出 强推挽输出/强上拉输出,要加输出限流电阻1K-10K
    仅为输入/高阻输入 PWM无效
    开漏 开漏

    ------

    #include "stc12c5a.h"
    
    void PCA_Init(void)
    {
    	CCON = 0;				//PCA初始化
    	CMOD = 0x00;			//空闲时不计数,不产生中断,时钟源为Sysclk/12,PWM频率大约为4KHz
    	CL = 0x00;				//PCA低8位清零
    	CH = 0x00;				//PCA高8位清零
    
    	CCAPM0 = 0x42;			//8位PWM模式,无中断
    	CCAP0H = 0xc0;			//PWM0占空比(调节此处值调节PWM占空比)
    	CCAP0L = 0xc0;			//PWM0占空比(调节此处值调节PWM占空比)
    
    	CCAPM1 = 0x42;			//8位PWM模式,无中断
    	CCAP1H = 0x40;			//PWM1占空比(调节此处值调节PWM占空比)
    	CCAP1L = 0x40;			//PWM1占空比(调节此处值调节PWM占空比)
    
    	CR = 1;					//启动PCA计数器
    }
    
    /*PWM占空比设置*/
    void PWM_Set(unsigned char x,unsigned char y)
    {
      CCAP0H = y;				//设置比较值
      CCAP0L = y;	
      CCAP1H = x;				//设置比较值
      CCAP1L = x;
    }
    
    void main(void)
    {
      P1M0 = 0xff;				//P1口推挽输出
      P1M1 = 0x00;
      PCA_Init();				//PCA初始化
      
      PWM_Set(0x80,0x80);       //设置占空比
    
      while(1);            
    }

    此时产生的就是占空比为50%的PWM波。使用示波器可以在P13和P14口测得PWM输出波形。
     

     

     

     


     

     

    展开全文
  • 51单片机模拟PWM

    2013-06-11 11:40:20
    51单片机模拟PWM 吴水林的学习笔记 怎样用单片机模拟PWM 版本:v2 在讲解PWM 之前,让我们来了解几个和PWM 相关的词汇。 1. 频率: 频率f 是周期T 的倒数,即f =1/T。而像中国使用的电是一种正弦交流电...

    51单片机模拟PWM

    吴水林的学习笔记
    怎样用单片机模拟PWM
    版本:v2
    在讲解PWM 之前,让我们来了解几个和PWM 相关的词汇。
    1. 频率:
    频率是周期的倒数,即f =1T。而像中国使用的电是一种正弦交流电,其频
    率是50Hz,也就是它一秒钟内做了50 次周期性变化。
    2. 周期(period)
    事物在运动、变化的发展过程中,某些特征多次重复出现,其接续两次出现所经过的时
    间。通常用表示。频率(f)的倒数。即T = 1 / f.物体完成一个完整的振动所需要的
    时间,以T0 表示。单位一般是用来表示,也常用毫秒(ms)或微秒(us)做
    单位。1s=1000ms1s=1000000us。例如一个单摆,它的周期就是重锤从左运动到
    右,再从右运动回左边起点所需要的时间。
    3. 占空比(Duty Cycle):
    在一串理想的脉冲序列中(如方波),正脉冲的持续时间与脉冲总周期的比值。
    例如:脉冲宽度1μs,信号周期4μ的脉冲序列占空比为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%占空比的时标,计算如下:
    在 51 单片机中。我们可以作如下处理:
    /*------------------------------------------------------------------------------------------------*-
    函数名称: Pwm_init ()
    函数功能设定1%占空比时标。
    说 明:
    *
    当前版本: 1.0 * 取代版本:
    作 者吴水林 原作者 :
    完成日期: 2009-05-31 * 完成日期:
    -*------------------------------------------------------------------------------------------------*/
    void Pwm_init(void)
    { // 22.1184MHz
    TMOD = 0x20; // 定时器模式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)
    { // 高电平从...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%上,下图是软件的仿真结果:

    展开全文
  • STC单片机(具有PCA功能的),怎么实现可变频率的PWM输出?很多朋友还在使用定时器做可变频PWM, 这里我就介绍怎么使用硬件PWM,在定时器0的分频基数下设计PWM。 首先看CMOD这个寄存器,这里我们主要关注 CPS0,...
  • 单片机测量PWM占空比的三种方法 PWM(Pulse Width Modulation),一般指脉冲宽度调节,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中,...
  • PIC单片机PWM PWM原理

    2015-04-29 22:13:48
    比如 单片机 40ms的时间 输出高电平然后60ms的时间 输出低电平接着一直不断周期性的交替输出高低电平 这就是典型的PWM波。高电平输出的时间40ms就是传说中的脉宽,40ms+60ms=100ms 便是PWM的周期。假定我们把...
  • 基于51单片机模拟PWM

    2020-07-28 23:32:30
    脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。本程序基于51单片机所涉及的模拟PWM的脉宽输出。
  • 舵机、使用51单片机的定时器中断实现PWM
  • 利用STM32单片机输出一路PWM波,并且可调频率和占空比。频率范围在5-10KHZ,占空比在10-90%之间可调。
  • PIC单片机PWM

    2014-03-20 15:57:05
    比如 单片机 40ms的时间 输出高电平然后60ms的时间 输出低电平接着一直不断周期性的交替输出高低电平 这就是典型的PWM波。高电平输出的时间40ms就是传说中的脉宽,40ms+60ms=100ms 便是PWM的周期。假
  • 51单片机PWM输出

    2019-01-06 13:42:55
    学期快结束了,51单片机的学习也差不多告一段落,也快要转入新的学习阶段,寒假找个时间看看32,小白哈哈哈,下面是我学习51定时器弄出来的小东西,一个PWM的输出。还请大神指点。 刚开始觉得PWM输出应该不难,很...
  • 51单片机pwm调光程序

    2020-07-30 23:32:00
    51单片机实现pwm调光程序,通过pwm调节led等的亮度,程序简单易懂
  • 单片机PCA和PWM的关系

    2019-12-21 14:36:06
    使用单片机的PCA模块可以实现PWM功能,比如要输出一个固定的频率,那么单片机只要开机时,把PCA的相关寄存器配置一下,频率就出来了,就是后台运行了,单片机就可以去做其他的事情,想连续发脉冲时,不中断其他运行...
  • 单片机 PWM 占空比计算D=(256-CCAPnH)/ 256(8位PWM模式)
  • 最近应实验室需求写一篇51单片机产生PWM的文章供参考.  单片机芯片STC89C52,晶振12MHz,编译环境Keil5.  分析:若使单片机端口为高电平, 则单片机输出电压为恒值5V. 反之低电平输出电压为0V. 但是我们如果在周期为...
  • 15单片机生成PWM

    2019-07-28 17:20:13
    void PWM_Config(void) { P2M0 &= //配置 P2M1 &= P0 &= //设置P2.1 P2.2电平 PWMCKS = PWMC = CYCLE; PWM3T1 = PWM3T2 = PWM3CR = PWM4T1 = PWM4T2 = PWM4CR = PW...
1 2 3 4 5 ... 20
收藏数 7,706
精华内容 3,082
关键字:

单片机如何使用pwm