分享两种STC15定时器模拟PWM的方法

发布者:太白山人最新更新时间:2020-02-29 来源: 51hei关键字:STC15  定时器  模拟PWM 手机看文章 扫描二维码
随时随地手机看文章

刚刚搜了一下,发现坛里还没有这样分析PWM的帖子,然后发了一个。
手电LED控制或马达转速控制都离不开PWM,下面有两种方法可以模拟PWM的。如果不正确希望各位指教。
 

 
//用定时器装载方式模拟PWM,这种方法PWM周期短,分辩率高,1毫秒内可以做到11000格分辩率,
//缺点:高低电平会的百分之一格不受控制
#include "reg51.h"
#include
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr AUXR      = 0x8e;//辅助寄存器
sbit P20   = P2^0; //PWM输出脚   
sbit P17   = P1^7; //按键增量
sbit P16   = P1^6; //按键减少   
unsigned int HIGHDUTY,LOWDUTY;//高低时间存放寄存器
unsigned char num;//记录分辩个数
bit flag;
void Delayms(unsigned int ms)//1mS@11.0592MHz
{unsigned char i, j;
        while(ms--)
        {        _nop_();
        _nop_();
        _nop_();
                i = 11;
        j = 190;
        do
        {
                while (--j);
        } while (--i);}
}
void main()
{  
        P0M0 = 0x00;
        P0M1 = 0x00;
        P1M0 = 0x00;
        P1M1 = 0x00;
        P2M0 = 0x00;
        P2M1 = 0x00;
        P3M0 = 0x00;
        P3M1 = 0x00;
        AUXR = 0x80;        //定时器0为1T模式
        TMOD &= 0xf0;       //设置定时器0为模式0(16位自动重装载)
        TR0 = 1;            //定时器0开始计时
        ET0 = 1;            //使能定时器0中断
        EA = 1;
        HIGHDUTY=54477+(11058/255)*num;
        LOWDUTY=54477+(11058/255)*(256-num);
    while (1)
        {
       if(!P17)
        {
        Delayms(90);          
         if(!P17)
        {
        //while(!P17);
        num++;             //按制分辩率,uchar字符型范围0~255格
        HIGHDUTY=54477+(11058/255)*num;/*求占空比高位,0xD4CD = 54477;
        程序装载初始值54477一直跑到65535共花时间1000微秒,
        65535-54477=11058,11058就是1000微秒。
        (11058再除以分辩率255)等于一格所需的时间,要点空比高位多少就剩多少 */
        LOWDUTY=54477+(11058/255)*(255-num);//求占空比高位低位
         }
       }
         if(!P16)
        {
        Delayms(90);          
         if(!P16)
        {
        //while(!P16);
        num--;                        
        HIGHDUTY=54477+(11058/255)*num;
        LOWDUTY=54477+(11058/255)*(255-num);//
         }
       }
    }
}
void tm0() interrupt 1//定时器0中断服务程序
{
   flag = !flag; 
    if (flag)//反转标志去执行高低电平的时间   
    {
        TL0 = HIGHDUTY;                //设置定时初值
        TH0 = HIGHDUTY>>8;//设置定时初值
        P20=1;//输出高电位
    }
    else
    {
        TL0 = LOWDUTY;                //设置定时初值
        TH0 = LOWDUTY>>8;        //设置定时初值
        P20=0;//输出低电位
    }
}

---------------------------------------------------------------------------------------------------------------------------
 

