[应用方案] 单片机PWM技术实现呼吸灯和KTV等娱乐场所的灯光闪烁效果

[复制链接]
1672|2
 楼主| 李香兰 发表于 2016-2-29 19:59 | 显示全部楼层 |阅读模式
程序是在51hei单片机开发板上面做的,电路很简单,最小系统+P0的八个led即可.ADDR0和ENLED那是开发板上的led使能电路控制端,如果是你自己做的电路 可以删掉这几个语句.或者不用管他,不会影响程序的运行.
  1. /**
  2.   ************************************************************************************************************
  3.   * [url=home.php?mod=space&uid=288409]@file[/url]   :      main.c
  4.   * [url=home.php?mod=space&uid=187600]@author[/url] :      xr
  5.   * [url=home.php?mod=space&uid=212281]@date[/url]   :      2014年4月15日20:34:05 - 2014年4月15日22:28:08
  6.   * @version: V1.2.3
  7.   * [url=home.php?mod=space&uid=247401]@brief[/url]  :      PWM技术实现呼吸灯和KTV等娱乐场所的灯光闪烁效果 单片机STC89C52RC MCU 晶振 11.0592MHZ
  8.   ************************************************************************************************************
  9.   */
  10. #include <reg52.h>

  11. //74HC138
  12. sbit ADDR0 = P1^0;
  13. sbit ADDR1 = P1^1;
  14. sbit ADDR2 = P1^2;
  15. sbit ADDR3 = P1^3;
  16. sbit ENLED = P1^4;

  17. //sbit PWMOUT = P0^0;//PWM输出
  18. #define PWMOUT P0   //8个LED小灯同时呼吸

  19. //灯光控制编码(调整PWM的占空比)
  20. unsigned char code PWM_Table[] = {
  21.   1,  3,  8,  11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50,
  22.   53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98, 99
  23. }; //34个占空比

  24. unsigned char heighHR0, heighLR0;//PWM高电平计数初值的高字节和低字节
  25. unsigned char lowHR0, lowLR0;   //PWM低电平计数初值的高字节和低字节
  26. unsigned char thr1, tlr1;       //T1计数初值高字节和低字节
  27. unsigned long PWMCounter = 0;      //PWM设定频率后的对应的所需计数值 UL型

  28. void Initial();
  29. void ConfigPWM(unsigned int fr, unsigned char dc);
  30. void ConfigTimer1(unsigned int xms);

  31. void main(void)
  32. {
  33. Initial();
  34. /**********呼吸灯效果***************/
  35. ConfigPWM(100, 5);//设定PWM的脉冲宽度为100hz,即10ms,占空比为5%,当PWM的脉冲宽度小于100HZ时,形成的是闪烁的灯光效果
  36. ConfigTimer1(50);  //定时50ms调整PWM占空比

  37. /*PWM技术实现KTV等娱乐场所的灯光闪烁效果*/
  38. /***************灯光闪烁****************/
  39. /*
  40. ConfigPWM(10, 5); //PWM脉冲宽度为10HZ,即1ms, 占空比5%
  41. ConfigTimer1(50); //定时20ms调整PWM占空比
  42. */

  43. while (1);
  44. }

  45. /*初始化*/
  46. void Initial()
  47. {
  48. ADDR3 = 1;
  49. ENLED = 0;//选择LED

  50. ADDR2 = 1;
  51. ADDR1 = 1;
  52. ADDR0 = 0;//选择LEDS6,即流水灯
  53. }

  54. /*使用定时器T0配置PWM*/
  55. void ConfigPWM(unsigned int fr, unsigned char dc) //参数:fr PWM配置的频率,当是100时,即是100HZ,周期是10ms,dc为占空比
  56. {
  57. unsigned long tmp;
  58. unsigned int heigh, low;//分别存放高电平计数值和低电平计数值

  59. tmp = 11059200/12;//一个机器周期的计数频率
  60. PWMCounter = tmp / fr;//一个机器周期计数频率是多少个fr计数频率,即fr频率需要的计数值
  61. heigh = (PWMCounter * dc) / 100;//高电平所需计数值 1/fr周期内高电平计数值
  62. low   = PWMCounter - heigh;//低电平所需计数值  1/fr周期内低电平计数值
  63. heigh = 65536-heigh;       //高电平时定时器需要装入的初值
  64. low   = 65536-low;    //低电平时定时器需要装入的初值

  65. heighHR0 = (unsigned char)(heigh >> 8);
  66. heighLR0 = (unsigned char)heigh;
  67. lowHR0   = (unsigned char)(low >> 8);
  68. lowLR0   = (unsigned char)low;

  69. TMOD &= 0xF0;//清零T0控制位
  70. TMOD |= 0x01;//Timer0方式1,16位可设定定时模式
  71. TH0 = heighHR0;
  72. TL0 = heighLR0;//装入高电平时的初值
  73. PWMOUT = 0xFF;//开始PWM输出高电平
  74. TR0 = 1;//启动定时器T0
  75. ET0 = 1;//开启T0中断
  76. EA  = 1;//开总中断
  77. }

  78. /*配置定时器Timer1,用于定时xms调整PWM的占空比*/
  79. void ConfigTimer1(unsigned int xms)
  80. {
  81. unsigned long tmp;
  82. tmp = 11059200/12;//一个机器周期的计数频率
  83. tmp = (tmp * xms) /1000;//定时xms需要的计数频率(即计数次数)
  84. tmp = 65536-tmp;//定时xms需要装入的计数初值
  85. thr1 = (unsigned char)(tmp >> 8);//取高八位
  86. tlr1 = (unsigned char)tmp;

  87. TMOD &= 0x0F;//清零T1控制位
  88. TMOD |= 0x10;//定时器T1方式1,16位可设定时器
  89. TH1 = thr1;
  90. TL1 = tlr1;
  91. TR1 = 1;//启动timer1
  92. ET1 = 1;//开启定时器T1中断
  93. EA  = 1;//开启总中断
  94. }


 楼主| 李香兰 发表于 2016-2-29 20:00 | 显示全部楼层
  1. /*调整PWM占空比*/
  2. void AdjustPWMdc(unsigned char dc)
  3. {
  4. unsigned int heigh, low;
  5. heigh = (PWMCounter * dc) / 100; //PWM脉冲中高脉冲所需计数值
  6. low   = PWMCounter - heigh;//PWM脉冲中低脉冲所需的计数值
  7. heigh = 65536-heigh;//高脉冲装入计数的初值
  8. low   = 65536-low;  //低脉冲装入计数的初值

  9. /*调整PWM高低脉冲计数初值,来调整PWM的占空比*/
  10. heighHR0 = (unsigned char)(heigh >> 8);
  11. heighLR0 = (unsigned char)heigh;
  12. lowHR0   = (unsigned char)(low >> 8);
  13. lowLR0   = (unsigned char)low;
  14. }

  15. /*定时器Timer0中断服务*/
  16. void Timer0_ISP() interrupt 1
  17. {
  18. //在中断中对PWM的输出电平进行判断,若当前输出是高电平,则开始装入低电平的计数初值,PWM输出低电平
  19. if (PWMOUT)
  20. {
  21. //Timer0装入PWM一个周期中低脉冲的计数初值
  22. TH0 = lowHR0;
  23. TL0 = lowLR0;
  24. PWMOUT = 0x00;//PWM输出低电平
  25. }
  26. else  //否则装入高电平的计数初值,输出高电平
  27. {
  28. //Timer0装入PWM一个周期中高脉冲的计数初值
  29. TH0 = heighHR0;
  30. TL0 = heighLR0;
  31. PWMOUT = 0xFF;//PWM输出高脉冲
  32. }
  33. }

  34. /*定时器Timer1中断服务*/
  35. void Timer1_ISP() interrupt 3
  36. {
  37. //注意:index和dir在每次进入中断后都要使用上一次的值,因此必须定义为静态类型
  38. static unsigned char index = 0;//占空比索引
  39. static bit dir = 0;//方向位,0灯光由亮->暗 1灯光由暗->亮

  40. TH1 = thr1;
  41. TL1 = tlr1;

  42. AdjustPWMdc(PWM_Table[index]);//调用调整PWM占空比函数,调整PWM占空比

  43. if (dir == 0)
  44. {
  45. index++;   //索引++
  46. if (index >= 33)     //34个占空比
  47. {
  48. index = 33;
  49. dir = 1;//改变方向
  50. }
  51. }
  52. else
  53. {
  54. index--; //索引--
  55. if (index == 0)
  56. {
  57. index = 0;
  58. dir = 0;//改变方向
  59. }
  60. }
  61. }
cowboy2014 发表于 2016-3-5 20:11 | 显示全部楼层
PWM能够实现呼吸灯,纯硬件是不是也可以呢
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

248

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部