⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dimmer.c

📁 LED控制
💻 C
字号:
/************************************************************************
主题:DMX512 按键调光---主控程序
单片机:STC12C5404
晶振:8MHZ  波特率-250KB/S
最后修改日期:2008-12-19
功能:按键调光,带记忆功能 
      S1:P2.5--POWER (ON/OFF)
      S2;P2.6--UP
      S3:P2.7--DOWN 
************************************************************************/
#include    <intrins.h>
#include	<stdio.h>
#include	"stc12c5410.h"
#include	"CodingTable.h"

#define     uchar   unsigned    char
#define     uint    unsigned    int
typedef     unsigned char	INT8U;		/* 8 bit 无符号整型  */
typedef     unsigned int    INT16U;     /* 16 bit 无符号整型 */

#define		TRUE 	1
#define		FALSE 	0
#define     ON		1     
#define     OFF		0
#define		OVERTIME	0xF0
#define		NONE		0x00  

//#define		GREY_LEVEL_MAX	52			//最大灰度值
#define		GREY_LEVEL_MIN	0			//最小灰度值
#define     MAX_ADDR 		210  		//定义最大的需发送数据次数
#define     eeprom_began   	0x2800    	//定义EEPROM起始址

sbit	LED			= P2^0;       		//on/off指示灯
sbit   	KEY_POWER	= P2^5;       		//按键定义
sbit   	KEY_INC		= P2^6;
sbit   	KEY_DEC		= P2^7;
#define	KEY_MASK	0xE0

#define		EnableInterrupt()	EA = 1
#define		DisableInterrupt()	EA = 0

/***************************************************************************
**								全局变量								  **
****************************************************************************/

uchar   Cnt10us;						//延时10us定时器计数器
uchar   Cnt1ms;							//延时1ms定时器计数器

uchar   PowerState;						//电源开关状态 
uchar   GreyLevel;						//LED的灰度值

extern INT8U byte_read(INT16U byte_addr);  //读字节函数
extern INT8U write_flash_with_protect_in_one_sector(INT16U begin_addr, INT16U counter, INT8U array[]);

/************************************************************************
输入参数:uint   ms级
返回参数:无  
备注    ;延时函数
 ************************************************************************/
void  Delay1ms(uchar t)
{
	if(t==0) return;
	Cnt1ms = t;
    TH1 = (65536-8000)/256;	// 8MHz,1T,8000个时钟周期,定时时间为1ms
    TL1 = (65536-8000)%256;	
    
    TF1 = 0;
    TR1 = 1;				// 开定时器
    while(Cnt1ms);
    TR1 = 0;				// 关定时器1
}

/************************************************************************
函数说明:定时10us,使用定时器0  
备注    :定时时间为1us,1000个循环为1ms  
************************************************************************/
void  Delay10us(uchar t)
{
	if(t==0) return;
	Cnt10us = t;
    TH0 = (256-80);			// 8MHz,1T,80个时钟周期,定时时间为10us
    TF0 = 0;
    TR0 = 1;      			// 开定时器
    while(Cnt10us);
    TR0 = 0;				// 关定时器0
}

/************************************************************************
函数说明:定时器0中断服务程序 
备注    :中断时间为10us ,模式2(8位自动重装)
************************************************************************/
void ISR_Timer0(void) interrupt 1
{
	TF0 = 0;
	if(Cnt10us>0){ 
		Cnt10us--;	
	}
}

/************************************************************************
函数说明:定时器1中断服务程序 
备注    :中断时间为1ms,注意模式1(16位)需要软件装载计数器
************************************************************************/
void ISR_Timer1(void) interrupt 3 using 2
{
	TF1 = 0;
    
	TH1 = (65536-8000)/256;	//8MHz,1T,8000个时钟周期,定时时间为1ms
    TL1 = (65536-8000)%256;	
	
	if(Cnt1ms>0){  
		Cnt1ms--;	
	}
}

/************************************************************************
初始化  : 定时器初始化
输入参数:无 
返回参数:无  
备注    :无 
 ************************************************************************/
void Timer_Init(void)
{	
	AUXR |= 0xC0;    //T0,T1速度为12倍标准51 
	TMOD |=	0x12;		// 定时器0为8位自动重装计数器,定时器1为16位计数器

	TF0 = 0;
	TF1 = 0;
	ET0   = 1;       //  允许定时器0中断   
	ET1   = 1;       //  允许定时器1中断   
}

