📄 dimmer.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 + -