LED搖搖棒很好地利用了人眼的視覺暫留特性。下圖是基于51單片機控制、32只高亮度LED發(fā)光LED構(gòu)成的搖搖棒,配合手的左右搖晃就可呈現(xiàn)一幅完整的畫面,可以顯示字符、圖片等。演示效果見自制LED搖搖棒效果展示圖
黑暗條件下拍攝的效果圖片:
基本原理與硬件電路設(shè)計:
32只LED發(fā)光管作為畫面每一列的顯示,左右搖晃起到了掃描的作用,人眼的視覺暫留現(xiàn)象使得看到的是一幅完整的畫面。與LED點陣的顯示有幾分相仿。
硬件電路如下圖(點擊可放大) 由于上傳不上去我畫的圖,所以就截圖分享一下!
水銀開關(guān)的作用:棒在搖動時,只能在朝某一方向搖動時顯示,否則會出現(xiàn)鏡像字或者鏡像畫面,所以采用接一支水銀開關(guān)來進行控制,使搖搖棒在搖動過程時將內(nèi)容顯示出來。
硬件制作:包含單片機、PCB板、32個高亮藍光LED、電池盒、震動開關(guān)、輕觸按鍵、3pin插針(預留的程序下載接口)
水銀開關(guān)里的水銀珠很活躍,導致在接通時容易產(chǎn)生抖動,所以將水銀開關(guān)斜向上放置(尖尖朝斜上方45°角),靠水銀珠自身重力的作用減少抖動。
IC座里面隱藏元件,既美觀又能保護元件:
軟件設(shè)計:
/****************************************************************************************
/*描 述: 搖搖棒程序,通過滾珠開關(guān)檢測周期,搖動時間自適應,圖像始終保持在中間。開機后每搖晃10次切換下一組字模
/* 按了一下按鍵后變成了手動切換,直到回到第一組字的時候再自動切換
最后祝各位制作成功!學習進步!
/*****************************************************************************************/
#include
/*********外部接口定義**********/
#define uchar unsigned char
#define uint unsigned int //宏定義
#define out P1 //數(shù)據(jù)輸出端口
sbit led1=P3^0; //第1組LED
sbit led2=P3^1; //第2組LED
sbit led3=P3^3; //第3組LED
sbit led4=P3^4; //第4組LED
sbit key1=P3^5; //按鍵輸入
sbit p3_2=P3^2;
uchar KY,num; //KY作用在后面說明
uchar BUFF; //緩存
/*********全局變量定義**********/
unsigned long int TimeCount=0;
unsigned int DelayN=80, //延時臨時計數(shù)
DelayTime=80; //每次延時的周期個數(shù)
unsigned char key,keyy;
/**********************************************/
void delay(unsigned char n);
void DelayMs(void);
/*******************************************/
unsigned char code text0[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",0*/
0x20,0x00,0x20,0x80,0x20,0x80,0x20,0x46,0xA0,0x45,0x70,0x28,0x2F,0x28,0x20,0x10,0x20,0x18,0x20,0x26,0xE0,0x21,0x20,0x40,0x20,0x80,0x20,0x00,0x20,0x00,0x00,0x00,/*"女",1*/
0x08,0x02,0x08,0x01,0x89,0x00,0xEE,0xFF,0x98,0x00,0x00,0x03,0x00,0x00,0xF8,0x1F,0x88,0x08,0x88,0x08,0xFF,0xFF,0x88,0x08,0x88,0x08,0xF8,0x1F,0x00,0x00,0x00,0x00,/*"神",2*/
0x80,0x40,0x40,0x40,0x30,0x42,0x1E,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0xFF,0x7F,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x40,0x00,0x40,0x00,0x00,/*"生",0*/
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x82,0x40,0x82,0x40,0x82,0x40,0x82,0x40,0x82,0x40,0x82,0x40,0x82,0x40,0xFE,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"日",1*/
0x00,0x01,0xE0,0x00,0x00,0x00,0xFF,0xFF,0x10,0x00,0x20,0x81,0x08,0x41,0x08,0x31,0x08,0x0D,0xFF,0x03,0x08,0x0D,0x08,0x31,0xF8,0x41,0x00,0x81,0x00,0x81,0x00,0x00,/*"快",2*/
0x00,0x00,0x00,0x20,0xE0,0x10,0x9C,0x08,0x84,0x06,0x84,0x40,0x84,0x80,0xF4,0x7F,0x82,0x00,0x82,0x00,0x83,0x02,0x82,0x04,0x80,0x08,0x80,0x30,0x00,0x00,0x00,0x00,/*"樂",3*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",3*/
};
unsigned char code text1[]={
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*" ",0*/
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*" ",1*/
0xF7,0xFD,0xF7,0xFE,0x76,0xFF,0x31,0x00,0x57,0xFF,0xE7,0x7C,0xFF,0xBF,0x01,0xCF,0x7D,0xF0,0x7D,0xFF,0x7D,0xFF,0x7D,0x80,0x01,0x7F,0xFF,0x7F,0xFF,0x0F,0xFF,0xFF,/*"祝",2*/
0x7F,0xFF,0xBF,0xFF,0x0F,0x80,0xD3,0xFF,0xBC,0xEF,0xDF,0xF3,0x67,0xFC,0xF0,0xDE,0xF5,0xBF,0x17,0xC0,0xF7,0xFF,0x77,0xFF,0xD7,0xFC,0xE3,0xE3,0xF7,0xF7,0xFF,0xFF,/*"你",3*/
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*" ",4*/
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*" ",5*/
0xFF,0xFF,0xBF,0x7F,0xBD,0xBF,0xBD,0xDF,0xBD,0xEF,0xBD,0xF7,0xBD,0xF9,0x01,0xFE,0xBD,0xFD,0xBD,0xFB,0xBD,0xF7,0xBD,0xEF,0xBD,0xCF,0xBD,0x9F,0xBF,0xDF,0xFF,0xFF,/*"天",6*/
0xFF,0xFF,0xBF,0x7F,0xBD,0xBF,0xBD,0xDF,0xBD,0xEF,0xBD,0xF7,0xBD,0xF9,0x01,0xFE,0xBD,0xFD,0xBD,0xFB,0xBD,0xF7,0xBD,0xEF,0xBD,0xCF,0xBD,0x9F,0xBF,0xDF,0xFF,0xFF,/*"天",7*/
0xBF,0xFF,0xBD,0xBF,0xBD,0xDF,0xBD,0xEF,0xBD,0xF3,0x01,0xFC,0xBD,0xFF,0xBD,0xFF,0xBD,0xFF,0xBD,0xFF,0x01,0x80,0xBD,0xFF,0xBD,0xFF,0xBD,0xFF,0xBD,0xFF,0xFF,0xFF,/*"開",8*/
0xFF,0xFB,0x7F,0xFC,0xFF,0xFF,0xFF,0xFF,0x0F,0xC0,0xFF,0xBF,0xFE,0xBF,0xFD,0xBF,0xE3,0xBF,0xF7,0xBF,0xFF,0xBF,0xBF,0x87,0x7F,0xFF,0xFF,0xF8,0xFF,0xFD,0xFF,0xFF,/*"心",9*/
};
unsigned char code text2[]={
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFF,0x9F,0xF9,0xFF,0xFF,0x9F,0xF9,0xFF,0xFF,0x9F,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0xF9,0xFF,0xFF,0x9F,
0xF9,0xFF,0xFF,0x9F,0xF9,0xFF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x87,0xFF,0xFF,0xFF,0x01,0xFE,0xFF,
0x7F,0x00,0xF8,0xFF,0x3F,0x00,0xF0,0xFF,0x1F,0x00,0xE0,0xFF,0x0F,0x00,0xC0,0xFF,0x07,0x00,0x80,0xFF,0x03,0x00,0x00,0xFF,0x03,0x00,0x00,0xFF,0x03,0x00,0x00,0xFE,
0x03,0x00,0x00,0xFC,0x03,0x00,0x00,0xF8,0x07,0x00,0x00,0xF0,0x0F,0x00,0x00,0xE0,0x1F,0x00,0x00,0xE0,0x3F,0x00,0x00,0xC0,0x3F,0x00,0x00,0x80,0x1F,0x00,0x00,0xC0,
0x0F,0x00,0x00,0xE0,0x07,0x00,0x00,0xF0,0x03,0x00,0x00,0xF8,0x03,0x00,0x00,0xFC,0x03,0x00,0x00,0xFE,0x03,0x00,0x00,0xFF,0x07,0x00,0x80,0xFF,0x0F,0x00,0xC0,0xFF,
0x1F,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0xFF,0x00,0xF8,0xFF,0xFF,0x01,0xFC,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x07,0x00,0x00,0xE0,0x07,0x00,0x00,0xC0,0x07,0x00,0x00,0xC0,0xFF,0xFF,0xFF,0xC7,0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0xCF,
0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0xC7,0x07,0x00,0x00,0xC0,0x07,0x00,0x00,0xC0,0x07,0x00,0x00,0xE0,0xFF,0xFF,0xFF,0xFF,/*"未命名文件",0*/
};
unsigned char code text3[]={
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*" ",0*/
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*" ",1*/
0x00,0x08,0x00,0x04,0x00,0x03,0xE0,0x00,0x00,0x00,0x00,0x40,0x00,0x80,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x40,0x00,0x80,0x01,0x00,0x0E,0x00,0x00,/*"小",0*/
0x10,0x04,0x60,0x04,0x02,0x7E,0x8C,0x01,0x00,0x00,0x44,0x00,0x54,0xFF,0x54,0x15,0x54,0x15,0x7F,0x15,0x54,0x55,0x54,0x95,0x54,0x7F,0x44,0x00,0x40,0x00,0x00,0x00,/*"清",1*/
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*" ",4*/
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*" ",5*/
0x40,0x20,0x44,0x12,0x54,0x4A,0x65,0x82,0xC6,0x7F,0x64,0x02,0x54,0x0A,0x44,0x92,0x00,0x60,0xFC,0x1F,0x44,0x00,0x44,0x00,0xC4,0xFF,0x42,0x00,0x40,0x00,0x00,0x00,/*"新",2*/
0x40,0x00,0x40,0x40,0x42,0x20,0xCC,0x1F,0x00,0x20,0x88,0x40,0x89,0x50,0x8E,0x48,0x88,0x46,0xF8,0x41,0x88,0x42,0x8C,0x44,0x8B,0x58,0x88,0x40,0x80,0x40,0x00,0x00,/*"送",3*/
};
/***********n(us)延時子程序***************/
void DelayUs(uint N)
{
uint x;
for(x=0; x<=N;x++);
}
/******************************************/
void main()
{
AUXR=0x80;
CLK_DIV=0;
EX0=1; //開放外部中斷0
IT0=1; //中斷0為邊沿觸發(fā)方式
IP=0x02; //設(shè)置中斷優(yōu)先級
TMOD=0x02; //定時器0方式2,8位重裝載
TH0=0x80; //設(shè)定定時器初值
TL0=0x80;
KY=0;
EA=1; //開放中斷
ET0=1; //開放定時器0中斷
TR0=1; //啟動定時器0,開始計時*/
key=0; //初始化顯示第一組文字
keyy=0;
P1M0=0x55; //0101 0101 /P1.0 P1 .2 P1.4 P1.6推挽輸出
P1M1=0xAA;
while(1){//等待中斷
if(key1==0){ //有鍵按下
DelayUs(50);
if(key1==0){
key++; //更換下一幅圖片
if(key>2) key=0; //圖片循環(huán)顯示 根據(jù)顯示的組數(shù)來定義 這里有9組 所以就要keyy>9
while(key1==0); //等待按鍵釋放
}
}
if(num>10) //每中斷10次切換
{
keyy++;
num=0;
}
if(keyy>2)keyy=0; //圖片循環(huán)顯示 根據(jù)顯示的組數(shù)來定義 這里有9組 所以就要keyy>9
}
}
/*********文字顯示子程序**********/
void display_word(unsigned char code *text)
{
unsigned char i,j=2; //j為圖片起始位置 3 為第3個開始是圖片 如果要顯示高時32的大字 也屬于圖片格式
DelayUs(6300);
for(i=0;i<64;i++)
{
P3M0=0x00; //0000 0000 //P3.0推挽輸出 P3 .1 P3.3 P3.4輸入高阻
P3M1=0x1B;
if((key>=j)||(keyy>=j))
BUFF=(*(text+i*4+3));
else
BUFF=(*(text+128+i*2+1));
led4=0;
P1=~BUFF>>1;
P3M0=0x10; //0001 0000 //P3.4推挽輸出 P3 .0 P3.3 P3.1輸入高阻
P3M1=0x0B; //0000 1011
delay(1);
P3M0=0x00; //0000 0000 //P3.0推挽輸出 P3 .1 P3.3 P3.4輸入高阻
P3M1=0x1B; //0001 1011
led4=1;
P1=BUFF; //01010101 1357
P3M0=0x10; //0001 0000 //P3.4推挽輸出 P3 .0 P3.3 P3.1輸入高阻
P3M1=0x0B; //0000 1011
delay(1);
P3M0=0x00; //0000 0000 //P3.0推挽輸出 P3 .1 P3.3 P3.4輸入高阻
P3M1=0x1B; //0001 1011
if((key>=j)||(keyy>=j))
BUFF=(*(text+i*4+2));
else
BUFF=(*(text+128+i*2));
led3=0;
P1=~BUFF>>1;
P3M0=0x08; //0000 1000 //P3.3推挽輸出 P3 .0 P3.1 P3.4輸入高阻
P3M1=0x13; //0001 0011
delay(1);
P3M0=0x00; //0000 0000 //P3.0推挽輸出 P3 .1 P3.3 P3.4輸入高阻
P3M1=0x1B; //0001 1011
led3=1;
P1=BUFF; //01010101 1357
P3M0=0x08; //0000 1000 //P3.3推挽輸出 P3 .0 P3.1 P3.4輸入高阻
P3M1=0x13; //0001 0011
delay(1);
P3M0=0x00; //0000 0000 //P3.0推挽輸出 P3 .1 P3.3 P3.4輸入高阻
P3M1=0x1B;
if((key>=j)||(keyy>=j))
BUFF=(*(text+i*4+1));
else
BUFF=(*(text+i*2+1));
led2=0;
P1=~BUFF>>1;
P3M0=0x02; //0000 0010 //P3.1推挽輸出 P3 .0 P3.3 P3.4輸入高阻
P3M1=0x19; //0001 1001
delay(1);
P3M0=0x00; //0000 0000 //P3.0推挽輸出 P3 .1 P3.3 P3.4輸入高阻
P3M1=0x1B; //0001 1011
led2=1;
P1=BUFF; //01010101 1357
P3M0=0x02; //0000 0010 //P3.1推挽輸出 P3 .0 P3.3 P3.4輸入高阻
P3M1=0x19; //0001 1001
delay(1);
P3M0=0x00; //0000 0000 //P3.0推挽輸出 P3 .1 P3.3 P3.4輸入高阻
P3M1=0x1B; //0001
if((key>=j)||(keyy>=j))
BUFF=(*(text+i*4));
else
BUFF=(*(text+i*2));
led1=0;
P1=~BUFF>>1;
P3M0=0x01; //0000 0001 //P3.0推挽輸出 P3 .1 P3.3 P3.4輸入高阻
P3M1=0x1A; //0001 1010
delay(1);
P3M0=0x00; //0000 0000 //P3.0推挽輸出 P3 .1 P3.3 P3.4輸入高阻
P3M1=0x1B; //0001 1011
led1=1;
P1=BUFF; //01010101 1357
P3M0=0x01; //0000 0001 //P3.0推挽輸出 P3 .1 P3.3 P3.4輸入高阻
P3M1=0x1A; //0001 1010
delay(1);
} }
/*********顯示內(nèi)容選擇子程序**********/
void display(unsigned char t)
{ keyy=0;
switch (t){ //通過按鍵選擇顯示內(nèi)容
case 0: {display_word(text0);}break;
case 1: {display_word(text1);}break;
case 2: {display_word(text2);}break;
case 3: {display_word(text3);}break;
// case 4: {display_word(text4);}break;
// case 5: {display_word(text5);}break;
// case 6: {display_word(text6);}break;
// case 7: {display_word(text7);}break;
// case 8: {display_word(text8);}break;
// case 9: {display_word(text9);}break;
// case 10:{display_word(text10);}break;
//default:{display_word(text1);}
}}
/*****************************************/
void display1(unsigned char y)
{
switch (y){ //通過按鍵選擇顯示內(nèi)容
case 0: {display_word(text0);}break;
case 1: {display_word(text1);}break;
case 2: {display_word(text2);}break;
case 3: {display_word(text3);}break;
// case 4: {display_word(text4);}break;
// case 5: {display_word(text5);}break;
// case 6: {display_word(text6);}break;
// case 7: {display_word(text7);}break;
// case 8: {display_word(text8);}break;
// case 9: {display_word(text9);}break;
// case 10:{display_word(text10);}break;
}
}
/***************************************/
/*********延時子程序**********/
void delay(unsigned char n)
{
for(;n>0;n--){
DelayN=DelayTime;
while (DelayN);
}
}
/*********中斷子程序**********/
void int0() interrupt 0 //使用外部中斷0
{
KY=~KY;
if(KY==0)
{
DelayTime=TimeCount/1580;
TimeCount=0; //延時周期計數(shù)清零
if(key==0)
{
num++;
display1(keyy); //根據(jù)按鍵選擇循環(huán)顯示文字
}
else
{
display(key); //根據(jù)按鍵選擇循環(huán)顯示文字
}
}
}
void timer0() interrupt 1 //定時器0中斷子程序
{
TimeCount++;
if (DelayN!=0)
DelayN--;
}
最后別的不多說了,自己剛剛學習,希望大家可以多多給予小清新同學在學習上面的幫助,十分感謝各位!