?? meteor.c.bak
字號:
/****************************************Copyright (c)****************************************************
** LED Incorporated Co.,LTD.
**
** http://www.ledinc.biz
**
**------------------------------------- File Info --------------------------------------------------------
** File Name : Meteor.c
** Hardware : MCU = AT89C2051; Fosc = 24MHz
** Compiler : C51
**
**------------------------------------ Version Info ------------------------------------------------------
** Create By : Raymond
** Create Date : 09-04-09
** Version : 1.00
** Description :
** 1. 隨機速度、流星長度;
** 2. 定時器0產生隨機種子;
** 3. 淡入淡出效果;
** 4. 梯形算法產生流星頭亮尾暗的效果;
** 5. 發現問題:亮度不夠,因為每次都是等所有的LED滅了以后再移位的,總體上看LED點亮的時間比列不高。
**--------------------------------------------------------------------------------------------------------
** Modify By : Raymond
** Modify Date : 09-04-13
** Version : 1.01
** Description :
** 1. 解決梯形算法的一個bug:當流星長度Len為1時,除數(Len-1)為零;
** 2. 移位應該進行16+1次,不然最后1bit會殘留在流星管上,這在Len=1時表現突出;
** 3. 隨機函數有待改進,發現Len=1的重復周期總在6次到8次左右;
**--------------------------------------------------------------------------------------------------------
** Modify By : Raymond
** Modify Date : 09-04-13
** Version : 2.00
** Description :
** 1. 優化梯形算法(多米諾骨牌算法,Domino),增加亮度以及平滑度;
** 2. 改進隨機函數,使輸出數據更加隨機;
**
**--------------------------------------------------------------------------------------------------------
** Modify By : Raymond
** Modify Date : 09-04-15
** Version : 2.01
** Description :
** 1. 從STC12C4510AD移植到AT89C2051,管腳有變化,且STC是1T時鐘,更快,定時相關的需要修改;
** 2. 當隨機算法相同時,偽隨機數的種子決定出現的隨機數;
** 3. 修改軟件,使用捕捉RC充電常數來決定隨機種子,硬件方面把RC中的電容接到Vcc,電阻接到GND,RC節點連到INT1
** 即外部中斷1,使用下降沿觸發,捕捉定時器0(因為是8位隨機數,故只捕捉TL0);當RC值足夠大時,實際效果可以做到
** 每次上電后的第一次都不一樣,即硬件非偽隨機。
**
**--------------------------------------------------------------------------------------------------------
** Modify By : Raymond
** Modify Date : 09-04-16
** Version : 2.02
** Description :
** 1. 細調時間參數、增加閃爍間隔時間的隨機數量;
**
*********************************************************************************************************/
#include "reg51.h"
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
#define NOP() /*Delay(1) */
#define EnableInterrupt() EA = 1
#define DisableInterrupt() EA = 0
/* PIN define */
sbit LATCH = P3^0;
sbit CLK = P3^1;
sbit SDA = P3^2;
typedef struct{
unsigned char MeteorLen; //流星長度
unsigned char Speed; //下降速度,數組越大速度越慢
} METEOR;
//-------------Config Parameter-------------
#define SPEED_MAX_GRAD 8
#define LEN_MAX_GRAD 5
#define INTERVAL_MAX_GRAD 10
#define METEOR_MAX_NUM (5*10)
//-------------Global Variables-------------
METEOR code MeteorTable[METEOR_MAX_NUM] = {
{1,40}, {1,50}, {1,60}, {1,70}, {1,80},
{2,15}, {2,20}, {2,20}, {2,25}, {2,30},
{3,10}, {3,12}, {3,15}, {3,17}, {3,20},
{4,7}, {4,10}, {4,13}, {4,17}, {4,20},
{5,5}, {5,8}, {5,11}, {5,4}, {5,18},
{6,4}, {6,7}, {6,10}, {6,13}, {6,16},
{7,4}, {7,6}, {7,8}, {7,10}, {7,12},
{8,2}, {8,4}, {8,7}, {8,9}, {8,9},
{9,1}, {9,3}, {9,5}, {9,7}, {9,8},
{10,1}, {10,3}, {10,5}, {10,6}, {10,7}
};
unsigned char code DispTable[LEN_MAX_GRAD] = {0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
//length table, 4 grads of length
unsigned char code IntervalTable[INTERVAL_MAX_GRAD] = {20, 40, 60, 80, 100, 120, 140, 160, 180, 200};
//interval table
unsigned char FlagRandStarted;
unsigned char RAND_SEED; //the random seed, to generate a random number
unsigned char Cnt10ms, Cnt10us;
#define CNT10MS 20000
#define CNT1US 35
//-------------Function define-------------
void SPI_SendWord(unsigned int);
/*********************************************************************************************************
** Function : Delay
** Input : t
** Output : none
** Return : none
** Description : Delay. soft delay
**
*********************************************************************************************************/
void Delay(uchar t)
{
uint j;
while(t--){
j = 1000;
while(j--);
}
}
/*********************************************************************************************************
** Function : RandomStart
** Input : none
** Output : none
** Return : none
** Description : Initialize the random seed, select TIMER0 as the source
**
*********************************************************************************************************/
void RandomStart(void)
{
char i;
FlagRandStarted = 0;
TL0 = 0;
TH0 = 0;
RAND_SEED = 0;
TR0 = 1; //startup TIMER0
IT1 = 1; //falling edge active (edge triggered)
EX1 = 1;
EA = 1;
i = 0;
while(!FlagRandStarted){
Delay(1);
SPI_SendWord(0x0000);
if(++i>100){ //超時,沒有RC充電電路
RAND_SEED = TL0;
SPI_SendWord(0xFFFF);
Delay(50);
break;
}
}
//RAND_SEED = 11;
EX1 = 0;
EA = 0;
TR0 = 0; //stop TIMER0
}
/*********************************************************************************************************
** Function : ISR_INT1
** Input : none
** Output : none
** Return : none
** Description : Interrupt Serve Routine for External Interrupt 1.
** use for initialize the random seed with TL0
**
*********************************************************************************************************/
void ISR_INT1(void) interrupt 2
{
RAND_SEED = TL0; //initialize the random seed
FlagRandStarted = 1;
}
/*********************************************************************************************************
** Function : Random
** Input : none
** Output : none
** Return : A random number
** Description : Get a random number, 8 bit integer
**
*********************************************************************************************************/
unsigned char Random(void)
{
//RAND_SEED = TL0;
RAND_SEED = RAND_SEED*13 + 3;
return(RAND_SEED);
}
/*********************************************************************************************************
** Function : Port_Init
** Input : none
** Output : none
** Return : none
** Description : Initialize the IO port
**
*********************************************************************************************************/
void Port_Init(void)
{
LATCH = 0;
CLK = 0;
SDA = 0;
}
/*********************************************************************************************************
** Function : Delay10ms
** Input : t
** Output : none
** Return : none
** Description : Delay 10*t ms. Use TIMER1, Mode 1(16 bit)
**
*********************************************************************************************************/
void Delay10ms(uchar t)
{
if(t==0) return;
Cnt10ms = t;
TH1 = (65536-CNT10MS)/256; // 8MHz,1T,8000個時鐘周期,定時時間為1ms
TL1 = (65536-CNT10MS)%256;
TF1 = 0;
TR1 = 1; // 開定時器
ET1 = 1; // 允許定時器1中斷
while(Cnt10ms);
TR1 = 0; // 關定時器1
ET1 = 0; // 禁止定時器1中斷
}
/*********************************************************************************************************
** Function : Delay10us
** Input : t
** Output : none
** Return : none
** Description : Delay 10*t us. Use TIMER0, Mode 2(8 bit autoload)
**
*********************************************************************************************************/
void Delay10us(uchar t)
{
if(t==0) return;
Cnt10us = t;
TH0 = (256-CNT1US); // 2MHz,1T,80個時鐘周期,定時時間為10us
TF0 = 0;
TR0 = 1; // 開定時器
ET0 = 1; // 允許定時器0中斷
while(Cnt10us);
TR0 = 0; // 關定時器0
ET0 = 0; // 禁止定時器0中斷
}
/*********************************************************************************************************
** Function : ISR_Timer0
** Input : none
** Output : none
** Return : none
** Description : Interrupt Serve Routine for TIMER0.
** TIMER0 config as Mode 2(8 bit autoload), clock is
**
*********************************************************************************************************/
void ISR_Timer0(void) interrupt 1
{
TF0 = 0;
if(Cnt10us>0){
Cnt10us--;
}
}
/*********************************************************************************************************
** Function : ISR_Timer1
** Input : none
** Output : none
** Return : none
** Description : Interrupt Serve Routine for TIMER1.
** TIMER1 config as Mode 1(16 bit), clock is
**
*********************************************************************************************************/
void ISR_Timer1(void) interrupt 3
{
TF1 = 0;
TH1 = (65536-CNT10MS)/256; //8MHz,1T,8000個時鐘周期,定時時間為1ms
TL1 = (65536-CNT10MS)%256;
if(Cnt10ms>0){
Cnt10ms--;
}
}
/*********************************************************************************************************
** Function : Timer_Init
** Input : none
** Output : none
** Return : none
** Description : Initialize the timers(TIMER0 and TIMER1)
**
*********************************************************************************************************/
void Timer_Init(void)
{
//AUXR |= 0xC0; //T0,T1速度為12倍標準51
TMOD |= 0x12; // 定時器0為8位自動重裝計數器,定時器1為16位計數器
//TF0 = 0;
//TF1 = 0;
//TR0 = 1; // 開定時器
//ET0 = 1; // 允許定時器0中斷
//ET1 = 1; // 允許定時器1中斷
}
/*********************************************************************************************************
** Function : SPI_SendWord
** Input : Data -> data to be sent
** Output : none
** Return : none
** Description : Send a 16 bit data by the SPI interface(soft SPI)
**
*********************************************************************************************************/
void SPI_SendWord(uint Data)
{
uchar i, Buf;
LATCH = 0;
Buf = (uchar)(Data>>8); //High byte
for(i = 0; i < 8; i++){
CLK = 0;
if(Buf & 0x80) {
SDA = 1;
} else {
SDA = 0;
}
CLK = 1;
Buf <<= 1;
NOP();
}
Buf = (uchar)Data; //Low byte
for(i = 0; i < 8; i++){
CLK = 0;
if(Buf & 0x80) {
SDA = 1;
} else {
SDA = 0;
}
CLK = 1;
Buf <<= 1;
NOP();
}
LATCH = 1;
}
#define Tmax 4
/*********************************************************************************************************
** Function : Flash
** Input : none
** Output : none
** Return : none
** Description : Display one time of meteor falling
**
*********************************************************************************************************/
void Flash(void)
{
char i, j, k;
unsigned char dT, DelayMax;
unsigned char Speed, Len; //the fall speed and the length of meteor
unsigned char FlagOver;
unsigned int DispBuf;
unsigned char BitDelay[16], DelayBuf[16];
i = Random() % METEOR_MAX_NUM;
Len = MeteorTable[i].MeteorLen; //get the falling speed of meteor
Speed = MeteorTable[i].Speed;
/*******************
Len = 3;
Speed = 10; */
/********************/
DelayMax = Len*Tmax; //????
for(i = 0; i < 16; i++){
BitDelay[i] = 0;
}
BitDelay[0] = DelayMax;
if(Len == 1){
dT = Tmax - 1;
} else {
dT = Tmax;
}
//dT = 5;
FlagOver = 0;
while(1){
for(j = 0; j < 16; j++){
if(BitDelay[j] > 0){
BitDelay[j]--;
}
}
//for(j = 0; j < 16; j++){ //注意數組越界
for(j = 0; j < 15; j++){
if( BitDelay[j] == DelayMax-dT){
BitDelay[j+1] = DelayMax; //觸發下一位
}
DelayBuf[j] = BitDelay[j];
}
DelayBuf[15] = BitDelay[15];
if(BitDelay[15] == DelayMax){ //MSB開始點亮
FlagOver = 1;
}
if(FlagOver & (BitDelay[15] == 0)){ //MSB熄滅
break;
}
for(j = 0; j < DelayMax; j++){
DispBuf = 0;
for(k = 0; k < 16; k++){
if(DelayBuf[k]>0){
DelayBuf[k]--;
DispBuf |= (1 << k);
}
}
SPI_SendWord(DispBuf);
Delay10us(Speed); //control the falling speed of meteor
}
}
SPI_SendWord(0x0000); //clear display
}
/*********************************************************************************************************
** Function : IntervalBetweenFlash
** Input : none
** Output : none
** Return : none
** Description : Delay a certain time between two flash
**
*********************************************************************************************************/
void IntervalBetweenFlash(void)
{
unsigned char i;
unsigned char Interval; //the interval between the two meteor-falling
i = Random() % INTERVAL_MAX_GRAD; //get the index of the interval table
Interval = IntervalTable[i]; //40~200
Delay10ms(Interval);
Delay10ms(Interval);
}
/*********************************************************************************************************
** Function : main
** Input : none
** Output : none
** Return : none
** Description : the main function that is a endless loop
**
*********************************************************************************************************/
void main(void)
{
RandomStart();
Port_Init();
SPI_SendWord(0x0000); //Clear display
Timer_Init();
EnableInterrupt();
while(1)
{
Flash();
IntervalBetweenFlash();
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -