找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 21475|回复: 15
收起左侧

51单片机入门经验分享9-定时器模拟实现PWM呼吸灯效果(代码+详解)

  [复制链接]
ID:74187 发表于 2018-10-12 09:04 | 显示全部楼层 |阅读模式
本帖最后由 dabing89 于 2018-10-14 19:04 编辑

用定时器来模拟实现PWM实现呼吸灯的效果--20181012
      众所周知,PWM的应用是及其广泛的,现在很多高速的单片机内部都集成了硬件PWM,使用起来也很简单,配置好频率和装入计数值就可以工作了,但是在一些低成本的场合,我们选择的单片机没有硬件PWM功能模块,但是我们还存在这个需求怎么办呢?这个时候,我们需要用PWM来模拟实现他,但实现PWM必须要了解PWM的原理,这里我们先了解下。
      PWM全称是脉冲宽度调制解调,比如1个小灯,按照500MS亮一次,500MS灭一次,周期是1S,频率是1HZ,在这里,1个周期说明白了就是2个方波,有高电平和低电平组成,在周期固定的情况下,我们通过不断的调整高电平所占的整个周期比例,即所谓的占空比,就可以实现小灯”不是那么亮“的效果,如果连续起来,就可以实现呼吸灯的效果了,先来用定时器0实现小灯500MS闪烁的效果,通过DEBUG来看下波形。我们把下面的代码拷贝进去,看下现象

单片机源码:
  1. /********************************************************
  2. *描述:工程模板,点亮led        500MS闪烁 12MHZ
  3. ********************************************************/
  4. #include "stc15w.h"


  5. /*******************************************************************************
  6. * 文件名:位定义
  7. * 描  述:
  8. * 功  能:
  9. * 作  者:大核桃
  10. * 版本号:1.0.1(2017.05.23)
  11. *******************************************************************************/
  12. bit flag500ms = 0;//500ms标志位
  13. sbit LED0 = P1^0;//
  14. sbit DATA0 = P2^0;//

  15. /*******************************************************************************
  16. * 文件名:数据类型定义
  17. * 描  述:
  18. * 功  能:
  19. * 作  者:大核桃
  20. * 版本号:1.0.1(2017.05.23)
  21. *******************************************************************************/
  22. typedef unsigned char uint8;
  23. typedef unsigned int  uint16;
  24. typedef unsigned long uint32;

  25. /*******************************************************************************
  26. * 文件名:函数前置声明
  27. * 描  述:
  28. * 功  能:
  29. * 作  者:大核桃
  30. * 版本号:1.0.1(2017.05.23)
  31. *******************************************************************************/

  32. void Bsp_Power_Init(void);
  33. void Timer0Init(void);

  34. /*******************************************************************************
  35. * 文件名:主循环入口
  36. * 描  述:
  37. * 功  能:
  38. * 作  者:大核桃
  39. * 版本号:1.0.1(2017.05.23)
  40. *******************************************************************************/
  41. void main(void)
  42. {
  43.         Bsp_Power_Init();//LED端口初始化
  44.         Timer0Init();
  45.         LED0 = 1;

  46.         while(1)
  47.         {

  48.                 if(flag500ms)
  49.                 {
  50.                         flag500ms = 0;

  51.                         DATA0 = ~DATA0;//
  52.                 }
  53.                         
  54.         }
  55. }

  56. /*******************************************************************************
  57. * 文件名:void Bsp_Power_Init()
  58. * 描  述: 数码管上电显示
  59. * 功  能:编程模块化
  60. * 作  者:大核桃
  61. * 版本号:1.0.1(2017.05.23)
  62. *******************************************************************************/
  63. void Bsp_Power_Init(void)
  64. {
  65.         P0M1 = 0xFC;
  66.         P0M0 = 0X03;
  67.         P0 = 0X00;

  68.         P1M1 = 0xE0;
  69.         P1M0 = 0X1F;
  70.         P1 = 0X00;


  71.         //P2口开漏输出
  72.         P2M1 = 0XFF;
  73.         P2M0 = 0XFF;
  74.         P2 = 0Xff;
  75. //        //P54,P55口为推挽输出
  76.         P5M1 = 0X00;
  77.         P5M0 = 0X00;
  78.         P5 = 0xFF;

  79.         //P37,P36,3.2,P3.3 P3.4口为推挽输出
  80.         P3M1 = 0X00;
  81.         P3M0 = 0XFC;
  82.         P3 = 0X23;

  83. }

  84. /*******************************************************************************
  85. * 文件名:void Bsp_Power_Init()
  86. * 描  述: 数码管上电显示
  87. * 功  能:编程模块化
  88. * 作  者:大核桃
  89. * 版本号:1.0.1(2017.05.23)
  90. *******************************************************************************/
  91. void Timer0Init(void)                //1毫秒@12MHZ
  92. {
  93.         AUXR &= 0x7f;                    //定时器时钟12T模式
  94.         TMOD &= 0xF0;                    //设置定时器模式
  95.         TMOD |= 0x01;                    //设置定时器模式
  96.         TL0 = (65535 - 1000) % 256;                //设置定时初值
  97.         TH0 = (65535 - 1000) / 256;                //设置定时初值
  98.         ET0 = 1;
  99.         TR0 = 1;                //定时器0开始计时
  100.         EA = 1;
  101. }

  102. /*******************************************************************************
  103. * 文件名:void TIME0_INTER(void) interrupt 1
  104. * 描  述:
  105. * 功  能:
  106. * 作  者:大核桃
  107. * 版本号:1.0.1(2017.05.23)
  108. *******************************************************************************/
  109. void TIME0_INTER(void) interrupt 1
  110. {
  111.         static uint16 tmr500ms = 0;

  112.         TL0 = (65535 - 1000) % 256;                //设置定时初值1ms
  113.     TH0 = (65535 - 1000) / 256;                //设置定时初值

  114.         tmr500ms++;

  115.         if(tmr500ms >= 500)
  116.         {
  117.                 tmr500ms = 0;

  118.                 flag500ms  = 1;
  119.         }
  120.                                        
  121. }

