草庐IT

蓝桥杯单片机比赛学习:8、PWM的基本原理之呼吸灯

Do My Best 2023-05-12 原文

经过7节的学习,我们已经掌握了基本的硬件的使用规则,从本节开始我们开始学习一些模块的使用PWM、PCF8591、AT24C02、DS18B20、DS1302、555频率测量、光敏电阻测量、超声波测距等。本节先将PWM的基本原理,本节通过调节呼吸灯进一步理解PWM。如果之前的led、按键、数码管、中断等有不懂的请去我的主页看一下之前的文章,或许可以帮助你。(1条消息) Do My Best的博客_CSDN博客-蓝桥杯单片机比赛学习领域博主

pwm的概念 

PWM脉冲宽度调制,就是英文 “Pulse Width Modulation” 的缩写,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。

pwm的频率(Hz)

就是1s中有几个脉冲(周期),如有50个脉冲(周期)pwm的频率就是50Hz。

什么是脉冲?

脉冲就是从低电平到高电平再回到高电平,这样就是1个脉冲信号。

例:如下图,如果1s中产生3个脉冲(也就是3个周期),那么此pwm的频率就为3Hz。

 

PWM的周期 (S)

pwm的周期(T = 1 / f),也就是频率的倒数。

例:pwm频率(f)为50Hz,周期(T)就为20ms

1s中有50个周期(脉冲),每个周期为20ms

 

PWM的占空比

pwm的占空比就是 在一个周期内,高电平时间占整个周期时间的比例。

 例:一个pwm的周期为20ms,高电平的时间为15ms,则此pwm的占空比为15/20 = 75%

 

PWM的基本原理 

在我们使用单片机的时候一般都会使用到PWM进行小车调速、灯光亮度调节等,一般的,都是通过IO口输出高低电平调节占空比。例如,假设单片机输出的高电平为5V,低电平为0V,我们要想得到0~5V之间的任意电压就要使用PWM,通过改变IO口的占空比从而实现DA转化(数字量转化为模拟量)

我们知道,单片机可以输出5V和0V的电压,那么怎么输出0~5V之间的任意电压呢?我们现在就得使用pwm改变占空比 进而 输出0~5V之间的任意电压。

例:如下图,占空比依次为50% 25% 75%,他们的输出电压为:

占空比为50%:Vout = 5V*50%=2.5V

占空比为25%:Vout = 5V*25%=1.25V

占空比为75%:Vout = 5V*75%=3.75V

综上,PWM的 这种原理就是通过DA转换来实现的,最重要的是我们要知道输出电压是通过改变占空比来实现的。

PWM调节呼吸灯

在这里我们需要知道这样的小知识,LED灯的亮度是由电压来决定的,给的电压大LED亮度强,给的电压小LED亮度弱

从百度上我们可以搜到,人眼对于83Hz的频率以上的刷新率基本不感到闪烁?

 用定时器模拟pwm,具体参数如何设置?如下图,请认真看,重点!重点!!重点!!!

 步骤:

1、我们用定时器模拟一个pwm周期,我们选择频率为200Hz,周期为5ms(T=1/200s)的周期信号,每隔50us进一次中断,程序如下

void Timer0Init(void)		//50微秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCE;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时

	EA=1;
	ET0=1;
}

//每50us进入一次中断,flag++,当flag=100时,就相当于过了5ms
//也就是相当于我们这里设置了一个pwm周期为5ms,频率为200Hz(f = 1/T)
void Timer0Service(void)  interrupt 1
{
	flag++;								
	if(flag==100)
		flag=0;
}

 

2、并通过以下程序来设置脉冲宽度(也就是高电平的时间)

void key_scan(void)
{  
  if(s4==0)
  {
    delay_ms(10);
    if(s4==0)
    {
			set_flag+=10;        //通过按键设置脉宽时间,每按一次脉宽时间增大,周期不变,输出电压高,LED变亮
			if(set_flag>100)    //周期为5ms(我们自行设计分为100份),占空比不能超过100
					set_flag=0;
			
			while(s4==0)
			{
				led_pwm();
			}
    } 
  } 
}

3、通过步骤2设置的脉冲时间,进而算出占空比,占空比实现的程序如下

void led_pwm(void)
{
	if(flag<=set_flag)    //set_flag为脉冲宽度(高电平时间)
		led_stat=0x00;
	else
		led_stat=0xff;
		
	
	slect_138_573(4,led_stat);
}

 通过以上步骤既可以实现pwm控制呼吸灯,完整代码如下:

#include "stc15f2k60s2.h"
#include "intrins.h"

unsigned char flag=0,set_flag=0,led_stat=0xff;

//***********独立按键****************
sbit s7 = P3^0;
sbit s6 = P3^1;
sbit s5 = P3^2;
sbit s4 = P3^3;
//***********************************

void Delay1ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
}

void delay_ms(int x)
{
	while(x--)
	{
		Delay1ms();
	}
}


/* 选择通道并且输入数据 */
void slect_138_573(unsigned char channel, unsigned char dat)
{
	P0 = 0x00;
	P0 = dat;										/* 这里用P0而不用其他端口是因为我们操作LED、数码管、继电器、蜂鸣器都是对P0进行操作 */
	switch(channel)							/* 选择通道 */
	{
		case 4:										/* 使Y4输出低电平0,也就是操作LED */
			P2 = (P2 & 0x1f) | 0x80;/* (P2 & 0x1f)就是将前3位清0,再操作前3位。将0x80转为2进制1000 0000,这里只看前3位100就是Y4 */
		break;
		case 5:										/* 使Y5输出低电平0,也就是操作继电器和蜂鸣器 */
			P2 = (P2 & 0x1f) | 0xa0;
		break;
		case 6:										/* 使Y6输出低电平0,也就是操作8个数码管 */
			P2 = (P2 & 0x1f) | 0xc0;
		break;
		case 7:										/* 使Y7输出低电平0,也就是操作8个数码管中的1个数码管显示值 */
			P2 = (P2 & 0x1f) | 0xe0;
		break;
		case 0:										/* 关闭所有通道 */
			P2 = (P2 & 0x1f) | 0x00;
		break;
	}
	P2 = (P2 & 0x1f) | 0x00;		/* 使用后,关闭所有通道 */
	
}

void led_pwm(void)
{
	if(flag<=set_flag)
		led_stat=0x00;
	else
		led_stat=0xff;
		
	
	slect_138_573(4,led_stat);
}

void key_scan(void)
{  
  if(s4==0)
  {
    delay_ms(10);
    if(s4==0)
    {
			set_flag+=10;
			if(set_flag>100)
					set_flag=0;
			
			while(s4==0)
			{
				led_pwm();
			}
    } 
  } 
}



void Timer0Init(void)		//50微秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCE;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时

	EA=1;
	ET0=1;
}

//每50us进入一次中断,flag++,当flag=100时,就相当于过了5ms
//也就是相当于我们这里设置了一个pwm周期为5ms,频率为200Hz(f = 1/T)
void Timer0Service(void)  interrupt 1
{
	flag++;								
	if(flag==100)
		flag=0;
}


void System_init(void)
{
	slect_138_573(4,0xff);
	slect_138_573(5,0x00);
	Timer0Init();
}

void main(void)
{
	System_init();
	while(1)
	{
		key_scan();
		led_pwm();
	}
}

 总结:LED灯的亮度就是通过调节占空比来实现,通过调节占空比调节输出电压,进而调节LED灯的亮度。

 

有关蓝桥杯单片机比赛学习:8、PWM的基本原理之呼吸灯的更多相关文章

  1. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  2. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  3. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  4. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  5. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  6. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  7. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

  8. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  9. ruby-on-rails - Rails 基本 Base64 身份验证 - 2

    我正在尝试复制此GETcurl请求:curl-D--XGET-H"Authorization:BasicdGVzdEB0YXByZXNlYXJjaC5jb206NGMzMTg2Mjg4YWUyM2ZkOTY2MWNiNWRmY2NlMTkzMGU="-H"Content-Type:application/json"http://staging.example.com/api/v1/campaigns在Ruby中,通过电子邮件+apikey生成身份验证:auth="Basic"+Base64::encode64("test@example.com:4c3186288ae23fd9661c

  10. ruby - 我如何学习 ruby​​ 的正则表达式? - 2

    如何学习ruby​​的正则表达式?(对于假人) 最佳答案 http://www.rubular.com/在Ruby中使用正则表达式时是一个很棒的工具,因为它可以立即将结果可视化。 关于ruby-我如何学习ruby​​的正则表达式?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1881231/

随机推荐