历史上的今天
今天是:2025年07月13日(星期日)
2020年07月13日 | 51单片机入门经验分享9-定时器模拟实现PWM呼吸灯效果
2020-07-13 来源:51hei
众所周知,PWM的应用是及其广泛的,现在很多高速的单片机内部都集成了硬件PWM,使用起来也很简单,配置好频率和装入计数值就可以工作了,但是在一些低成本的场合,我们选择的单片机没有硬件PWM功能模块,但是我们还存在这个需求怎么办呢?这个时候,我们需要用PWM来模拟实现他,但实现PWM必须要了解PWM的原理,这里我们先了解下。
PWM全称是脉冲宽度调制解调,比如1个小灯,按照500MS亮一次,500MS灭一次,周期是1S,频率是1HZ,在这里,1个周期说明白了就是2个方波,有高电平和低电平组成,在周期固定的情况下,我们通过不断的调整高电平所占的整个周期比例,即所谓的占空比,就可以实现小灯”不是那么亮“的效果,如果连续起来,就可以实现呼吸灯的效果了,先来用定时器0实现小灯500MS闪烁的效果,通过DEBUG来看下波形。我们把下面的代码拷贝进去,看下现象
单片机源码:
/********************************************************
*描述:工程模板,点亮led 500MS闪烁 12MHZ
********************************************************/
#include "stc15w.h"
/*******************************************************************************
* 文件名:位定义
* 描 述:
* 功 能:
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
bit flag500ms = 0;//500ms标志位
sbit LED0 = P1^0;//
sbit DATA0 = P2^0;//
/*******************************************************************************
* 文件名:数据类型定义
* 描 述:
* 功 能:
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
/*******************************************************************************
* 文件名:函数前置声明
* 描 述:
* 功 能:
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
void Bsp_Power_Init(void);
void Timer0Init(void);
/*******************************************************************************
* 文件名:主循环入口
* 描 述:
* 功 能:
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
void main(void)
{
Bsp_Power_Init();//LED端口初始化
Timer0Init();
LED0 = 1;
while(1)
{
if(flag500ms)
{
flag500ms = 0;
DATA0 = ~DATA0;//
}
}
}
/*******************************************************************************
* 文件名:void Bsp_Power_Init()
* 描 述: 数码管上电显示
* 功 能:编程模块化
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
void Bsp_Power_Init(void)
{
P0M1 = 0xFC;
P0M0 = 0X03;
P0 = 0X00;
P1M1 = 0xE0;
P1M0 = 0X1F;
P1 = 0X00;
//P2口开漏输出
P2M1 = 0XFF;
P2M0 = 0XFF;
P2 = 0Xff;
// //P54,P55口为推挽输出
P5M1 = 0X00;
P5M0 = 0X00;
P5 = 0xFF;
//P37,P36,3.2,P3.3 P3.4口为推挽输出
P3M1 = 0X00;
P3M0 = 0XFC;
P3 = 0X23;
}
/*******************************************************************************
* 文件名:void Bsp_Power_Init()
* 描 述: 数码管上电显示
* 功 能:编程模块化
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
void Timer0Init(void) //1毫秒@12MHZ
{
AUXR &= 0x7f; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = (65535 - 1000) % 256; //设置定时初值
TH0 = (65535 - 1000) / 256; //设置定时初值
ET0 = 1;
TR0 = 1; //定时器0开始计时
EA = 1;
}
/*******************************************************************************
* 文件名:void TIME0_INTER(void) interrupt 1
* 描 述:
* 功 能:
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
void TIME0_INTER(void) interrupt 1
{
static uint16 tmr500ms = 0;
TL0 = (65535 - 1000) % 256; //设置定时初值1ms
TH0 = (65535 - 1000) / 256; //设置定时初值
tmr500ms++;
if(tmr500ms >= 500)
{
tmr500ms = 0;
flag500ms = 1;
}
}

从DEBUG可以看到,是500MS变化一次,说明我们的设置是对的,但是在这里还是说明一点,我们用的而是STC15W系列的芯片,但是定时器我配置成了12T模式,和STC89C52是一样使用的。既然我们实现了这个500MS高电平,500MS低电平的效果,我们再来实现下200MS亮,800MS灭的效果吧,程序代码如下:
/********************************************************
*描述:工程模板,点亮led 500MS闪烁 12MHZ
********************************************************/
#include "stc15w.h"
/*******************************************************************************
* 文件名:位定义
* 描 述:
* 功 能:
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
sbit LED0 = P1^0;//
sbit DATA0 = P2^0;//
/*******************************************************************************
* 文件名:数据类型定义
* 描 述:
* 功 能:
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
/*******************************************************************************
* 文件名:函数前置声明
* 描 述:
* 功 能:
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
void Bsp_Power_Init(void);
void Timer0Init(void);
/*******************************************************************************
* 文件名:主循环入口
* 描 述:
* 功 能:
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
void main(void)
{
Bsp_Power_Init();//LED端口初始化
Timer0Init();
LED0 = 1;
while(1);
}
/*******************************************************************************
* 文件名:void Bsp_Power_Init()
* 描 述: 数码管上电显示
* 功 能:编程模块化
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
void Bsp_Power_Init(void)
{
P0M1 = 0xFC;
P0M0 = 0X03;
P0 = 0X00;
P1M1 = 0xE0;
P1M0 = 0X1F;
P1 = 0X00;
//P2口开漏输出
P2M1 = 0XFF;
P2M0 = 0XFF;
P2 = 0Xff;
// //P54,P55口为推挽输出
P5M1 = 0X00;
P5M0 = 0X00;
P5 = 0xFF;
//P37,P36,3.2,P3.3 P3.4口为推挽输出
P3M1 = 0X00;
P3M0 = 0XFC;
P3 = 0X23;
}
/*******************************************************************************
* 文件名:void Bsp_Power_Init()
* 描 述: 数码管上电显示
* 功 能:编程模块化
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
void Timer0Init(void) //1毫秒@12MHZ
{
AUXR &= 0x7f; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = (65535 - 1000) % 256; //设置定时初值
TH0 = (65535 - 1000) / 256; //设置定时初值
ET0 = 1;
TR0 = 1; //定时器0开始计时
EA = 1;
}
/*******************************************************************************
* 文件名:void TIME0_INTER(void) interrupt 1
* 描 述:
* 功 能:
* 作 者:大核桃
* 版本号:1.0.1(2017.05.23)
*******************************************************************************/
void TIME0_INTER(void) interrupt 1
{
static uint16 tmr200ms = 0;
static bit a = 0;//翻转状态变量
if(a)
{
TL0 = (65535 - 1000) % 256; //设置定时初值1ms
史海拾趣
|
:ICT4040XP电路板故障检测仪 电路板故障检测仪◆先进的测试技术,强大的驱动能力,任何故障原因的电路板皆可修好◆友好简单的中文操作界面,不经专业训练,任何人均可成为维修专家◆无需电路原理图,不必知道器件型号,对任何电路板皆可快 ...… 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 03:55 编辑 各位大虾:你们好! 再下最近在做一个基于单片机的语音播报时钟,但是在语音器件分段地址的获取遇到了问题!主要功能是通过按键播报当前系统时间,我选用的语音芯片是ISD2560,用的AT89S5 ...… 查看全部问答> |
|
在虚拟机上 能够正常实现连接服务器 取得文件;现在,在设备上,则提示“无法连接服务器”; 代码: CInternetSession IS; CFile * pFile; CString sURL; sURL = (char *)strDataURL; sURL.MakeUpper(); pFile=IS.OpenURL(sURL, ...… 查看全部问答> |
|
在EVC中写一应用程序. 书写如下: printf(TEXT(\"创建表失败,错误码:%d,错误原因:%s\\n\"), result, zErrMsg ); 在VC中这样编译OK. 但EVC编译出错. 请问怎么才能保证输出不是乱码的书写语法? … 查看全部问答> |
|
概伦电子2012招聘职位 公司简介 概伦电子科技有限公司(ProPlus Electronics Co., Ltd.)致力于提升先进半导体工艺下集成电路设计的竞争力,提供创新的电子设计自动化(EDA)解决方案,其产品发展方向包括针对于十 ...… 查看全部问答> |