/************************************************************************
初始化  : 串口初始化
输入参数:无 
返回参数:无  
备注    :baud rate = 8MHz/32 = 250Kbps 
 ************************************************************************/
void UART_Init(void)
{
	PCON	|=	0x80;		// SMOD=1,double baud rate 
 	SCON	|=	0x80;		// Mode 2:9 bit,fixed baud rate(1/32 the oscillator frequency)
}

/************************************************************************
初始化  : IO口初始化
输入参数:无 
返回参数:无  
备注    :无 
 ************************************************************************/
void Port_Init(void)
{
	P2M0 = 0xE0; P2M1 = 0x1F;   //强推挽输出

	LED = OFF;
	KEY_POWER = ON;
	KEY_INC= ON;
	KEY_DEC = ON;
}

/************************************************************************
初始化  : 系统初始化
输入参数:无 
返回参数:无  
备注    :无 
 ************************************************************************/
void Sys_Init(void)
{	
	Timer_Init();	//定时器初始化
	UART_Init();	//串口初始化
	Port_Init();	//IO端口初始化
}

/************************************************************************
输入参数:无 
返回参数:无  
备注    :读按键值--eeprom
 ************************************************************************/
void DataResume(void)
{
    PowerState = byte_read(eeprom_began);
    GreyLevel = byte_read(eeprom_began + 1);
}

/************************************************************************
输入参数:无 
返回参数:无  
备注    :读按键值--eeprom
 ************************************************************************/
void DataSave(void)
{
	uchar FlagWrEEPROM;
	uchar Temp[2];
	
	Temp[0] = PowerState;
	Temp[1] = GreyLevel;
	do{
		FlagWrEEPROM = write_flash_with_protect_in_one_sector(eeprom_began,2,&Temp[0]);  //写EEPROM
	}while(!FlagWrEEPROM);
}

/************************************************************************
函数说明:发送DMX512数据(一帧)   
备注    :波特率为250Kbit/s  共发送210次数据(MAX_ADDR)  则发送一轮数据需
          44*210+88+8+8=9344us
************************************************************************/
void DMX512_SendData(uchar TxBuf)
{
    uchar i;
    
	TXD = 0;   			// Break
	Delay10us(10);		// Delay 100us instead 88us
	TXD = 1;			// Mark-after-break
    Delay10us(1);

	TB8 = 1;  			// the tenth bit that is the first stop bit
	for(i=0;i<MAX_ADDR;i++){
		TI = 0;			// 清发送中断标志位	
        SBUF = TxBuf;	// 发送数据
        while(!TI);  	// 等待数据发送完毕
    }
    TXD = 1;   			// 置数据空闲位
}

void TurnOff_Output(void)
{
    uchar i;
	
	TXD = 0;   			// Break
	Delay10us(10);		// Delay 100us instead 88us
	TXD = 1;			// Mark-after-break
    Delay10us(1);

	TB8 = 1;  			// the tenth bit that is the first stop bit
	for(i=0;i<MAX_ADDR;i++){
		TI = 0;			// 清发送中断标志位	
        SBUF = 0x00;	// 发送数据
        while(!TI);  	// 等待数据发送完毕
    }
    TXD = 1;   			// 置数据空闲位
}

/************************************************************************
输入参数:无 
返回参数:BIT[2-0]对应DEC,INC,POWER,值为1表示按键按下  
备注    :KEY_POWER -> P2.5
		  KEY_INC 	-> P2.6
		  KEY_DEC 	-> P2.7
 ************************************************************************/
uchar KeyScan(void)
{
    uchar i, KeyValue;

	if((P2 & KEY_MASK)== KEY_MASK) return(NONE); 	//无按键按下
	Delay1ms(20);    								//有按键按下,则延时消抖
	if((P2 & KEY_MASK)== KEY_MASK) return(NONE); 	//误触发
	
	if(PowerState) LED = !LED;
	
	KeyValue = (~(P2>>5)) & 0x07;
	
	for(i=0;i<20;i++){
		Delay1ms(10);
		if((P2 & KEY_MASK)== KEY_MASK) break;		//按键松开	
	}
	
	if(PowerState) LED = !LED;
	
	if(i<20) return KeyValue;						//没有超时
	else return OVERTIME;							//按键按下超过200ms
}


