1. 程式人生 > >工程師表白神器--炫彩心形DIY

工程師表白神器--炫彩心形DIY

這段時間做了個玩具,用彩色LED搭建了一個心形圖案,並用STC51微控制器驅動,實現心形LED炫彩閃動,超級炫酷的,總工有32個燈,使用了微控制器的所有IO口,可以靈活控制每個LED的閃爍,然後配上適合的音樂,絕對是屌絲工程師表白神器,先上兩張圖看看:



接下來簡單說下實現過程:

將32個LED分成4組LED_P0,LED_P1,LED_P3,LED_P2,每一組代表8個LED燈,也就是講心形分成4個部分, 如下圖所示,這樣,我們只需操作這些值,然後將這些值對應到相應的IO口上就可以了


為了便於操作,我們對每一組單獨做了幾個動作,然後將這些動作已多種方式結合起來,就可以啦。

基本動作:

uchar code table0[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//LED從低位往高位移
uchar code table1[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//LED從高位往低位移
uchar code table2[]={0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00};//LED從1個亮到8個都點亮(從低位往高位)
uchar code table3[]={0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x00};//LED從1個亮到8個都點亮(從高位往低位)
uchar code table4[]={0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};//LED從8個全亮到一個都不亮(從低位往高位)
uchar code table5[]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};//LED從8個全亮到一個都不亮(從高位往低位)
uchar code table6[]={0xfe,0xfc,0xfa,0xf6,0xee,0xde,0xbe,0x7e};//LED從低位往高位移(最低位始終為0)
uchar code table7[]={0x7f,0x3f,0x5f,0x6f,0x77,0x7b,0x7d,0x7e};//LED從高位往低位移(最高位始終為0)

下面我們將LED順時針旋轉一週,如下:
void disp1()			
{
	for(i=0;i<8;i++)
	{
		LED_P2=table1[i];
		Display(100);
	}
	LED_P2=0xff;
	for(i=0;i<8;i++)
	{
		LED_P3=table1[i];
		Display(100);
	}
	LED_P3=0xff;
	for(i=0;i<8;i++)
	{
		LED_P1=table1[i];        
		Display(100);
	}
	LED_P1=0xff;
	for(i=0;i<8;i++)
	{
		LED_P0=table1[i];
		Display(100);
	}
	LED_P0=0xff;
}

為了方便佈線,我們的LED燈的位置並不是個微控制器IO口嚴格對應的,所以我們要在顯示函式裡面做好對應關係,一起重新整理顯示:
//將LED_P0,LED_P1,LED_P3,LED_P2的值的對應到具體IO口上,並延時
void Display(uint time)	
{
	P0 = ((LED_P0 & 0xfe)>>1) + ((LED_P1 & 0x01)<<7);
	
	P1 = ((LED_P1 & 0xfe)>>1) + ((LED_P3 & 0x01)<<7);
	
	P3 = ((LED_P3 & 0xfe)>>1) + ((LED_P2 & 0x01)<<7);
	
	P2 = ((LED_P2 & 0xfe)>>1) + ((LED_P0 & 0x01)<<7);
	
	Delayms(time);
}

將LED順時針旋轉一週只是一週場景,這裡可以t提供40多種場景,可以自由搭配順序哦,實現方法也是很簡單的:
#define SCENE_COUNT 20//定義迴圈播放發的數量

//可自定義場景,按場景順序播放多種狀態
uchar scene[SCENE_COUNT] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};

選擇要顯示的場景函式:
void DispStatus(unsigned char index)
{
	switch(index)
	{
		case 0	:disp0()	;	break;
		case 1	:disp1()	;	break;
		case 2	:disp2()	;	break;
		case 3	:disp3()	;	break;
		case 4	:disp4()	;	break;
		case 5	:disp5()	;	break;
		case 6	:disp6()	;	break;
		case 7	:disp7()	;	break;
		case 8	:disp8()	;	break;
		case 9	:disp9()	;	break;
		case 10	:disp10()	;	break;
		case 11	:disp11()	;	break;
		case 12	:disp12()	;	break;
		case 13	:disp13()	;	break;
		case 14	:disp14()	;	break;
		case 15	:disp15()	;	break;
		case 16	:disp16()	;	break;
		case 17	:disp17()	;	break;
		case 18	:disp18()	;	break;
		case 19	:disp19()	;	break;
		case 20	:disp20()	;	break;
		case 21	:disp21()	;	break;
		case 22	:disp22()	;	break;
		case 23	:disp23()	;	break;
		case 24	:disp24()	;	break;
		case 25	:disp25()	;	break;
		case 26	:disp26()	;	break;
		case 27	:disp27()	;	break;
		case 28	:disp28()	;	break;
		case 29	:disp29()	;	break;
		case 30	:disp30()	;	break;
		case 31	:disp31()	;	break;
		case 32	:disp32()	;	break;
		case 33	:disp33()	;	break;
		case 34	:disp34()	;	break;
		case 35	:disp35()	;	break;
		case 36	:disp36()	;	break;
		case 37	:disp37()	;	break;
		case 38	:disp38()	;	break;
		case 39	:disp39()	;	break;
		case 40	:disp40()	;	break;
		case 41	:disp41()	;	break;
		default: break;		
	}
}

主函式迴圈播放設定好的場景
void main()
{	
	int i;
	while(1)
	{
		//按照自定義場景迴圈播放
		for(i=0;i<SCENE_COUNT;i++)
		{
			DispStatus(scene[i]);
		}
	}
}

這樣一個表白神器就完成了,有需要的或者有其他問題的親猿們,如果有需要可以直接評論我就好了哦。