复制代码
方针.jpg
从DEBUG可以看到,是500MS变化一次,说明我们的设置是对的,但是在这里还是说明一点,我们用的而是STC15W系列的芯片,但是定时器我配置成了12T模式,和STC89C52是一样使用的。既然我们实现了这个500MS高电平,500MS低电平的效果,我们再来实现下200MS亮,800MS灭的效果吧,程序代码如下:

  1. /********************************************************
  2. *描述:工程模板,点亮led        500MS闪烁 12MHZ
  3. ********************************************************/
  4. #include "stc15w.h"


  5. /*******************************************************************************
  6. * 文件名:位定义
  7. * 描  述:
  8. * 功  能:
  9. * 作  者:大核桃
  10. * 版本号:1.0.1(2017.05.23)
  11. *******************************************************************************/
  12. sbit LED0 = P1^0;//
  13. sbit DATA0 = P2^0;//

  14. /*******************************************************************************
  15. * 文件名:数据类型定义
  16. * 描  述:
  17. * 功  能:
  18. * 作  者:大核桃
  19. * 版本号:1.0.1(2017.05.23)
  20. *******************************************************************************/
  21. typedef unsigned char uint8;
  22. typedef unsigned int  uint16;
  23. typedef unsigned long uint32;

  24. /*******************************************************************************
  25. * 文件名:函数前置声明
  26. * 描  述:
  27. * 功  能:
  28. * 作  者:大核桃
  29. * 版本号:1.0.1(2017.05.23)
  30. *******************************************************************************/

  31. void Bsp_Power_Init(void);
  32. void Timer0Init(void);

  33. /*******************************************************************************
  34. * 文件名:主循环入口
  35. * 描  述:
  36. * 功  能:
  37. * 作  者:大核桃
  38. * 版本号:1.0.1(2017.05.23)
  39. *******************************************************************************/
  40. void main(void)
  41. {
  42.         Bsp_Power_Init();//LED端口初始化
  43.         Timer0Init();
  44.         LED0 = 1;

  45.         while(1);

  46. }

  47. /*******************************************************************************
  48. * 文件名:void Bsp_Power_Init()
  49. * 描  述: 数码管上电显示
  50. * 功  能:编程模块化
  51. * 作  者:大核桃
  52. * 版本号:1.0.1(2017.05.23)
  53. *******************************************************************************/
  54. void Bsp_Power_Init(void)
  55. {
  56.         P0M1 = 0xFC;
  57.         P0M0 = 0X03;
  58.         P0 = 0X00;

  59.         P1M1 = 0xE0;
  60.         P1M0 = 0X1F;
  61.         P1 = 0X00;


  62.         //P2口开漏输出
  63.         P2M1 = 0XFF;
  64.         P2M0 = 0XFF;
  65.         P2 = 0Xff;
  66. //        //P54,P55口为推挽输出
  67.         P5M1 = 0X00;
  68.         P5M0 = 0X00;
  69.         P5 = 0xFF;

  70.         //P37,P36,3.2,P3.3 P3.4口为推挽输出
  71.         P3M1 = 0X00;
  72.         P3M0 = 0XFC;
  73.         P3 = 0X23;

  74. }

  75. /*******************************************************************************
  76. * 文件名:void Bsp_Power_Init()
  77. * 描  述: 数码管上电显示
  78. * 功  能:编程模块化
  79. * 作  者:大核桃
  80. * 版本号:1.0.1(2017.05.23)
  81. *******************************************************************************/
  82. void Timer0Init(void)                //1毫秒@12MHZ
  83. {
  84.         AUXR &= 0x7f;                    //定时器时钟12T模式
  85.         TMOD &= 0xF0;                    //设置定时器模式
  86.         TMOD |= 0x01;                    //设置定时器模式
  87.         TL0 = (65535 - 1000) % 256;                //设置定时初值
  88.         TH0 = (65535 - 1000) / 256;                //设置定时初值
  89.         ET0 = 1;
  90.         TR0 = 1;                //定时器0开始计时
  91.         EA = 1;
  92. }

  93. /*******************************************************************************
  94. * 文件名:void TIME0_INTER(void) interrupt 1
  95. * 描  述:
  96. * 功  能:
  97. * 作  者:大核桃
  98. * 版本号:1.0.1(2017.05.23)
  99. *******************************************************************************/
  100. void TIME0_INTER(void) interrupt 1
  101. {
  102.         static uint16 tmr200ms = 0;
  103.         static bit a = 0;//翻转状态变量


  104.         if(a)
  105.         {
  106.                 TL0 = (65535 - 1000) % 256;                //设置定时初值1ms
  107.         TH0 = (65535 - 1000) / 256;                //设置定时初值

  108.                 DATA0 = 0;//小灯亮

  109.                 tmr200ms++;        
  110.                 if(tmr200ms >= 200)
  111.                 {
  112.                         tmr200ms = 0;
  113.                         a = 0;
  114.                 }
  115.         }
  116.         else
  117.         {
  118.                 TL0 = (65535 - 1000) % 256;                //设置定时初值1ms
  119.         TH0 = (65535 - 1000) / 256;                //设置定时初值
  120.                 DATA0 = 1;//小灯灭

  121.                 tmr200ms++;        
  122.                 if(tmr200ms >= 800)
  123.                 {
  124.                         tmr200ms = 0;
  125.                         a = 1;
  126.                 }        
  127.         }
  128.                                        
  129. }
