前言:
如果只用单片机做一个调光系统,pwm是可以实现的,但是如果有其它的功能(比如传感器要检测,显示屏显示数据等等功能)就不推荐了。其它函数一多,定时器的时间又比较短,以至于单片机大多数时间都用在定时中断函数里去了,处理其它函数的时间太少,其它函数执行太慢,效果不佳。如果定时器的时间太大,其它功能倒是有时间执行了,但是小灯的闪烁就会太严重,效果不佳。

目录

  • PWM工作原理
    • 1、PWM简介
    • 2、工作原理
    • 3、代码实现
      • 1)定时器代码实现
      • 2)串口部分代码实现:

PWM工作原理

1、PWM简介

PWM(pulse width modulation)是脉冲宽度调制的缩写,利用微处理器的数字输出来对模拟电路进行控制的一种技术。应用领域包括:功率控制与变换,电动机控制,伺服控制,调光等等。

2、工作原理

pwm调光是通过调节占空比的方式调节灯光亮度的。它先要设定一个周期(比如10ms),然后在这个周期内调节高电平和低电平的时间。比如:
1、10ms内全是高电平,这个灯就是最亮;
2、如果5ms是高电平,5ms是低电平,这样其实是灯亮5ms,然后熄灭5ms,灯是在不断的闪烁的,但是由于灯频闪太快,人肉眼是分辨不过来,所以最后人观测灯的效果就是亮度减半了;
3、如果10ms内全是低电平,这个灯就是熄灭的状态。

如下图:所以我们可以设定一个临界值c,只需要调节这个c就可以调节周期内高低电平的时间了。

3、代码实现

先说一下最终实现的样子吧:

通过在串口中发送调光命令(数字+#的组合方式,数字范围0-100),比如我要调节灯的来高度为50,就通过串口发送“50#”的命令,然后灯的亮度就是最高亮度的一半,我通过串口发送“100#“,灯的亮度就是最亮。

所以接下来依次实现所有思路:

先引入一个小疑问:

有人问为什么我们要用定时器呢,这里用定时器来固定周期长度,用定时器确定时间,相对延时函数来说要准确些,当然不用定时器也能实现PWM调光,用延时函数实现的方法大致如下:

//这里周期为10us
int c=1;   //亮度为最亮的1/10
while(1)
{led=1;    delay_us(c);led=0;delay_us(10-c);
}

下面还是言归正传,回到这次话题上

1)定时器代码实现

 1、先对定时器进行初始化
void InitTimer0(void)
{TMOD |= 0x01;     //设置定时器0工作方式1TH0 = 0x0FF;          //设置时间为1usTL0 = 0x0FF;EA = 1;                 //开总中断ET0 = 1;             //开定时器0中断TR0 = 1;              //启动定时器0,开始计数
}

初始化中有一个小细节: 这里选择了定时器0,后面串口也要用到定时器,所以串口只能选择定时器1了,两边都会对TMOD这个寄存器初始化,所以对其赋值为了不影响另一个定时器的配置,我们这里没有采用TMOD = 0x01;的方式,而是采用TMOD |= 0x01;的方式。这样就可以防止影响高四位了(因为高四位对应定时器1)。

2、再写定时器中断函数代码
int time0Flag;   //time0Flag用于计数,判断当前多少us了
int num1;       //num1就是上图中的C,通过调节它,从而调节高低电平的占空比void Timer0Interrupt(void) interrupt 1
{TH0 = 0x0FF;          //重新赋予计数初值,方便下次计数TL0 = 0x0FF;time0Flag++;         //记录计数时间为多少us,if(time0Flag>100)   //PWM占空比周期为100us,超过周期变量赋值为0,变为下一周期time0Flag=0;/*你会不会产生疑问?为什么把下面的这个判断功能放在定时器中断函数里,为什么不放在主函数里。放在主函数里没有放在这里执行的次数多,执行的次数多,pwm调光时灯的频闪就越小,看起越舒服。还好主函数里没有什么执行函数,你可以在主函数的while循环里执行一些其它函数,当函数多起来的时候,单品即的时间都基本用在处理定时中断函数去了,主函数里的函数就会得不到及时处理。把下面的功能放在主函数里和其它函数一起不断执行呢,你可以试一下,我试过了,哪个屏闪哦,没得说,灯简直不要太闪。那有没有既有效可以解决pwm调光的频闪,同时又可以在主函数里运行很多其它函数,目前我还没有找到解决办法,想来想去,可能唯一的办法就是多cpu并行执行的多线程了,pwm调光单独开一个线程,但单片机不允许呀,哈哈。所以就这样搞着玩一下吧。*/if(time0Flag<num1)led=0;        //led为单片机连接的灯的引脚elseled=1;
}

