Arduino教程(非常适合初学者)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Arduino教程一: 数字输出
Arduino, 教程11 Comments »
Arduino的数字I/O被分成两个部分,其中每个部分都包含有6个可用的I/O管脚,即管脚2到管脚7和管脚8到管脚13。
除了管脚13上接了一个1K的电阻之外,其他各个管脚都直接连接到ATmega上。
我们可以利用一个6位的数字跑马灯,来对Arduino数字I/O 的输出功能进行验证,以下是相应的原理图:
电路中在每个I/O管脚上加的那个1K电阻被称为限流电阻,
由于发光二极管在电路中没有等效电阻值,使用限流电阻可
以使元件上通过的电流不至于过大,能够起到保护的作用。
该工程对应的代码为:
int BASE = 2;
int NUM = 6;
int index = 0;
void setup()
{
for (int i = BASE; i < BASE + NUM; i ++)
{
pinMode(i, OUTPUT);
}
}
void loop()
{
for (int i = BASE; i < BASE + NUM; i ++) {
digitalWrite(i, LOW);
}
digitalWrite(BASE + index, HIGH);
index = (index + 1) % NUM;
delay(100);
}
下载并运行该工程,连接在Arduino数字I/O管脚2到管脚7上的发光二极管会依次点亮0.1秒,然后再熄灭:
这个实验可以用来验证数字I/O输出的正确性。
Arduino上一共有十二个数字I/O管脚,我们可以用同样的办法验证其他六个管脚的正确性,而这只需要对上述工程的第一行做相应的修改就可以了:
int BASE = 8;
SEP01
Arduino教程二: 数字输入
Arduino, 教程3 Comments »
在数字电路中开关(switch)是一种基本的输入形式,它的作用是保持电路的连接或者断开。
Arduino从数字I/O管脚上只能读出高电平(5V)或者低电平(0V),因此我们首先面临到的一个问题就是如何将开关的开/断状态转变成Arduino能够读取的高/低电平。
解决的办法是通过上/下拉电阻,按照电路的不同通常又可以分为正逻辑(Positive Logic)和负逻辑(Inverted Logic)两种。
在正逻辑电路中,开关一端接电源,另一端则通过一个10K的下拉电阻接地,输入信号从开关和电阻间引出。
当开关断开的时候,输入信号被电阻“拉”向地,形成低电平(0V);当开关接通的时候,输入信号直接与电源相连,形成高电平。
对于经常用到的按压式开关来讲,就是按下为高,抬起为低。
在负逻辑电路中,开关一端接地,另一端则通过一个
10K的上拉电阻接电源,输入信号同样也是从开关
和电阻间引出。
当开关断开时,输入信号被电阻“拉”
向电源,形成高电平(5V);当开关接通的时候,输
入信号直接与地相连,形成低电平。
对于经常用到的
按压式开关来讲,就是按下为低,抬起为高。
为了验证Arduino数字I/O的输入功能,我们可以将
开关接在Arduino的任意一个数字I/O管脚上(13除
外),并通过读取它的接通或者断开状态,来控制其
它数字I/O管脚的高低。
本实验采用的原理图如下所
示,其中开关接在数字I/O的7号管脚上,被控的发
光二极管接在数字I/O的13号管脚上:
Arduino教程三: 模拟输入
Arduino, 教程5 Comments »
Arduino的优势在于对数字信号的识别和处理,但我们所生活的真实世界并不是数字(digital)化的,简单到只要用0和1就能够表示所有的现象。
例如温度这一我们已经司空见惯的概念,它只能在一个范围之内连续变化,而不可能发生像从0到1这样的瞬时跳变,类似这样的物理量被人们称为是模拟(analog)的。
Arduino是无法理解这些模拟量的,它们必须在经过模数转换后变成数字量后,才能被Arduino进一步处理。
像温度这样的数据必须先被转换成微处理器能够处理的形式(比如电压),才能被Arduino处理,这一任务通常由各类传感器(sensor)来完成的。
例如,电路中的温度传感器能够将温度值转换成0V到5V间的某个电压,比如0.3V、3.27V、4.99V等。
由于传感器表达的是模拟信号,它不会像数字信号那样只有简单的高电平和低电平,而有可能是在这两者之间的任何一个数值。
至于到底有多少可能的值则取决于模数转换的精度,精度越高能够得到的值就会越多。
Arduino所采用的ATmega8微处理器一其有6个模数转换器(ADC,Analog to Digital Converter),每一个模数转换器的精度都是10bit,也就是说能够读取1024(2^10 = 1024)个状态。
在Arduino的每一个模拟输入管脚上,电压的变化范畴是从0V到5V,因此Arduino 能够感知到的最小电压变化是4.8毫伏(5/1024 = 4.8mV)。
电位计(potentiometer)是一种最简单的模拟输入设备,它实际上就是一个可变电阻箱,通过控制滑块所在的位置我们可以得到不同
的电压值,而输入信号正是从滑块所在的位置接入到电路中的。
这一实验我们将通过改变电位计的值来控制发光二极管闪烁的频率。
电位计上一共有三个管脚,分别连接到Arduino的电源、地和模拟输入的5号管脚上,发光二极管则连接到数字I/O的13号管脚上,原理图如下所示:
相应的代码为:
int ledPin = 13;
int potPin = 5;
int value = 0;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
value = analogRead(potPin);
digitalWrite(ledPin, HIGH);
delay(value);
digitalWrite(ledPin, LOW);
delay(value);
}
在Arduino中,对模拟输入端口不需要调用pinMode()函数将其指定为输入或者是输出模式,这点同数字I/O端口是有所不同的。
通过旋转电位计的轴,我们能改变电位计中间那根连线同地之间的电阻量,从而也就能改变从模拟输入的5号管脚上所读入的模拟量的值。
当电位计完全旋转到头时,输入到模拟输入管脚上的电压为0V,用analogRead()函数读出的值为0;当电位计完全旋转到另一头时,输入到模拟I/O管脚上的电压为5V,此时用analogRead()函数读出的值为1023;当电位计旋转到中间的某个位置时,输入到模拟输入管脚上的电压是0V到5V之间的某个值,而用analogRead()函数读出的则是位于0到1023之间的某个对应值。
读出的模拟量在我们的实验中被用来确定发光二极管点亮和熄灭的时间,以反映模拟量的变化。
电位计运用的是分压原理,通过旋转到不同的位置来得到不同的电压值。
从这
种意义上讲,它能够被用来对当前旋转到的位置进行度量,因此可以被用在转
向轮等旋转装置中。
今天发现PCB板上另外一个错误,就是将模拟输入对应管脚号标反了,试了
好久才意识到是这一问题。
加上之前电源设计上的两个小缺陷,一共有三个
需要修改的地方。
如果有机会再做PCB板的话,试着将这些问题解决一下:-)
相应的代码为:
int ledPin = 13;
int switchPin = 7;
int value = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(switchPin, INPUT);
}
void loop() {
value = digitalRead(switchPin);
if (HIGH == value) {
// turn LED off
digitalWrite(ledPin, LOW);
} else {
// turn LED on
digitalWrite(ledPin, HIGH);
}
}
由于采用的是负逻辑电路,开关按下时用digitalRead()函数读取到的值为LOW,此时再用digitalWrite()函数将发光二极管所在的管脚置为高,点亮发光二极管。
同理,当开关抬起时,发光二极管将被熄灭,这样我们就实现了用开关来控制发光二极管的功能。
Arduino教程四: 模拟输出
Arduino, 教程2 Comments »
就像模拟输入一样,在现实的物理世界中我们经常需要输出除了0和1之外的其他数值。
例如,除了想用微控制器找开或者关闭电灯之外,我们还会想控制灯光的亮度,这时就需要用到模拟输出。
由于Arduino的微控制器只能产生高电压(5V)或者低电压(0V),而不能产生变化的电压,因此必须采用脉宽度调制技术(PWM,Pulse Width Modulation)来模仿模拟电压。
PWM是一种开关式稳压电源应用,它是借助微处理器的数字输出来对模拟电路进行控制的一种非常用效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
简而言之,PWM是一种对模拟信号电平进行数字编码的方法,它通过对半导体开关器件的导通和关断进行控制,使输出端得到一系列幅值相等但宽度不相等的脉冲,而这些脉冲能够被用来代替正弦波或其它所需要的波形。
在Arduino数字I/O管脚9、10和11上,我们可以通过analogWrite()函数来产生模拟输出。
该函数有两个参数,其中第一个参数是要产生模拟信号的引脚(9、10或者11);第二个参数是用于产生模拟信号的脉冲宽度,取值范围是0到255。
脉冲宽度的值取0可以产生0V的模拟电压,取255则可以产生5V的模拟电压。
不难看出,脉冲宽度的取值变化1,产生的模拟电压将变化0.0196V(5/255 = 0.0196)。
本实验中我们将用模拟输出来调暗发光二极管(LED),由于正常情况下LED对电压的变化非常敏感,因此当脉冲宽度变化时人眼会感觉到LED实际上是在不断地熄灭和点亮,而不是逐渐变暗。
解决这一问题可以采用滤波电路,它能使有用频率信号通过而同时抑制(或大大衰减)无用频率信号。
实验中我们采用的是低通滤波器,它的原理非常简单,只需要一个电阻和一个电容,能够很好地过滤掉电路中超过某一频率的信号。
此处给出的电路并不能校平所有脉冲,它之所以被称为“低通滤波”是因为它只允许
频率低于某个限度的脉冲通过,对于高于这个限度的脉冲则被平衡为伪模拟电压,
滤波的频率范围由电阻器和电容器的比值决定。
实验中采用的电路原
理如下:
相应的代码为:
int potPin = 0;
int ledPin =
11;
byte bright_table[] = { 30, 30, 30, 40, 50,
60, 70, 80, 90, 100,110, 120, 130, 140, 150, 160,
170, 180, 190, 200, 210, 220, 230, 240, 250, 250,
240, 230, 220, 210, 200, 190, 180, 170, 160, 150,
140, 130, 120, 110, 100, 90, 80, 70, 60, 50,
40, 30, 30, 30 };
int MAX = 50;
int count = 0;
int val = 0;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
analogWrite(ledPin, bright_table[count]);
count ++;
if (count > MAX) {
count = 0;
}
val = analogRead(potPin);
val = val /4;
delay(val);
}
该工程调用analogWrite()函数在数字I/O端口的11号管脚上模仿模拟输出,每产生一次输出后都设置了相应的延时,而延时的长度由模拟输入端口0号管脚上的电位器来决定。
通过调整电位器的位置,我们可以观察到发光二极管逐渐变亮后再逐渐变暗的效果。
Arduino教程五: 串口输出
Arduino, 教程No Comments »
在许多实际应用场合中我们会要求在Arduino和其它设备之间实现相互通信,而最常见通常也是最简单的办法就是使用串行通信。
在串行通信中,两个设备之间一个接一个地来回发送数字脉冲,它们之间必须严格遵循相应的协议以保证通信的正确性。
在PC机上上最常见的串行通信协议是RS-232串行协议,而在各种微控制器(单片机)上采用的则是TTL串行协议。
由于这两者的电平有很大的不同,因此在实现PC机和微控制器的通信时,必须进行相应的转换。
完成RS-232电平和TTL电平之间的转换一般采用专用芯片,如MAX232等,但在Arduino上是用相应的电平转换电路来完成的。
根据Arduino的原理图我们不难看出,ATmega的RX和TX引脚一方面直接接到了数字I/O端口的0号和1号管脚,另一方面又通过电平转换电路接到了串口的母头上。
因此,当我们需要用Arduino与PC机通信时,可以用串口线将两者连接起来;当我们需要用Arduino 与微控制器(如另一块Arduino)通信时,则可以用数字I/O端口的0号和1号管脚。
串行通信的难点在于参数的设置,如波特率、数据位、停止位等,在Arduino语言可以使用Serial.begin()函数来简化这一任务。
为了实现数据的发送,Arduino则提供了Serial.print()和Serial.println()两个函数,它们的区别在于后者会在请求发送的数据后面加上换行符,以提高输出结果的可读性。
在这一实验中没有用到额外的电路,我们只需要用串口线将Arduino和PC机连起来就可以了,相应的代码为:
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("Hello World!");
delay(1000);
}
在将工程下载到Arduino模块中之后,在Arduino集成开发环境的工具栏中单击“Serial Monitor”控制,打开串口监视器:
接着将波特率设置为9600,即保持与工程中的设置相一致:
如果一切正常,此时我们就可以在Arduino集成开发环境的Console窗口中看到串口上输出的数据了:
为了检查串口上是否有数据发送,一个比较简单的办法是在数字I/O端口的1号管脚(TX)和5V电源之间接一个发光二极管,如下面的原理图所示:
这样一旦Arduino在通过串口向PC机发送数据时,相应的发光二极管就会闪烁,实际应用中这是一个非常方便的调试手段;-)
Arduino教程六: 串口输入
Arduino, 教程1 Comment »
串行通信是在实现在PC机与微控制器进行交互的最简单的办法。
之前的PC机上一般都配有标准的RS-232或者RS-422接口来实现串行通信,但现在这种情况已经发生了一些改变,大家更倾向于使用USB这样一种更快速但同时也更加复杂的方式来实现串行通信。
尽管在有些计算机上现在已经找不到RS-232或者RS-422接口了,但我们仍可以通过USB/串口或者PCMCIA/串口这样的转换器,在这些设备上得到传统的串口。
通过串口连接的Arduino在交互式设计中能够为PC机提供一种全新的交互方式,比如用PC机控制一些之前看来非常复杂的事情,像声音和视频等。
很多场合中都要求Arduino能够通过串口接收来自于PC机的命令,并完成相应的功能,这可以通过Arduino语言中提供的Serial.read()函数来实现。
在这一实验中我们同样不需要任何额外的电路,而只需要用串口线将Arduino和PC机连起来就可以了,相应的Arduino工程代码为:int ledPin = 13;
int val;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
val = Serial.read();
if (-1 != val) {
if ('H' == val) {
digitalWrite(ledPin,
HIGH);
delay(500);
digitalWrite(ledPin,
LOW);
}
}
}
把工程下载到Arduino模块中之后,在Arduino集成开发环境中打开串口监视器并将波特率设置为9600,然后向Arduino模块发送字
符H,如下图所示:
该工程运行起来之后会不断调用Serial.read()函数从串口获得数据。
Arduino语言提供的这个函数是不阻塞的,也就是说不论串口上是
否真的有数据到达,该函数都会立即返回。
Serial.read()函数每次只读取一个字节的数据,当串口上有数据到达的时候,该函数的返回
值为到达的数据中第一个字符的ASCII码;当串口上没有数据到达的时候,该函数的返回值则为-1。
Arduino语言的参考手册中没有对Serial.read()函数做过多的说明,我的一个疑问是如果PC机一次发送的数据太多,Arduino是否提
供相应的串口缓存功能来保证数据不会丢失?Arduino语言中提供的另外一个函数Serial.available()或许能够帮助我们用实验来进行
验证:
int ledPin = 13;
int val;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
val = Serial.read();
if (-1 != val) {
if ('H' == val) {
digitalWrite(ledPin,
HIGH);
delay(500);
digitalWrite(ledPin,
LOW);
Serial.print("Available:
");
Serial.println(Serial.availab
le(), DEC);
}
}
}
函数Serial.available()的功能是返回串口缓
冲区中当前剩余的字符个数,按照Arduino
提供的该函数的说明,串口缓冲区中最多能
缓冲128个字节。
我们可以一次给Arduino模块发送多个字符,来验证这一功能:
在这一实验中,每当Arduino成功收到一个字符H,连接在数字I/O端口管脚13上的发光二极管就会闪烁一次:
Arduino教程七: XBee无线通信
Arduino, 教程4 Comments »
借助XBee扩展板我们可以很方便地将XBee模块连接到Arduino上,XBee模块的工作原理也非常简单,它与Arduino之间其实就是通过串行接口(即Tx和Rx引脚)进行通信。
对于简单的点对点通信来讲,只需要通过串行接口向XBee模块写数据就可以实现数据的发送;当XBee模块通过无线通道接收到数据时,通过读串行接口可以很方便地获得这些数据。
原理弄清楚之后,其实我们可以将XBee模块看成是Arduino的串口,通过相应的串口操作函数来实现数据的接收和发送。
首先请按照
Arduino XBee模块使用手册中的说明配置好你的两个XBee模块,然后
将相应的跳线连接到XBEE一端:
这里我们使用一个最简单的工程来进行相应的实验:
int ledPin = 13;
int val;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
// send data to another XBee module
Serial.print('A');
delay(1000);
// receive data from another XBee module
val = Serial.read();
if (-1 != val) {
if ('A' == val) {
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
}
}
}
该工程首先通过Serial.print()函数向XBee模块发送一个字母A,该字母会被XBee模块通过无线网络发送出去,并被另外一个XBee 模块接收到。
紧接着再通过Serial.read()函数从XBee模块读取从无线网络接收到的数据,如果是字母A的话,则点亮相应的发光二极管。
将该工程编译并分别下载到两个Arduino模块中,注意下载的时候不要连接XBee扩展板,这是因为XBee模块会占用串口,从而导致下载无法正确完成。
下载完成后将XBee扩展板连接到Arduino上,并分别给两者上电。
这两个Arduino模块都会向对方发送字母A,然后从对方接收字母A,并对点亮数字I/O管脚13上连接的发光二极管。
你可以试着将两个模块放在房间里的不同位置,来对XBee模块的传输性能进行测试。
Arduino电机驱动扩展板
Arduino, 基本电路, 教程11 Comments »
除了使用传感器对各种外部物理量进行感知之外,能够对实际物体的运动进行相应的控制也是互动设计中不可或缺的一部分。
在所有这类动力装置中,电机显然是最常见、最基本、最便宜的解决方案了,常用的电机的种类有很多种,如直流电机,步进电机,伺服电机,减速电机等,并且每一种电机的控制方法都有所不同。
如果你是一个电子高手,控制普通的直流电机用几个三极管就行了,否则话像L293这样的芯片将是一个更好的选择。
L293芯片的核心是两个H-桥,所有的H-桥芯片都具有如下一些引脚:
•逻辑输入
•逻辑电压
•电源电压
•电源输出
•地
其中逻辑电压引脚采用与微控制器相同的电压和电流,电源电压采用与运行电机所需要的电压和电流。
逻辑输入引脚连接到用来向H-桥输出控制信号的微控制器上的引脚,而电源输出引脚则连接到电机上。
这么专业的术语翻译到Arduino上可以这样来理解。
首先,我们需要两套电源,一套用来给Arduino供电,一套用来给电机供电。
其次,我们需要用到Arduino的数字I/O管脚来控制L293,并把电机接到L293上接受控制。
说到这里,正好解释一下Arduino的供电系统,通常Arduino有三种供电方式:
•USB供电
•电池供电
•变压器供电
后两者在Arduino上统称为外部供电。
供电方式的选择是通过Arduino上的电源选择跳线来实现的,当把跳线接到“USB”一端时,采用的是USB供电方式,这时整个Arduino及其附属电路上的电源都由PC的USB接口提供,此时电流一般比较小,只能驱动功率比较小的电路,如LED等。
当把跳线接到“EXT”一端时,采用的是外部供电方式,这时一般能够驱动比较大的设备,如电机等。
Arduino内部一套电源转换电路,可以用来将外部供电时的电压(6-12V)转换成内部所需要的5V电压,使用L293控制电机正是需要这两套电源。
下面这个就是基于L293D芯片的Arduino专用电机驱动扩展板,它能够用来驱动两个直流电机。
使用该扩展板来驱动直流电机非常简单,只需要将扩展板插到Arduino上,同时将直流电机连接到扩展板上的motors引脚上就可以了。
正如上面所提到的,此时应该采用Arduino的外部供电方式,并使用变压器或者电源为Arduino提供电力。
这里我选用的是9V变压器和9V的直流电机:
电机扩展板上motors引脚的上面两针是用来接电机1的,下面两针是用来接电机2的。
电路连接好之后,剩下的工作就是如何用程序进行控制了。
使用这一扩展板我们能够控制直流电机的转动方向和转动速度,其中对转动方向的控制是通过Arduino上的数字I/O引脚12和13来实现的,对转速的控制则是通过数字I/O引脚9和10来实现的。
如果要控制直流电机1,我们需要向引脚9输出相应的PWM信号来控制电机的速度,同时设置引脚12和13的高低电压来控制电机的方向。
如果要控制直流电机2,则需要向引脚10输出相应的PWM信号来控制电机的速度,此时也是通过设置引脚12和13 的高低电压来控制电机的方向的。
电机扩展板上带有S1和S2两个按钮,分别对应于Arduino数字I/O的7号和6号管脚,并且在按下时为低电平。
因此我们可以像下面的程序这样利用S1来控制电机1的正反转:
int switchPin = 7; // switch pin
int dir1Pin = 12; // direction 1
int dir2Pin = 13; // direction 2
int speedPin = 9; // spped pin
void setup() {
pinMode(switchPin, INPUT);
pinMode(dir1Pin, OUTPUT);
pinMode(dir2Pin, OUTPUT);
pinMode(speedPin, OUTPUT);
}
void loop() {
// switch is pressed
if (digitalRead(switchPin) == LOW) {
// set spped
analogWrite(speedPin, 250);
// set direction
digitalWrite(dir1Pin, LOW);
digitalWrite(dir2Pin, HIGH);
} else {
analogWrite(speedPin, 100);
digitalWrite(dir1Pin, HIGH);
digitalWrite(dir2Pin, LOW);
}
}
在将上述程序下载到Arduino上并运行起来之后,我们就可以通过按S1键,来改变电机的旋转速度和方向了:)
P.S. 在调试这一电机扩展板的奇遇是,在将其插入到Arduino Diecimila的贴片版本上时,发现MC33269异常热,并且电机偶尔才能工作。
进一步设计发现如果把整个扩展板很好地插入到Arduino上时,5V和Gnd之间居然是短路的。
一开始并没有发现问题在哪,后来才发现扩展板上的电容C9与USB接头的外壳短路了!将其锡去掉一下,并抬高扩展板时问题得到解决。
实际使用时请检查下图电容下面的引脚是否与USB接口的外壳短路了,特别是对于贴片版本来讲,最好在通电前用万用表检查一下5V和Gnd之间的电阻值:)
Arduino下载线使用手册
Arduino, DIY, 手册3 Comments »
Arduino使用的是Atmel公司的AVR单片机,一般为ATmega8和ATmega168,这一系列的单片机都支持ISP(In System Programmability )编程,无需依赖昂贵的编程器就可以完成程序的下载。
Arduino电路在设计上考虑到了ISP功能,也留出了相应的接口(ICSP),从而允许我们通过ISP下载线来完成bootloader的下载。
新买来的Arduino模块上一般都已经预先下载好了bootloader,因此上电之后就能够直接通过Arduino集成开发环境下载相应的Arduino程序。
正常情况下我们在用Arduino时是不需要ISP下载线的,但在某些情况下可能会出现在Arduino集成开发环境中无法正常下载程序的现象,这很可能是由于bootloader受损所致。
解决的办法就是重新将bootloader烧写到ATmega芯片中,此时你就需要用到这里介绍的ISP下载线了。
Arduio网站上给出的并口下载线电路我只成功地更新过ATmega8的bootloader,而无法为Diecimila上的ATmega168下载bootloader。
此外,Arduino给出的这一下载线电路过于简单,没有做相应的隔离和保护,经常使用可能会对Atmega芯片带来一定的损害。
AVR 建议使用一片74HC244来隔离并口和ATmega芯片,下面是我所使用的下载线的原理图:
以及自制的下载线:
使用并口下载线的时候,我们需要先到计算机的BIOS中将并口设为ECP(The extended capabilities port )模式,同时将I/O基地址设置成378:
此时在Windows的设备管理器中,我们会发现并口已经被标记为
“ECP 打印机端口”:
用鼠标右键单击后从弹出的菜单中选择“属性”命令打开属性对话
框,在“资源”页面中我们会看到相应I/O基地址的设置已经生效:
现在就可以用ISP下载线连接计算机并口和Arduino上的ICSP接口
了,请特别留意连接方向:ISP下载线六口插座上标有小三角的一端应该靠近Arduino的ICSP接口上标为1的一端。
虽然计算机并口能够为下载电路提供一定的电压,但一般我还是建议给Arduino模块加上5V电压(通过USB线和外接电源都可以),以保证下载过程的稳定。
硬件准备好之后,我们就可以通过相应的软件将bootloader烧到Arduino中。
支持AVR下载线的软件比较多,如AVRDUDE和SLISP 等,我们在这里使用的是PonyProg。
下载并安装好PonyProg v2.07a BETA版本,启动PonyProg时会提示你进行相应的校准和设置工作。
首先选择“Setup”菜单中的“Calibration”命令进行校准,然后再选择“Setup”菜单中的“Intreface Setup…”命令进行相应的并口设置:
根据你的Arduino模块上的芯片类型,从“Device” 菜单中的“AVR micro”
子菜单中选择“ATmega8”或者“ATmega168”。
你也可以从工具栏上的
Device下拉框中进行相应的选择:
首先从“Command”菜单中选择“Read All” 命令,从Arduino模块上读出
ATmega中的当前数据和设置,其中最重要的是之后要设置的熔丝位。
然后选择“File”菜单中的“Open Program (FLASH) File…” 命令,打开“Open
program (FLASH) content file”对话框。
从你的Arduino安装目录下找出对应于的bootloader。
对于Arduino 0010版本来讲,我们可以在hardware\bootloaders目录下找到atmega8和atmega168两个目录,分别对应ATmega8和ATmega168芯片所对应的bootloader(文件扩展名为.hex),在atmega168目录下可以找到ATmegaBOOT_168_diecimila.hex和ATmegaBOOT_168_ng.hex两个文件,分别对应Diecimila和NG模块。
你需要根据你的Arduino 模块的具体情况,加载相应的bootloader文件。
AVR通过熔丝来控制芯片内部的一些功能,比如JTAG,时钟的使用,掉电检测电压,是否允许调试等。
熔丝位的配置是为Arduino下载bootloader过程中最复杂的一步,而且设置出错很有可能导致芯片锁死,所以一定要仔细。
选择“Command”菜单中的“Security and Configuration Bits …”命令,打开相应的熔丝设置对话框。
Arduino的bootloader对熔丝位有一定的要求,主要是同外部时间设置相关的。
对于串口模块采用的ATmega8来讲,相应的熔丝字节要设置成0xCA(Fuse High Byte)和0xFF(Fuse Low Byte),具体每位的含义可以参见Wolf Paulus的文章。
在PonyProg中对ATmega8的熔丝位设置为下图所示:
对于NG和Diecimila采用的ATmega168
来讲,相应的熔丝字节要设置成0xF8
(Extended Fuse Byte), 0xDF(Fuse
High Byte)和0xFF(Fuse Low Byte)。
在PonyProg中对ATmega168的熔丝位
设置为下图所示:
熔丝位设置好之后,选择“Command”菜
单中的“Write All”命令,将bootloader
下载到Arduino中。
下载过程中Arduino
上的发光二极管L会不断闪烁。
下载完
成之后,我们可以通过Arduino集成开。