复制代码


仿真效果如下图所示: 方针2.jpg
我们可以看到高电平占到了80,低电平占到了20,但是把代码下载进单片机,怎么不是我们想要的那种状态呢?这里普及一个知识点,前面帖子说过的,人类的眼睛不能分辨这种刷新速度低于10MS的物体,如果物体的刷新速度高于10MS,我们的眼睛就会感觉到明显的闪烁了,所以我们看到了下载进开发板的现象就是亮200MS,灭800MS的效果,但是我们想实现我们想要的那种不是太亮的效果怎么办呢?其实只要把刷新频率高于100HZ就OK了,也就是周期要控制在10MS之内,改变高低电平所占的比例即可实现这样的效果,我们写一个让小灯2MS亮8MS灭的程序,看看啥效果,程序如下:
  1. /********************************************************
  2. *描述:工程模板,点亮led        500MS闪烁 12MHZ
  3. ********************************************************/
  4. #include "stc15w.h"


  5. /*******************************************************************************
  6. * 文件名:位定义
  7. * 描  述:
  8. * 功  能:
  9. * 作  者:大核桃
  10. * 版本号:1.0.1(2017.05.23)
  11. *******************************************************************************/
  12. sbit LED0 = P1^0;//
  13. sbit DATA0 = P2^0;//

  14. /*******************************************************************************
  15. * 文件名:数据类型定义
  16. * 描  述:
  17. * 功  能:
  18. * 作  者:大核桃
  19. * 版本号:1.0.1(2017.05.23)
  20. *******************************************************************************/
  21. typedef unsigned char uint8;
  22. typedef unsigned int  uint16;
  23. typedef unsigned long uint32;

  24. /*******************************************************************************
  25. * 文件名:函数前置声明
  26. * 描  述:
  27. * 功  能:
  28. * 作  者:大核桃
  29. * 版本号:1.0.1(2017.05.23)
  30. *******************************************************************************/

  31. void Bsp_Power_Init(void);
  32. void Timer0Init(void);

  33. /*******************************************************************************
  34. * 文件名:主循环入口
  35. * 描  述:
  36. * 功  能:
  37. * 作  者:大核桃
  38. * 版本号:1.0.1(2017.05.23)
  39. *******************************************************************************/
  40. void main(void)
  41. {
  42.         Bsp_Power_Init();//LED端口初始化
  43.         Timer0Init();
  44.         LED0 = 1;

  45.         while(1);

  46. }

  47. /*******************************************************************************
  48. * 文件名:void Bsp_Power_Init()
  49. * 描  述: 数码管上电显示
  50. * 功  能:编程模块化
  51. * 作  者:大核桃
  52. * 版本号:1.0.1(2017.05.23)
  53. *******************************************************************************/
  54. void Bsp_Power_Init(void)
  55. {
  56.         P0M1 = 0xFC;
  57.         P0M0 = 0X03;
  58.         P0 = 0X00;

  59.         P1M1 = 0xE0;
  60.         P1M0 = 0X1F;
  61.         P1 = 0X00;


  62.         //P2口开漏输出
  63.         P2M1 = 0XFF;
  64.         P2M0 = 0XFF;
  65.         P2 = 0Xff;
  66. //        //P54,P55口为推挽输出
  67.         P5M1 = 0X00;
  68.         P5M0 = 0X00;
  69.         P5 = 0xFF;

  70.         //P37,P36,3.2,P3.3 P3.4口为推挽输出
  71.         P3M1 = 0X00;
  72.         P3M0 = 0XFC;
  73.         P3 = 0X23;

  74. }

  75. /*******************************************************************************
  76. * 文件名:void Bsp_Power_Init()
  77. * 描  述: 数码管上电显示
  78. * 功  能:编程模块化
  79. * 作  者:大核桃
  80. * 版本号:1.0.1(2017.05.23)
  81. *******************************************************************************/
  82. void Timer0Init(void)                //1毫秒@12MHZ
  83. {
  84.         AUXR &= 0x7f;                    //定时器时钟12T模式
  85.         TMOD &= 0xF0;                    //设置定时器模式
  86.         TMOD |= 0x01;                    //设置定时器模式
  87.         TL0 = (65535 - 1000) % 256;                //设置定时初值
  88.         TH0 = (65535 - 1000) / 256;                //设置定时初值
  89.         ET0 = 1;
  90.         TR0 = 1;                //定时器0开始计时
  91.         EA = 1;
  92. }

  93. /*******************************************************************************
  94. * 文件名:void TIME0_INTER(void) interrupt 1
  95. * 描  述:
  96. * 功  能:
  97. * 作  者:大核桃
  98. * 版本号:1.0.1(2017.05.23)
  99. *******************************************************************************/
  100. void TIME0_INTER(void) interrupt 1
  101. {
  102.         static uint16 tmr200ms = 0;
  103.         static bit a = 0;//翻转状态变量


  104.         if(a)
  105.         {
  106.                 TL0 = (65535 - 1000) % 256;                //设置定时初值1ms
  107.         TH0 = (65535 - 1000) / 256;                //设置定时初值

  108.                 DATA0 = 0;//小灯亮

  109.                 tmr200ms++;        
  110.                 if(tmr200ms >= 2)
  111.                 {
  112.                         tmr200ms = 0;
  113.                         a = 0;
  114.                 }
  115.         }
  116.         else
  117.         {
  118.                 TL0 = (65535 - 1000) % 256;                //设置定时初值1ms
  119.         TH0 = (65535 - 1000) / 256;                //设置定时初值
  120.                 DATA0 = 1;//小灯灭

  121.                 tmr200ms++;        
  122.                 if(tmr200ms >= 8)
  123.                 {
  124.                         tmr200ms = 0;
  125.                         a = 1;
  126.                 }        
  127.         }
  128.                                        
  129. }
