?? 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 + -