//用定时器计算方式模拟PWM,高低电平容易控制
//缺点:这种方法周期能做到1KHz以内,大多数马达或调光设置会闪烁
#include "reg51.h"
#include
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;
sfr AUXR      = 0x8e;//辅助寄存器
sbit P20   = P2^0; //PWM输出脚   
sbit P17   = P1^7; //按键增量
sbit P16   = P1^6; //按键减少   
unsigned char num;//记录分辩个数
void Delayms(unsigned int ms)                //1mS@11.0592MHz
{unsigned char i, j;
        while(ms--)
        {        _nop_();
        _nop_();
        _nop_();
                i = 11;
        j = 190;
        do
        {
                while (--j);
        } while (--i);}
}
void main()
{   P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    AUXR = 0x80;            //定时器0为1T模式
    TMOD &= 0xf0;           //设置定时器0为模式0(16位自动重装载)
    TR0 = 1;                //定时器0开始计时
    ET0 = 1;                //使能定时器0中断
    EA = 1;
    num=10;  //给初始值
    while (1)
        {
       if(!P17)
        {
        Delayms(10);          
         if(!P17)
        {        
                num++;
         }
       }
        if(!P16)
         {
        Delayms(10);          
         if(!P16)
        {
                num--;
         }
       }
    }
}
void tm0() interrupt 1//定时器0中断服务程序
{ static unsigned char k;
        TL0 = 0xF5;        //设置定时初值 按1T时钟计算,1uS一次
        TH0 = 0xFF;        //设置定时初值 按1T时钟计算,1uS一次
        k++;
        if(k>num)P20=1;//输出高电位
        else P20=0;//输出低电位
}

关键字:STC15  定时器  模拟PWM 引用地址:分享两种STC15定时器模拟PWM的方法

上一篇:51单片机(STC15W408AS)映射printf函数 串口收发实现
下一篇:基于51单片机的PID控制的DC/DC电路仿真+程序设计

推荐阅读最新更新时间:2024-11-19 21:14

定时器PWM脉冲
简介 STM32 的定时器除了 TIM6 和 TIM7。其他的定时器都可以用来产生 PWM 输出。 高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。 通用定时器也能同时产生多达 4路的 PWM 输出, PWM 寄存器与功能原理 TIMx_CCR1~4,捕获/比较寄存器 该寄存器的值与 CNT 的值比较,可以控制 PWM 的输出脉宽 TIMx_CCMR1/2,捕获 / 比较模式寄存器 CCMR1/2:OCxM 位,用于设置 PWM模式1 ,只要TIMx_CNT CCR(计数值小于比较标准值)则为有效电平 PWM模式2 ,只要TIMx_CNT CCR(计数值小于比较标准
[单片机]
stm32库函数学习篇----通用定时器PWM功能)
上午花了半天时间熟悉了stm32的PWM模块。中午利用午饭时间把PWM功能调试成功。当然,很简单的东西,也许很多前辈估计都不屑一顾的东西。 今天最大的感叹就是网络资源实在是个巨大的宝库,真的很庆幸,在这个复杂的社会环境里,在一个到处充斥着私心、私利的时代,各个网站,各个论坛上的众多网友都时刻保持着开源的氛围。学习一定要和他人交流,而网络提供了这么一个极好的平台。 废话少说,言归正传。 实现功能:采用定时器2的通道2,使PA1输出频率1K,占空比40的PWM波形,用PA8随意延时取反led灯,指示程序运行。 首先熟悉一下定时器的PWM相关部分。看图最明白 其实PWM就是定时器的一个比较功能而已。 CNT里的值不断++
[单片机]
stm32库函数学习篇----通用<font color='red'>定时器</font>(<font color='red'>PWM</font>功能)
labview中的的几种定时器
LABVIEW提供了几种定时器(包括DELAY),如下图所示 首先看看Tick Count 节点的帮助说明: 返回毫秒定时器的值. 基准参考时间(0 毫秒)未定义,也就是说,不能把返回的毫秒数直接转换成现实世界的时间和日期.必须注意当你使用这个函数进行比较的时候,毫秒定时器达到2^32-1后反转成0. 基准参考时间未定义,说法比较模糊,难道会是个随机数,那显然不可能,如果是随机数,那两次调用 TI CK COUNT取得差值就不可能表示经过的毫秒数.无论如何,必须有个时间的起点. API函数中也有一个类似的函数:GetTickCount,该函数返回计算机启动以来经过的毫秒数.在9X中,它读取的是BIOS中保存的系统时钟
[测试测量]
labview中的的几种<font color='red'>定时器</font>
51单片机定时器/计数器的结构和原理
  定时器/计数器简称定时器,其作用主要包括产生各种时标间隔、记录外部事件的数量等,是微机中最常用、最基本的部件之一。803l单片机有2个16位的定时器/计数器:定时器0(T0)和定时器1(T1)。   T0由2个定时寄存器TH0和TL0构成,T1则由TH1和TL1构成,它们都分别映射在特殊功能寄存器中,从而可以通过对特殊功能寄存器中这些寄存器的读写来实现对这两个定时器的操作。作定时器时,每一个机器周期定时寄存器自动加l,所以定时器也可看作是计量机器周期的计数器。由于每个机器周期为12个时钟振荡周期,所以定时的分辨率是时钟振荡频率的1/12。作计数器时,只要在单片机外部引脚T0(或T1)有从1到0电平的负跳变,计数器就自动加1。计
