基於STC51微控制器的霓虹燈

Code&將進酒發表於2021-08-01

基於STC51微控制器的霓虹燈

設計要求:

  • 使用PWM驅動8個LED燈
  • 人眼不能觀察到燈光全滅
  • 燈光要有動畫效果

設計概述:

​  按照設計要求,為了更直觀的說明脈衝寬度調製技術(PWM),所以霓虹燈的動畫效果為流水燈形式。所需要的微控制器晶片為STC89C52,所用的硬體工具是由華清遠見開發的基於STC89C52的智慧小車。該小車配備所需要的LED燈模組,8個LED燈由P1口來控制。STC89C52是一種低功耗,高效能的8位微控制器,是加強版的80C51微控制器,但是與80C51微控制器一樣不具備PWM硬體模組,所以我們需要自己寫一個程式來軟體模擬PWM方波。

​​  PWM是一種方波,可以實現數字訊號控制類比電路,它有兩個重要引數週期或頻率,佔空比。佔空比 = 高電平時間/週期,最小為0%,最大為100%,通過調整佔空比來控制高電平,低電平所佔比例,進而調控LED燈的亮滅與明暗變化。STC89C52中P1口為低電平有效,將P1口置0,LED燈亮,置1燈滅。若將P1口的電平輸出訊號調整成高低電平各佔50%,即在一個週期內高電平,低電平所佔比例都是50%,P1口控制的LED燈將會明暗閃爍。

​​  市面上的許多51微控制器開發板大同小異,都是用P1口控制LED燈,所以在此就不提供智慧小車的原理圖和實物圖。

原始碼:

軟體模擬PWM方波通常利用定時器來實現。

參考程式碼1:

#include <reg52.h>
//定義一個全域性變數pwm,通過對全域性變數的累加來控制PWM的佔空比
unsigned int pwm = 0;
/*
利用定時器和I/O口來輸出PWM方波實現8個LED燈的明暗變化
*/

/*定時器中斷服務函式*/
void Timer0() interrupt 1
{
	pwm++;
      if(pwm == 500)
      {
         P1 = 0xfe;//第1盞燈亮
      }
      else if(pwm == 1000)
      {
   	     P1 = 0xff;//第1盞燈滅
      }
	  else if(pwm == 1500)
      {
   	     P1 = 0xfd;//第2盞燈亮
      }
	  else if(pwm == 2000)
      {
   	     P1 = 0xff;
      }
	  else if(pwm == 2500)
      {
   	     P1 = 0xfb;//第3盞燈亮
      }
	  else if(pwm == 3000)
      {
   	     P1 = 0xff;
      }
	  else if(pwm == 3500)
      {
   	     P1 = 0xf7;//第4盞燈亮
      }
	  else if(pwm == 4000)
      {
   	     P1 = 0xff;
      }
	  else if(pwm == 4500)
      {
   	     P1 = 0xef;//第5盞燈亮
      }
	  else if(pwm == 5000)
      {
   	     P1 = 0xff;
      }
	  else if(pwm == 5500)
      {
   	     P1 = 0xdf;//第6盞燈亮
      }
	  else if(pwm == 6000)
      {
   	     P1 = 0xff;
      }
	  else if(pwm == 6500)
      {
   	     P1 = 0xbf;//第7盞燈亮
      }
	  else if(pwm == 7000)
      {
   	     P1 = 0xff;
      }
	  else if(pwm == 7500)
      {
   	     P1 = 0x7f;//第8盞燈亮
      }
	  else if(pwm == 8000)
      {
   	     P1 = 0xff;
		 pwm = 0;
      }
}

void main()
{
   TMOD |= 1<<1;	  //通過移位運算子"<<"來改變位的狀態
   TMOD &= ~(1<<0);	//置定時器/計數器的工作方式為方式2

   TMOD &= ~(1<<2);	  //選擇定時工作方式
   TMOD &= ~(1<<3);	  //門控位:由執行控制位TR啟動定時器

   TL0 = 156;		   
   TH0 = 156;		   //100us進入一次中斷,0.1毫秒

   ET0 = 1;			  //定時器0開中斷
   EA = 1;			   //CPU開中斷
   TR0 = 1;			  //啟動定時器0
   while(1)			 //防止程式跑飛
        ;
}

參考程式碼2:

/*第一個檔案為自定義標頭檔案
此標頭檔案裡宣告pwm_led_ctl函式
*/
#ifndef _LED_H
#define _LED_H

//控制某一盞燈亮
char pwm_led_ctl(unsigned int led_num);
#endif

/*
第二個檔案
此原始檔用於實現pwm_led_ctl函式
*/
#include <reg52.h>
#include "led.h"
//軟體模擬PWM方波,通過變數pwm調控PWM佔空比
char pwm_led_ctl(unsigned int led_num)
{
   unsigned int pwm;
   for(pwm = 0;pwm <= 2000;pwm++)
   {
     if(pwm == 1000)
     {
   	    P1 &= ~(1<<led_num);//通過移位運算子"<<"逐個點亮LED燈
     }
     else if(pwm == 2000)
     {
   	    P1 |= 1<<led_num;
     }
   }
   return 0;
}

/*
第三個檔案
主函式原始檔
*/
#include <reg52.h>
#include "led.h"

/*定時器中斷服務函式*/
void Timer0() interrupt 1
{
	unsigned int i;
	for(i=0;i<8;i++)
	{
	   pwm_led_ctl(i);
	}
}

void main()
{
   TMOD |= 1<<1;	  //通過移位運算子"<<"來改變位的狀態
   TMOD &= ~(1<<0);	//置定時器/計數器的工作方式為方式2

   TMOD &= ~(1<<2);	  //選擇定時工作方式
   TMOD &= ~(1<<3);	  //門控位:由執行控制位TR啟動定時器

   TL0 = 156;		   
   TH0 = 156;		   //100us進入一次中斷,0.1毫秒

   ET0 = 1;			  //定時器0開中斷
   EA = 1;			   //CPU開中斷
   TR0 = 1;			  //啟動定時器0
   while(1)			 //防止程式跑飛
        ;
}


相關文章