标题:
基于51单片机PWM控制LED实验程序
[打印本页]
作者:
东大高材生
时间:
2021-12-2 22:10
标题:
基于51单片机PWM控制LED实验程序
#include "STC15F2K60S2.H"
#include "stdio.h"
#include "board_init.h"
#include "Led.h"
#include "keyboard.h"
#include "Timer.h"
#include "seg.h"
#include "Delay.h"
#include "string.h"
#include "iic.h"
//函数声明区
void Key_Proc(void);
void Seg_Proc(void);
void Led_Proc(void);
unsigned char trans_function(unsigned char);
unsigned char PWM_control();
void BUZZ_control(void);
void Delay(unsigned int num);
long ms_Tick = 0;
//定时器减速区变量
unsigned int Key_Slow_Down;
unsigned int Seg_Slow_Down;
unsigned int Led_Slow_Down;
//按键专用变量
unsigned char Key_Value;
unsigned char Key_Old;
unsigned char Key_Down;
//数码管专用变量
unsigned char seg_string[10];
unsigned char seg_string1[5];
unsigned char seg_buf[8];
unsigned char pos=0;
//LED专用变量
unsigned char ucLed;
//其他变量定义
bit State_flag = 0;
unsigned char state = 1;
unsigned char light_Lv[10]={0,1,1,1,1,1,1,1,1,1};
unsigned char timer_count; //pwm控制一个周期 20ms,放在计时器1中累加,20置零。
unsigned char interface_state = 1; //页面状态。
unsigned int interface_timer = 0;
bit BUZZ = 0; //用于限制蜂鸣器只关闭一次的变量。
bit BUZZ1;
unsigned char BUZZ_LV ;
unsigned char timer_count1;
unsigned char timer_count_2;
sbit delay = P0^4;
sbit Buzz = P0^6;
bit sparkle;
bit Error_waning;
bit Led_control_state;
unsigned int A;
long ms_Tick_sparkle;
unsigned char V;
void main(void)
{
Cls_Periheral();
Timer1Init();
Timer0Init();
EA = 1;
ucLed = 0xff;
IP = 0X01; //0000 1000
while(1)
{
Key_Proc();
Led_Proc();
BUZZ_control();
V = Pfc_8591_Adc(0x43)/2.55/4;
}
}
/* Timer1_interrupt routine */
void tm1_isr() interrupt 3
{
ms_Tick++;
if (++timer_count == 23) timer_count = 0;//pwm 50HZ;
if (++timer_count_2 == 25) timer_count_2 = 0;
if (interface_timer == 10000)
{
interface_state = 1;
interface_timer = 0;
}
if(Led_control_state == 0)
interface_timer ++;
if (++Key_Slow_Down == 10) Key_Slow_Down = 0; //减速变量区,控制子函数的刷新频率
if (++Led_Slow_Down == 100) Led_Slow_Down = 0;
if (++Seg_Slow_Down == 500) Seg_Slow_Down = 0;
Seg_Disp(seg_buf,pos); //用于数码管显示
if(++pos == 8) pos=0;
Seg_Proc();
ucLed = PWM_control();
Led_Disp(ucLed); //用于LED显示
}
/* Timer0_interrupt routine */
void tm0_isr() interrupt 1
{
if (++timer_count1 == A) timer_count1 = 0;
}
void Key_Proc()
{
if (Key_Slow_Down) return;
Key_Slow_Down=1;
Key_Value = Key_Read();
Key_Down = Key_Value & (Key_Old ^ Key_Value);
Key_Old = Key_Value;
if(interface_state == 3) //PWM控制蜂鸣器声音大小
{
switch(Key_Down)
{
case 4:
BUZZ_LV = 0; break;
case 8:
BUZZ_LV = 1; break;
case 12:
BUZZ_LV = 2; break;
case 16:
BUZZ_LV = 3; break;
case 9:
BUZZ_LV = 4; break;
case 13:
BUZZ_LV = 5; break;
case 17:
BUZZ_LV = 6; break;
case 10:
BUZZ_LV = 7; break;
case 14:
BUZZ_LV = 8; break;
case 18:
BUZZ_LV = 9; break;
}
}
if(interface_state == 2)
{
switch(Key_Down)
{
case 5 ://向右调节
if(state == 8) state = 0;
state ++;
break;
case 6 ://向左调节
if(state == 1) state = 9;
state --;
break;
case 4:
light_Lv[state] = 0; break;
case 8:
light_Lv[state] = 1; break;
case 12:
light_Lv[state] = 2; break;
case 16:
light_Lv[state] = 3; break;
case 9:
light_Lv[state] = 4; break;
case 13:
light_Lv[state] = 5; break;
case 17:
light_Lv[state] = 6; break;
case 10:
light_Lv[state] = 7; break;
case 14:
light_Lv[state] = 8; break;
case 18:
light_Lv[state] = 9; break;
case 11:
Led_control_state = ~Led_control_state;
break;
case 15: //报警。
case 19:
Error_waning = 1;
break;
}
}
if(Key_Down == 7) //界面状态调节
{
if(interface_state == 3) interface_state = 0;
interface_state ++;
}
if(Key_Down) interface_timer = 0; //若有键盘按下,则重新计时返回主页面的时间。
}
void Led_Proc(void)
{
if (Led_Slow_Down) return;
Led_Slow_Down = 1;
}
void Seg_Proc()
{
if (Seg_Slow_Down) return;
Seg_Slow_Down = 1;
switch(interface_state)
{
case 1: //主界面 亮度表格
//因为sprintf打印%d超过4个会出现溢出,而keil5没有提供改进版,故分成两次打印。
sprintf(seg_string,"%d%d%d%d",(unsigned int)light_Lv[1],(unsigned int)light_Lv[2],(unsigned int)light_Lv[3],(unsigned int)light_Lv[4]);
sprintf(seg_string1,"%d%d%d%d",(unsigned int)light_Lv[5],(unsigned int)light_Lv[6],(unsigned int)light_Lv[7],(unsigned int)light_Lv[8]);
strcat(seg_string,seg_string1);
break;
case 2://当前选中闪烁
if(Led_control_state == 0)
{
sprintf(seg_string,"%d%d%d%d",(unsigned int)light_Lv[1],(unsigned int)light_Lv[2],(unsigned int)light_Lv[3],(unsigned int)light_Lv[4]);
sprintf(seg_string1,"%d%d%d%d",(unsigned int)light_Lv[5],(unsigned int)light_Lv[6],(unsigned int)light_Lv[7],(unsigned int)light_Lv[8]);
strcat(seg_string,seg_string1);
if((ms_Tick - ms_Tick_sparkle)>=200)
ms_Tick_sparkle = ms_Tick;
sparkle ^= 1;
if(sparkle ==1)
{
switch(state)
{
case 1:
seg_string[0] = ' ';
break;
case 2:
seg_string[1] = ' ';
break;
case 3:
seg_string[2] = ' ';
break;
case 4:
seg_string[3] = ' ';
break;
case 5:
seg_string[4] = ' ';
break;
case 6:
seg_string[5] = ' ';
break;
case 7:
seg_string[6] = ' ';
break;
case 8:
seg_string[7] = ' ';
break;
}
}
}
else
{
sprintf(seg_string,"%03.0f ",(float)(4*V));
}
break;
case 3:
sprintf(seg_string,"-------%d",(unsigned int)BUZZ_LV);
break;
}
Seg_Tran(seg_string,seg_buf);
}
/*****pwm亮度控制*****/
unsigned char PWM_control()
{
unsigned char i = 0;
unsigned char j = 0;
unsigned char k = 5;
if(Error_waning == 0 && Led_control_state == 0)
{
if(light_Lv[1] != 0) //不区分0亮度的话,灯熄灭不了。
{
if( timer_count <= light_Lv[1]*2.3 ) ucLed = ucLed | 0x01; //0000 0001
else ucLed = ucLed & ~0x01;
}
else
ucLed = ucLed & ~0x01;
if(light_Lv[2] != 0) //不区分0亮度的话,灯熄灭不了。
{
if( timer_count <= light_Lv[2]*2.3 ) ucLed = ucLed | 0x02; //0000 0010
else ucLed = ucLed & ~0x02;
}
else
ucLed = ucLed & ~0x02;
if(light_Lv[3] != 0) //不区分0亮度的话,灯熄灭不了。
{
if( timer_count <= light_Lv[3]*2.3 ) ucLed = ucLed | 0x04; //0000 0100
else ucLed = ucLed & ~0x04;
}
else
ucLed = ucLed & ~0x04;
if(light_Lv[4] != 0) //不区分0亮度的话,灯熄灭不了。
{
if( timer_count <= light_Lv[4]*2.3 ) ucLed = ucLed | 0x08; //0000 1000
else ucLed = ucLed & ~0x08;
}
else
ucLed = ucLed & ~0x08;
if(light_Lv[5] != 0) //不区分0亮度的话,灯熄灭不了。
{
if( timer_count <= light_Lv[5]*2.3 ) ucLed = ucLed | 0x10; //0001 0000
else ucLed = ucLed & ~0x10;
}
else
ucLed = ucLed & ~0x10;
if(light_Lv[6] != 0) //不区分0亮度的话,灯熄灭不了。
{
if( timer_count <= light_Lv[6]*2.3 ) ucLed = ucLed | 0x20; //0010 0000
else ucLed = ucLed & ~0x20;
}
else
ucLed = ucLed & ~0x20;
if(light_Lv[7] != 0) //不区分0亮度的话,灯熄灭不了。
{
if( timer_count <= light_Lv[7]*2.3 ) ucLed = ucLed | 0x40; //0100 0000
else ucLed = ucLed & ~0x40;
}
else
ucLed = ucLed & ~0x40;
if(light_Lv[8] != 0) //不区分0亮度的话,灯熄灭不了。
{
if( timer_count <= light_Lv[8]*2.3 ) ucLed = ucLed | 0x80; //1000 0100
else ucLed = ucLed & ~0x80;
}
else
ucLed = ucLed & ~0x80;
}
else if(Error_waning == 1 && Led_control_state == 0) //LED闪烁报警
{
while (k)
{
for(i=0;i<9;i++) //控制亮度等级
for(j=0;j<4;j++) //控制当前亮度等级的循环次数
{
Led_Disp(0Xff); //全亮
Delay(i+1); //亮的时间
Led_Disp(0x00);// 全灭
Delay(9-i); //灭的时间
}
k--;
}
Error_waning = 0;
}
else if (Led_control_state)
{
if(timer_count_2 <= V) ucLed = 0xFF; //
else ucLed = 0x00;
}
if(interface_state == 3) //PWM调频控制蜂鸣器
{
switch(BUZZ_LV)
{
case 0:
BUZZ1 = 0;
break;
case 1 :
A = 200;
if(timer_count1<=A/2) BUZZ1 = 1;
else BUZZ1 = 0; break;
case 2:
A = 100;
if(timer_count1<=A/2) BUZZ1 = 1;
else BUZZ1 = 0; break;
break;
case 3:
A = 50;
if(timer_count1<=A/2) BUZZ1 = 1;
else BUZZ1 = 0; break;
break;
case 4:
// A = 30;
A = 300;
if(timer_count1<=A/2) BUZZ1 = 1;
else BUZZ1 = 0; break;
break;
case 5:
//A = 20;
A = 400;
if(timer_count1<=A/2) BUZZ1 = 1;
else BUZZ1 = 0; break;
break;
case 6:
A = 14;
if(timer_count1<=A/2) BUZZ1 = 1;
else BUZZ1 = 0; break;
break;
case 7:
A = 10;
if(timer_count1<=A/2) BUZZ1 = 1;
else BUZZ1 = 0; break;
break;
case 8:
A = 4;
if(timer_count1<=A/2) BUZZ1 = 1;
else BUZZ1 = 0; break;
break;
case 9:
A = 2;
if(timer_count1<=A/2) BUZZ1 = 1;
else BUZZ1 = 0; break;
break;
}
}
return ucLed;
}
/*****蜂鸣器控制函数*****/
void BUZZ_control(void)
{
if(interface_state == 3 && BUZZ1 ==1 && BUZZ == 0)
{
BUZZ = 1;
Buzz = 1; //打开蜂鸣器
delay = 0;
P2=P2 & 0X1F | 0Xa0; //Y5 开蜂鸣器
P2 &= 0X1F;
}
if(interface_state == 3 && BUZZ1 == 0 && BUZZ == 1)
{
BUZZ = 0;
Buzz = 0; //
delay = 0;
P2=P2 & 0X1F | 0Xa0; //Y5 关蜂鸣器
P2 &= 0X1F;
}
if(interface_state <3 && BUZZ == 1)
{
BUZZ = 0;
Buzz = 0;
delay = 0;
P2=P2 & 0X1F | 0Xa0; //Y5 关蜂鸣器
P2 &= 0X1F;
}
}
/*****延时函数*****/
void Delay(unsigned int num)
{
unsigned int i;
while(num--)
for(i=0;i<628;i++); //晶振频率为12MHZ则震动一次周期为(1/12M)S\ 数量级为 um 执行628次,需要时间≈1ms
}
复制代码
Keil代码下载:
程序源码.zip
(151.44 KB, 下载次数: 13)
2021-12-2 22:09 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1