[单片机]
51单片机<font color='red'>定时器</font>/计数器的结构和原理
MSP430定时器中断程序
#include msp430g2452.h int main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; P1DIR |= BIT0; //P1.0设定为输出 P1OUT |= BIT0; //P1.0拉高 TACCTL0 = CCIE; //CCR0中断使能 TACCR0 = 50000; //终点值 //使用连续计数模式的话,此值不会有影响 TACTL = TASSEL_2 + MC_2;//控制定时器A 选择timer时钟ACLK和连续计数模式 _EINT
[单片机]
STM32 定时器周期动态修改
最近手头项目上有个需要模拟串口的地方,而模拟串口部分有这样的一个需求:当Strat信号来的时候启动定时器TIM3,到52us后采样Start信号是否是低电平,然后希望将定时器的周期改成104us,采样剩余的9个bit。 解决思路: ① 外部中断触发时候启动TIM3(同时关闭外部中断使能),等52us后在TIM3中断里判断Rx的状态; ② 如果是低电平就改变定时器TIM3的周期为104us; ③ 如果是高电平就不要接收了并恢复外部中断使能; ④ 在后续的9次中断里依次接收bit0...bit7还有STOP位; ⑤ 当接收到STOP位的时候就可以关闭TIM3了,然后再恢复外部中断使能; 知识难点: TI
[单片机]
STM32 <font color='red'>定时器</font>周期动态修改
STM32高级定时器之时钟源
1、定时器时钟源框图 从图片中可以看到定时器有4个时钟源, (1)内部时钟 ;(2) 外部时钟模式1,定时器的通道1、2 ; (3) 外部时钟模式模式2 ,ETR脚 ; (4)内部触发输入 下面分别介绍这几种时钟源的详细配置 2、内部时钟 寄存器SMCR的SMS选择000 3、外部时钟模式1 中文手册已经有以通道2为例子详细说明,这里我以通道1来说明,算是对它的温故和补充 3.1 滤波器设置,我的理解这里的滤波,比如我这里配置为0001,不是说通道来了N=2个脉冲才算这个输入有效,而是脉冲到来后,延时N/Fsampling的时间,还是高电平,就认为这个脉冲有效 类似按键检测的延时去抖动,如果理解
[单片机]
STM32高级<font color='red'>定时器</font>之时钟源
定时器1之使用定时器的查询方式来反转LED
话不多说,先说目的:使用定时器的查询方式来反转LED。然后上代码: ORG 0000H MOV TMOD,#00H MOV TH1,#0ECH MOV TL1,#78H SETB TR1 WhatchTf1: JBC TF1,T1Overflow SJMP WhatchTf1 T1Overflow: CPL P1.0 SJMP WhatchTf1 END 接着是分析程序: ORG 0000H MOV TMOD,#00H ; TMOD 即timer mode,定时器工作方式控制寄存器,设置他的工作方式16位自动重装,算了,这个还是不说那么具体了,感觉这种东西去查书或者数据手册都能查到。这里说说我的看法:单片机,就是对相应的寄存器放入
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved