向左和右移动的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也有所谓共阴和共阳的区别。希望大家仔细阅读相关文档,增加硬件知识,这样才能灵活的使用这些器件。
- 序言
- 第一章 arduino简介和学习
- 第一节 arduino介绍
- 第二节 学习方法概述
- 第三节 计算机的智能
- 第二章 开始学习之旅
- 第一节 安装环境和购买硬件的说明
- 第二节 介绍一个具体的范例
- 第三章 分类官网教程讲解
- 第一节 Basics类的示例项目
- 第二节 数字端口的示例
- 第三节 模拟端口的示例
- 第四节 串口通信的示例
- 第五节 LED显示的示例
- 第六节 arduino处理矩阵键盘
- 第七节 LCD显示范例
- 第四章 综合实践项目制作教程
- 第一节 简单的计算器
- 第五章 复习题
- 单选题
- 编程题目
- 单选题答案
- 编程题答案
- 第1题
- 第2题
- 第3题
- 第4题
- 第5题
- 第6题
- 第7题
- 第8题
- 第9题
- 第10题
- 第11题
- 第12题
- 第13题
- 第14题
- 第15题
- 第16题
- 第17题
- 复习题包含翻译
- 第六章 快速复习
- 第一节 英文解说