复制代码
方针3.jpg
将程序下载进板子上,可以很明显的看到小灯变的不是那么亮了,用逻辑分析仪看下,我们的周期是10MS,实现了我们想要的变的不是那么亮的效果,可是距离我们想要的呼吸灯还是没有实现啊?怎么办呢?答案很简单,只要在在定时器中装入不同的初值即可实现这样的效果,不过要实现呼吸灯的效果,一个定时器是不够的,还要再用一个定时器1才可以,写好的程序如下:
  1. /********************************************************
  2. *描述:工程模板 PWM呼吸灯代码
  3. ********************************************************/
  4. #include "stc15w.h"


  5. /*******************************************************************************
  6. * 文件名:位定义
  7. * 描  述:
  8. * 功  能:
  9. * 作  者:大核桃
  10. * 版本号:1.0.1(2017.05.23)
  11. *******************************************************************************/
  12. bit flag200ms = 0;
  13. bit flag800ms = 0;
  14. sbit LED0 = P1^0;//
  15. sbit DATA0 = P2^0;//
  16. void Bsp_Power_Init(void);
  17. void TIM0_Init(void);
  18. void TIM1_Init(void);

  19. /*******************************************************************************
  20. * 文件名:数据类型定义
  21. * 描  述:
  22. * 功  能:
  23. * 作  者:大核桃
  24. * 版本号:1.0.1(2017.05.23)
  25. *******************************************************************************/
  26. typedef unsigned char uint8;
  27. typedef unsigned int  uint16;
  28. typedef unsigned long uint32;

  29. uint8 i = 0;
  30. code uint16 PWM_H[] = {
  31.         100,300,500,700,1000,1300,1500,1700,2000,2300,2500,2700,
  32.         3000,3300,3500,3700,4000,4300,4500,4700,5000,5300,5500,
  33.         5700,6000,6300,6500,6700,7000,7300,7500,7700,8000,8300,
  34.         8500,8700,9000,9300,9500,9700,9900 //高电平重装值
  35. };

  36. code uint16 PWM_L[] = {

  37.         9900,9700,9500,9300,9000,8700,8500,8300,8000,7700,7500,
  38.         7300,7000,6700,6500,6300,6000,5700,5500,5300,5000,4700,
  39.         4500,4300,4000,3700,3500,3300,3000,2700,2500,2300,2000,
  40.         1700,1500,1300,1000,700,500,300,100//低电平重装值
  41. };


  42. /*******************************************************************************
  43. * 文件名:主循环入口
  44. * 描  述:
  45. * 功  能:
  46. * 作  者:大核桃
  47. * 版本号:1.0.1(2017.05.23)
  48. *******************************************************************************/
  49. void main(void)
  50. {
  51.         Bsp_Power_Init();//LED端口初始化
  52.         TIM0_Init();
  53.         TIM1_Init();
  54.         LED0 = 1;

  55.         while(1)
  56.         {
  57.                 if(flag200ms)
  58.                 {
  59.                         flag200ms = 0;

  60.                         DATA0 = 0;
  61.                 }

  62.                 if(flag800ms)
  63.                 {
  64.                         flag800ms = 0;

  65.                         DATA0 = 1;
  66.                 }

  67.         }
  68. }

  69. /*******************************************************************************
  70. * 文件名:void Bsp_Power_Init()
  71. * 描  述: 数码管上电显示
  72. * 功  能:编程模块化
  73. * 作  者:大核桃
  74. * 版本号:1.0.1(2017.05.23)
  75. *******************************************************************************/
  76. void Bsp_Power_Init(void)
  77. {
  78.         P0M1 = 0xFC;
  79.         P0M0 = 0X03;
  80.         P0 = 0X00;

  81.         P1M1 = 0xE0;
  82.         P1M0 = 0X1F;
  83.         P1 = 0X00;


  84.         //P2口开漏输出
  85.         P2M1 = 0XFF;
  86.         P2M0 = 0XFF;
  87.         P2 = 0Xff;
  88. //        //P54,P55口为推挽输出
  89.         P5M1 = 0X00;
  90.         P5M0 = 0X00;
  91.         P5 = 0xFF;

  92.         //P37,P36,3.2,P3.3 P3.4口为推挽输出
  93.         P3M1 = 0X00;
  94.         P3M0 = 0XFC;
  95.         P3 = 0X23;

  96. }

  97. /*******************************************************************************
  98. * 文件名:void Timer0Init(void)
  99. * 描  述: 数定时器0初始化
  100. * 功  能:编程模块化
  101. * 作  者:大核桃
  102. * 版本号:1.0.1(2017.05.23)
  103. *******************************************************************************/
  104. void TIM0_Init(void)
  105. {
  106.         AUXR &= 0x7F;//定时器时钟12T模式
  107.         TMOD &= 0XF0;//配置定时器0为工作模式1
  108.         TMOD |= 0X01;
  109.         TH0 = (65535 - 1000) / 256;//高八位重载值溢出1000次定时1ms
  110.         TL0 = (65535 - 1000) % 256;//低八位重载值
  111.         ET0 = 1;//打开定时器0中断使能位
  112.         TR0 = 1;//打开定时器,使之工作
  113.         EA = 1;//打开总中断        
  114. }

  115. /*******************************************************************************
  116. * 文件名:void TIM1_Init(void)
  117. * 描  述:定时器1初始化配置
  118. * 功  能:初始化
  119. * 作  者:大核桃
  120. * 版本号:1.0.1(2016.07.23)
  121. *******************************************************************************/
  122. void TIM1_Init(void)
  123. {
  124.         AUXR &= 0xBF;//定时器时钟12T模式
  125.         TMOD &= 0X0F;//配置定时器1为工作模式1
  126.         TMOD |= 0X10;
  127.         TH1 = (65535 - 10000) / 256;//高八位重载值溢出1000次定时1ms
  128.         TL1 = (65535 - 10000) % 256;//低八位重载值
  129.         ET1 = 1;//打开定时器1中断使能位
  130.         TR1 = 1;//打开定时器,使之工作
  131.         EA = 1;//打开总中断        
  132. }

  133. /*******************************************************************************
  134. * 文件名:中断服务函数
  135. * 描  述:定时器1中断服务函数
  136. * 功  能:        中断标号对应   参考数据手册560页        
  137. *                        中断名称         
  138. * 作  者:大核桃
  139. * 版本号:1.0.1(2016.11.15)
  140. *******************************************************************************/
  141. void TIM1_IRQ_Handler(void)        interrupt 3
  142. {
  143.         static uint16 tmr50ms = 0;
  144.         static bit a = 0;

  145.         TH1 = (65535 - 10000) / 256;
  146.         TL1 = (65535 - 10000) % 256;//10ms溢出一次

  147.         tmr50ms++;
  148.         if(tmr50ms >= 5)//50ms改变一次PWM重装值
  149.         {
  150.                 tmr50ms = 0;

  151.                 if(a)
  152.                 {
  153.                    i--;
  154.                    if(i == 0)
  155.                    {
  156.                             a = 0;
  157.                    }
  158.         
  159.                 }
  160.                 else
  161.                 {
  162.                         i++;
  163.                         if(i >= 40)
  164.                         {
  165.                                 a = 1;
  166.                         }
  167.         
  168.                 }
  169.         }
  170.                
  171. }

  172. /*******************************************************************************
  173. * 文件名:void TIMER0_INTER(void) interrupt 1
  174. * 描  述: 中断处理程序
  175. * 功  能:
  176. * 作  者:大核桃
  177. * 版本号:1.0.1(2017.05.23)
  178. *******************************************************************************/
  179. void TIM0_IRQ_Handler(void)        interrupt 1
  180. {
  181.         static bit index = 0;

  182.         if(index)
  183.         {
  184.                 TH0 = (65536 - PWM_H[i]) / 256;
  185.                 TL0 = (65536 - PWM_H[i]) % 256;//12MHZ下溢出1000次定时1ms

  186.                 flag200ms = 1;
  187.                 index = 0;
  188.         }
  189.         else
  190.         {
  191.                 TH0 = (65536 - PWM_L[i]) / 256;
  192.                 TL0 = (65536 - PWM_L[i]) % 256;//12MHZ下溢出1000次定时1ms
  193.                 flag800ms = 1;

  194.                 index = 1;        
  195.         }        
  196.                         
  197. }
复制代码


我们用了定时器1每隔50MS改变1次定时器的初值,做了2个数组,分别存放PWM的高电平计数初值和低电平计数初值,在12MHZ下计数10000个,恰好是10MS,这样我们就实现了呼吸灯的效果,如果你想让呼吸灯变的更平滑更均匀,可以将定时器的初值更加细化就可以了,如果你对这个程序有啥疑问,可以留言,好了,就介绍到这里吧,代码奉献上。

全部资料51hei下载地址:
009 实用PWM的使用.rar (35.08 KB, 下载次数: 203)
回复

使用道具 举报

ID:328014 发表于 2018-10-12 13:40 | 显示全部楼层
太棒了,介绍的非常详细,语言通俗易懂,非常适合单片机初学者学习PWM控制,楼主用心了
回复

使用道具 举报

ID:1 发表于 2018-10-12 13:40 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:398515 发表于 2018-10-12 13:41 | 显示全部楼层
一个不错的呼吸灯教程
回复

使用道具 举报

ID:258164 发表于 2018-12-18 09:51 | 显示全部楼层
楼主你好,我正在研究模拟呼吸灯的教程,请问如果只用一个定时中断能实现吗?或者说有没有别的效率更高的办法
回复

使用道具 举报

ID:407089 发表于 2018-12-27 00:44 | 显示全部楼层
HelloPan111 发表于 2018-12-18 09:51
楼主你好,我正在研究模拟呼吸灯的教程,请问如果只用一个定时中断能实现吗?或者说有没有别的效率更高的办 ...

http://www.51hei.com/bbs/dpj-147511-1.html
回复

使用道具 举报

ID:578183 发表于 2019-7-4 23:28 来自手机 | 显示全部楼层
最近刚刚接触pwm的我来学习一下
回复

使用道具 举报

ID:511328 发表于 2019-7-7 20:11 | 显示全部楼层
谢谢楼主的分享
回复

使用道具 举报

ID:612010 发表于 2019-9-17 10:18 | 显示全部楼层
收藏学习一下
回复

使用道具 举报

ID:245820 发表于 2020-1-9 21:49 | 显示全部楼层
学习了,谢谢
回复

使用道具 举报

ID:690363 发表于 2020-3-3 02:06 | 显示全部楼层
我没看懂,得慢慢消化
回复

使用道具 举报

ID:428114 发表于 2021-3-25 19:32 | 显示全部楼层
楼主花不少精力啊
回复

使用道具 举报

ID:64253 发表于 2022-4-5 16:17 | 显示全部楼层
这份资料图文并茂,相当详细
回复

使用道具 举报

ID:1032507 发表于 2022-10-26 15:35 | 显示全部楼层
写的非常详细,又配了图,谢谢楼主分享
回复

使用道具 举报

ID:1049825 发表于 2022-10-31 20:30 | 显示全部楼层
刚刚发现楼主的讲解精彩易懂,管理员的头像也很帅。看来要在这个论坛里泡好久了。。。
回复

使用道具 举报

ID:1033105 发表于 2023-2-7 11:48 | 显示全部楼层
楼主把PWM解说的通俗易懂,感谢楼主
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表