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

📄 meteor.c

📁 LED控制
💻 C
字号:
/****************************************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,14}, {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 + -