每次进入定时器,都判断当前时间是否达到num1,没有就让灯亮,达到了就让灯灭

PWM的周期要尽可能的小!,这样调节占空比,人肉眼才难发觉

假如你周期设为10s,然后调节占空比,实现高电平5s,低电平5s,然后不断这样亮灭亮灭。这个频率,你能接受?这样就不是调光了,就是闪光灯了。所以周期越小,然后调节高低电平时间,这样灯就会闪得越快,人肉眼就越难看出灯在闪烁,最终呈现的就是灯的亮度变化了

2)串口部分代码实现:

1、使用串口我们就要先对串口进行一系列的初始化,先列出串口的初始化代码
void UartInit()
{SCON=0X50;            //设置串口为工作方式1TMOD|=0X20;            //设置计数器1工作方式2//PCON=0X80;          //波特率加倍TH1=0xfd;               //计数器初始值设置,注意波特率是9600的TL1=0xfd;IP =0x10;               //将串口中断设置为高优先级,等同于语句于:PS=1;ES=1;                   //打开接收中断EA=1;                  //打开总中断TR1=1;                  //打开计数器
}

注意:IP寄存器平时我们很少用到,这里这条语句”IP =0x10;“不能少,去掉后串口中断不能正常工作,因为串口中断的优先级比定时器0的优先级低,因而在你想要从串口中接收、发送数据时,往往得不到处理,因为都处理定时中断函数去了,如果没有这条语句,加之你定时中断的时间很短的话,那么很有可能不会进入串口中断,每次都会优先执行定时中断0。所以我们人为的将串口中断的优先级设置为高优先级,让串口中断优先处理。那会不会有人问,这样的话那不就换成定时中断函数得不到处理了?不会的,因为从串口中接收、发送数据不可能每时每刻都在进行,用到它的时候很少,它没有中断的大部分时间,都可以去处理定时中断函数了。

2、然后就是串口中断函数的实现
//串口发送字符
void SendChar(char Char)
{SBUF=Char;while(!TI);TI=0;
}
//串口发送字符串
void SendString(char *p)
{while(*p!='\0'){SendChar(*p);p++;}
}int uartFlag=0;           //全局变量,接收串口命令中数组内的标号
char receiveData[8]={'\0'};  //全局变量,用于接收串口数据,表示命令最多有*个字符,对方的控制命令以#号结束//串口中断函数
void Uart() interrupt 4
{if(RI)     //如果是串口接收到一帧数据,就会产生中断,RI标志变为1{char sf,i,len;RI = 0;          //手动将标志置0,方便下次判断sf=SBUF;if(sf!='#')      //对方发送的命令都以'#'作为结束符,如果本次接受的字符不是'#',则保存命令中的字符到数组       {receiveData[uartFlag++]=sf;     //保存缓存中的数据}else     //表示接收到一条命令了{           receiveData[uartFlag]='\0';      //命令最后加上'\0',便于字符串比较(strcmp函数)uartFlag=0;                                     //表示本次数据接收完毕,置0,便于接收下条命令SendString(receiveData);num1=0;            //每次接收到调光的命令后都要将它置0len=strlen(receiveData);                for(i=0;i<len;i++)    //将命令中的字符数组,解析、组合成对应的数字,方便定时器中断函数中进行比较{num1+=((receiveData[i]-'0') * pow(10,len-1-i));}}}
}

结束了!!,上面的代码就是所有,看了实在还是不会,下面放上完整的项目代码:

【[完整代码地址]】(https://download.csdn.net/download/qq_41873236/18303870)

单片机——PWM调光工作原理相关推荐

  1. 基于51单片机pwm调光护眼台灯智能检测光强光控灯设计proteus仿真原理图PCB

    功能: 0.本系统采用STC89C52作为单片机 1.LCD1602液晶实时显示当前时间/模式/亮度等级 2.按'切换'键可切换四种不同的模式 a) 自动开关,自动调节亮度 b) 手动开关,自动调节亮 ...

  2. 一款大功率6A 深度PWM调光的降压恒流驱动工作原理

    产品描述    APS54083 是一款 PWM 工作模式,高效率.外 围简单.外置功率 MOS 管,适用于 5-220  V 输入 高精度降压 LED 恒流驱动芯片.输出功率150W 电流 6A. ...

  3. 基于8086单片机的PWM调光(带汇编)

    之前网上并没有详细的基于8086的PWM调光设计,做完课程设计,给大家分享一下使用DAC8032提供电压的设计思路. 1. 总体设计 在这次设计中,使用了PWM脉宽调制输出方式,即通过对一系列脉冲的宽 ...

  4. PT4115使用STM32单片机引脚PWM调光

    PT4115使用STM32单片机引脚PWM调光 与上位机使用modbus与上位机使用modbus通信,能够实现0~100%亮度调节,现存问题:上电时LED灯亮一下,可能怀疑是PWM初始化太慢,直接将引 ...

  5. 基于8086单片机的PWM调光(8255带汇编)

    之前网上并没有详细的基于8086的PWM调光设计,做完课程设计,给大家分享一下使用8255实现四个等级调光的设计思路. 1.总体设计 通过8255查询ADC0808的EOC口判断A/D转化是否完成,转 ...

  6. 单片机知识:了解PWM调光

    了解PWM 一.难受的频闪 二.显示器发展历程 三.PWM是什么? 四.小实验自己制作PWM调光 更多内容... 我们不是针对谁,无论是LCD,是OLED,还是灯管,任何使用低频PWM调光的显示和照明 ...

  7. PWM调光方法在LED亮度调节中的应用

    LED 是一种固态电光源, 是一种半导体照明器件,其电学特性具有很强的离散性.它具有体积小.机械强度大.功耗低.寿命长, 便于调节控制及无污染等特征,有极大发展前景的新型光源产品.LED 调光方法的实 ...

  8. 单片机自动调光C语言,51单片机触控调光程序C语言

    /********************************************************************************************* 程序名: ...

  9. OC7141 PWM 调光的线性降压 LED 恒流驱动器

    OC7141概述 OC7141 是一种带 PWM 调光功能的线  性降压 LED 恒流驱动器,仅需外接一个电阻和一个 NMOS 管就可以构成一个完整的LED 恒流驱动电路,调节该外接电阻就可以  调节 ...

最新文章

  1. CUDA C++编程接口:编译
  2. Mysql索引命中问题
  3. iOS实现经典登录页面,手机号自动格式化
  4. vue-cli 3.0 跨域请求代理
  5. 【转载】也有很多的例子飞鸽传书
  6. intellij mysql jdbc_intellij idea java项目中通过JDBC链接mysql
  7. 为什么学前端不先学框架?
  8. 大数据之-Hadoop3.x_Yarn_生产环境核心参数配置案例---大数据之hadoop3.x工作笔记0150
  9. BZOJ #3746: [POI2015]Czarnoksiężnicy okrągłego stołu 动态规划
  10. java 反射父类私有属性值_如何在Java中通过反射访问父类的父类的私有字段? - java...
  11. 使用jQuery快速高效制作网页交互特效(1)
  12. 使用锚标记返回网页顶部的方法
  13. Castle IOC容器构建配置详解(二)
  14. 设备管理系统未来发展的四大趋势
  15. Android network框架分析之NetworkManagementService和netd交互深入分析(二)
  16. nodejs+java+python网上体育用品销售系统
  17. stm32 IAP 程序编写心得
  18. 飞天系统和linux,用Linux或Windows系统运行抢茅台脚本在性能上有区别吗?
  19. 使用MOSES搭建网页翻译系统
  20. line-rate 线速

热门文章

  1. 【unity shader】基于UGUI字体的outline优化
  2. Tikz学习笔记(一)
  3. Word2vec词向量工具带你发现不一样的《天龙八部》
  4. Codeforces Round # 555 (Div3)
  5. Gauss工作—学习笔记
  6. wifi卡慢延迟高_WiFi明明信号满格,为何又卡又慢,问题在这里!
  7. 网络视频血战:弱者渔利
  8. 【已解决】ThinkdPad X1 麦克风没声音
  9. 【C语言/C++程序员编程】一小时做出来的数字雨(一颗开花的树)!
  10. 微信公众平台开发(1)验证TOKEN源码