void  main(void)
{
	uchar KeyValue;		//按键返回值(可能为NONE,OVERTIME或有效按键值1~7)
	uchar i;
	
	Sys_Init();				//系统初始化
	DataResume();	//从EEPROM中读取数据:电源开关状态和LED灰度值
	EnableInterrupt();
	
	while(1)
	{
		KeyValue = KeyScan();											//扫描按键
		
		if (KeyValue==NONE){											//无按键按下
			if (PowerState){											//控制面板上的LED开关			
				LED = ON;
				DMX512_SendData(CodingTable[GreyLevel]);								//向调光器发送数据
			} else {
				LED = OFF;
				TurnOff_Output();										//关闭调光器输出
			}
		}
		else if (KeyValue==OVERTIME){									//按键按下超时,快速调节模式
			if (!KEY_POWER){											//KEY_POWER键按下		
				while(!KEY_POWER);										//等待按键松开
				Delay1ms(20);
				while(!KEY_POWER);										//等待按键松开
				if(PowerState){
					PowerState = OFF;
					TurnOff_Output();
				}else{
					PowerState = ON;
					DMX512_SendData(CodingTable[GreyLevel]);
				}
				DataSave();												//记录下控制参数	
			} 
			else if (!KEY_INC){											//KEY_INC键按下
				if(PowerState == OFF) continue;							//在电源关闭的情况下禁止调光
				i = 0;
				while(!KEY_INC){										//KEY_INC键持续按下过程中
					if(GreyLevel < GREY_LEVEL_MAX){
						GreyLevel++;
						DMX512_SendData(CodingTable[GreyLevel]);						//调光
						Delay1ms(20);									//此处延时影响连续调光时的平滑程度及调节速度
						if(++i >= 6){									//6分频,周期120ms
							i = 0;
							LED = !LED;	
						}
					} else {
						GreyLevel = GREY_LEVEL_MAX;
						//DMX512_SendData(CodingTable[GreyLevel]);						//向调光器发送数据
						//Delay1ms(40);
						//LED = !LED;	
					} 
				}
				LED = ON;
				DataSave();	
			}
			else if (!KEY_DEC){											//KEY_DEC键按下
				if(PowerState == OFF) continue;							//在电源关闭的情况下禁止调光
				i = 0;
				while(!KEY_DEC){										//KEY_DEC键持续按下过程中
					if(GreyLevel > GREY_LEVEL_MIN){
						GreyLevel--;
						DMX512_SendData(CodingTable[GreyLevel]);						//调光
						Delay1ms(20);									//此处延时影响连续调光时的平滑程度及调节速度
						if(++i >= 6){									//6分频,周期120ms
							i = 0;
							LED = !LED;	
						}
						
					} else {
						GreyLevel = GREY_LEVEL_MIN;	
						//DMX512_SendData(CodingTable[GreyLevel]);						//向调光器发送数据
						//Delay1ms(40);
						//LED = !LED;	
					}
				}
				LED = ON;
				DataSave();	
			}
		}
		else {															//单击模式
			if(KeyValue & 0x01){										//KEY_POWER键按下
				if(PowerState){											//切换开关状态
					PowerState = OFF;
					TurnOff_Output();
				}else{
					PowerState = ON;
					DMX512_SendData(CodingTable[GreyLevel]);								//向调光器发送数据
				}
			}
			else if(KeyValue & 0x02){									//KEY_INC键按下
				if(PowerState == ON){
					if(GreyLevel < GREY_LEVEL_MAX){
						GreyLevel++;
						DMX512_SendData(CodingTable[GreyLevel]);						//向调光器发送数据
					} else {
						GreyLevel = GREY_LEVEL_MAX;
						DMX512_SendData(CodingTable[GreyLevel]);						//向调光器发送数据
					}
				}
			} 
			else if(KeyValue & 0x04){									//KEY_DEC键按下
				if(PowerState == ON){
					if(GreyLevel > GREY_LEVEL_MIN){
						GreyLevel--;
						DMX512_SendData(CodingTable[GreyLevel]);						//向调光器发送数据
					} else {
						GreyLevel = GREY_LEVEL_MIN;	
						DMX512_SendData(CodingTable[GreyLevel]);						//向调光器发送数据
					}
				}
			}
			DataSave();													//重新保存LED控制参数
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -