🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
向左和右移动的LED,硬件一样,软件不同,这个通常的单片机教程成为跑马灯或者流水灯的实验,是一个LED学习的经典范例,注意阅读程序(左移和右移的实现方式是不一样的,之所以给出多种实现方式是因为希望大家练习C语言的基本语法)。请大家思考如果要实现更复杂的移动效果,比如由中间向两边扩散,或者相反如何由程序实现?你认为哪种实现方式比较好?占用内存和实现多种图案两方面考虑: ![](https://img.kancloud.cn/af/f9/aff94bdf943f32c492176f9ef5506d9b_795x756.png) 左移 ``` char OneBit=0b00000001; int Show,i,j; void setup() { pinMode(13, OUTPUT); pinMode(12, OUTPUT); pinMode(11, OUTPUT); pinMode(10, OUTPUT); pinMode(9, OUTPUT); pinMode(8, OUTPUT); pinMode(7, OUTPUT); pinMode(6, OUTPUT); } void WriteBit(char XX) { for (i=13;i>5;i--) { j=i-6; Show=bitRead(OneBit,j); if(Show==0) { digitalWrite(i, LOW); } else { digitalWrite(i,HIGH); } } } void loop() { WriteBit(OneBit); delay(1000); // Wait for 1000 millisecond(s) OneBit=OneBit<<1; if(OneBit==0) OneBit=0b00000001; } ``` 右移动,用二维数组实现 ``` const char Map[8][8]={{0,0,0,1,1,0,0,0}, {0,0,1,1,1,1,0,0}, {0,1,1,1,1,1,1,0}, {1,1,1,1,1,1,1,1}, {0,1,1,1,1,1,1,0}, {0,0,1,1,1,1,1,0}, {0,0,0,1,1,1,0,0}, {0,0,0,0,1,0,0,0}}; int i=0,j,k; void WritePort(const char *MapStart) { for (j=13;j>5;j--) { k=*MapStart; digitalWrite(j,k); MapStart++; } } void setup() { pinMode(13, OUTPUT); pinMode(12, OUTPUT); pinMode(11, OUTPUT); pinMode(10, OUTPUT); pinMode(9, OUTPUT); pinMode(8, OUTPUT); pinMode(7, OUTPUT); pinMode(6, OUTPUT); } void loop() { WritePort(&Map[i][0]); delay(1000); // Wait for 1000 millisecond(s) i++; if(i>7) i=0; } ``` 右移动,用一维数组实现 ``` const char Map[8]={0b10000000,0b01000000,0b00100000,0b00010000, 0b00001000,0b00000100,0b00000010,0b00000001}; int i=0,j,k,Temp; void WritePort(const char MapStart) { for (j=13;j>5;j--) { k=j-6; Temp=bitRead(MapStart,k); digitalWrite(j,Temp); } } void setup() { for (j=13;j>5;j--) pinMode(j, OUTPUT); } void loop() { WritePort(Map[i]); delay(1000); // Wait for 1000 millisecond(s) i++; if(i>7) i=0; } ``` 矩阵LED是一种更为复杂的LED显示器材,有排成矩阵方式的二维LED(一般是8*8,即64个LED组成)。如果让Arduino直接驱动64个LED则它的数字管脚和模拟管脚加起来都不够用。而聪明的工程师想出了一种巧妙的方式解决了这个问题。其原理就是利用人类的视觉暂留效果实现了用很少的管脚控制了所有LED灯。实际上并不是所有的LED灯同时被控制,而是一列一列的依次被控制,轮换显示预定图案,而轮流所有的LED灯需要8次。如果我们轮流的时间足够块,则人类的研究就观察不到切换,而看到了所有LED灯组合而成的图案。所谓视觉暂留也可以这样理解,视网膜将光信号传递给视神经后,神经获得光信号,电位发生变化。光信号消失后电位变化有一个惯性,如果我们在信号消失后很快的再次输入光信号,则电信号持续存在了。我们就感觉不到光信号的消失。就好像电容的充放电有一个缓慢的过程一样。 LED_matrix的显示: ![](https://img.kancloud.cn/b8/e9/b8e99f25f2b55c39a96a5328365ff284_1759x719.png) ![](https://img.kancloud.cn/92/c0/92c0354c04455f2924d897d7704d8e95_1234x765.png) ``` #define ROW1 13 #define ROW2 12 #define ROW3 11 #define ROW4 10 #define ROW5 9 #define ROW6 8 #define ROW7 7 #define ROW8 6 #define COL1 5 #define COL2 4 #define COL3 3 #define COL4 2 #define COL5 A3 #define COL6 A2 #define COL7 A1 #define COL8 A0 const int row[] = {ROW1, ROW2, ROW3, ROW4, ROW5, ROW6, ROW7, ROW8}; const int col[] = {COL1,COL2, COL3, COL4, COL5, COL6, COL7, COL8}; int KARE1[8][8] = {{0,0,0,0,0,0,0,0}, {0,1,1,1,1,1,1,0}, {0,1,1,1,1,1,1,0}, {0,1,1,1,1,1,1,0}, {0,1,1,1,1,1,1,0}, {0,1,1,1,1,1,1,0}, {0,1,1,1,1,1,1,0}, {0,0,0,0,0,0,0,0}}; int KARE2[8][8] = {{1,1,1,1,1,1,1,1}, {1,0,0,0,0,0,0,1}, {1,0,1,1,1,1,0,1}, {1,0,1,1,1,1,0,1}, {1,0,1,1,1,1,0,1}, {1,0,1,1,1,1,0,1}, {1,0,0,0,0,0,0,1}, {1,1,1,1,1,1,1,1}}; int KARE3[8][8] = {{1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,0,0,0,0,1,1}, {1,1,0,1,1,0,1,1}, {1,1,0,1,1,0,1,1}, {1,1,0,0,0,0,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}}; int KARE4[8][8] = {{1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,0,0,1,1,1}, {1,1,1,0,0,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}}; void setup() { Serial.begin(9600); for (int i = 2; i <= 13; i++) { pinMode(i, OUTPUT); digitalWrite(i, LOW); } pinMode(A0, OUTPUT); digitalWrite(A0, LOW); pinMode(A1, OUTPUT); digitalWrite(A1, LOW); pinMode(A2, OUTPUT); digitalWrite(A2, LOW); pinMode(A3, OUTPUT); digitalWrite(A3, LOW); } void loop() { for (int c=0; c<22; c++){ drawScreen(KARE1); Serial.println(c); } delay(444); for (int c=0; c<22; c++){ drawScreen(KARE2); Serial.println(c); } delay(444); for (int c=0; c<22; c++){ drawScreen(KARE3); Serial.println(c); } delay(444); for (int c=0; c<22; c++){ drawScreen(KARE4); Serial.println(c); } delay(444); for (int c=0; c<22; c++){ drawScreen(KARE3); Serial.println(c); } delay(444); for (int c=0; c<22; c++){ drawScreen(KARE2); Serial.println(c); } delay(444); } void drawScreen(int letter[8][8]){ for (int r = 0; r < 8; r++){ digitalWrite(row[r], HIGH); } for (int c=0; c<8; c++){ digitalWrite(col[c], HIGH); for (int r = 0; r < 8; r++){ digitalWrite(row[r], letter[r][c]); delayMicroseconds(100); // delay(100); } delayMicroseconds(1000); digitalWrite(col[c], LOW); for (int r = 0; r < 8; r++){ digitalWrite(row[r], HIGH); // delayMicroseconds(100); //delay(100); } delayMicroseconds(1000); digitalWrite(col[c], LOW); } } ``` 其实控制矩阵LED也分为两种方式,行扫描和列扫描。就是分别点亮每一行,或者每一列。以行或者列为单位轮流。具体的硬件接法和编程需要细心,而LED也有所谓共阴和共阳的区别。希望大家仔细阅读相关文档,增加硬件知识,这样才能灵活的使用这些器件。