文章目录
- 前期教程
- 前言
- 一、库文件丰富
-
- 1. 舵机库——Servo.h
- 2. 软串口库——Softwareserial.h
- 3. IIC总线——Wire.h
- 4. 老旧的库——Wprogram.h
- 二、Arduino下载编程器&USBasp下载
-
- (一)用Arduino下载编程器
- (二)使用USBasp下载程序
- 三、Arduino作为USB转TTL模块
- 四、EEPROM操作
-
- 使用参考
- 五、总结其他问题
-
- 1. 电机和舵机不能同时运行?
- 2. Arduino程序烧不上去?
- 3. 建立多文件工程文件 /\*2022.3.14\*/更新
- 4. 利用MATLAB开发Arduino
- 5. 软件复位
前期教程
- 【单片机】Arduino(以UNO R3为例)—— 基本函数汇总
- 【单片机】Arduino供电总结
- 嵌入式模块舵机使用详细说明
前言
??作为最容易入门的单片机之一,Arduino总总是可以使用非常简单和容易理解的代码来实现你想要的功能,许多人可能会使用它Arduino做一些相对简单的工作或其他原因,从而形成一种思维定势:Arduino只能做简单的事。但是随着我的使用Arduino其他单片机的程度逐渐加深,我对Arduino的一些 有了更深的了解,发现Arduino真的不简单!
一、库文件丰富
??Arduino一个强大的功能是它配备了丰富的包装库文件,有些是安装软件时带来的,有些可以额外下载。 ??首先,我们 有两个地方可以找到:一个是安装目录libraries
文件夹,安装软件时自带;另一个是文档Arduino文件夹下的libraries
文件夹,应该是额外下载的库文件的安装位置。 ??那 在我看来,首先是单片机的工作原理和Arduino电影外设有足够的了解,其次是。此外,官方还提供了一个故事libraries
总是阅读链接。
1. 舵机库——Servo.h
??通过查看Servo.h可以发现舵机被定义为一个类,即Servo
,舵机的相关操作是其中的成员函数,因此在使用该库时,应首先定义一个类别,如Servo myservo
,然后再使用myservo.xxxxx
调用各类成员函数。
attach()
??设置舵机控制信号输出引脚,官方文件,至于这个Arduino0016是只IDE目前还不清楚还是只有芯片,但可以肯定的是UNO属于这Mega2560不属于。不属于的应该是可以定义任何支持PWM输出引脚。 :
servo.attach(pin) servo.attach(pin, min, max)
?? ???pin:设定的信号输出引脚; ???min:当舵机转向0度时(默认值为544us,周期是20ms) ???max:当舵机转向180度时(默认值为2500us,周期为20ms)
attached()
??判断是否判断舵机信号引脚"绑定"如果是,返回true
,如果没有,返回false
。
bool a; a = servo.attached();
detach()
??可以使用信号输出引脚解绑analogWrite()
来输出PWM波。
servo.detach()
write()
直接输出舵机的角度
servo.write(angle); //angle0-180之间的输出角度
??
#include <Servo.h> Servo myservo; void setup() {
myservo.attach(9);
}
void loop()
{
myservo.write(90);
delay(1000);
myservo.write(180);
delay(1000);
}
writeMicroseconds()
输出脉冲时间,相比于直接输出角度稍有点复杂,对于标准舵机,PWM频率固定是50Hz,当脉冲宽度为1500us时,舵机处于中间状态,上下限和舵机舵机生产厂商有关,一般来说下限是500us,上限是2500us。【注意看舵机数据手册】
servo.writeMicroseconds(us); //us即为脉冲宽度,单位为微秒
read()
读取当前舵机的角度,返回值为0-180。
int angle = servo.read();
2. 软串口库——Softwareserial.h
在Arduino中,只有一个串口模块,即0,1引脚,而且这个串口模块还是和插电脑的USB的连通的,因此在烧录程序时只能拔掉串口连接的设备,否则无法烧录程序,因此十分有必要。 所谓软串口,就是使用一般的数字引脚模拟串口传输时的高低电平变化,而这个库Softwareserial.h
的作用就是将一些底层代码封装成一个个函数,方便直接调用。下面是这个库中封装的好的函数 由于这里很多函数名字和使用都和中的函数相同,故这里只总结第一个函数
SoftwareSerial
的使用,并给出一个使用例程,方便参考。
SoftwareSerial()
选择引脚设置为软串口,其语法如下:
SoftwareSerial(rxPin, txPin, inverse_logic);
其中rxPin和txPin分别为输入引脚和输出引脚号,而inverse_logic参数是设置为负逻辑,不加时默认为false。
// include the SoftwareSerial library so you can use its functions:
#include <SoftwareSerial.h>
#define rxPin 10
#define txPin 11
// set up a new serial port
SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);
void setup() {
// define pin modes for tx, rx:
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
// set the data rate for the SoftwareSerial port
mySerial.begin(9600);
}
void loop() {
if (mySerial.available()>0){
mySerial.read();
}
}
3. IIC总线——Wire.h
Arduino Wire.h 库函数基本操作 IIC - CSDN 官方Wire库讲解 Arduino的Wire.h库主要用于进行IIC通信(还有TWI,但是不常用),将IIC通信传输的操作封装成函数,方便直接调用。建议在使用之前找到这个库的源代码,位置在C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries
,找到Wire文件夹,看源码和关键词。
begin()
用来初始化IIC总线,使该设备作为主设备或者从设备加入到IIC总线中,。
Wire.begin()
Wire.begin(address)
其中address为地址,如果不加,默认为主设备。
requestFrom()
主设备向从设备请求发送数据,这个数据可以被read()
和available()
函数接收
Wire.requestFrom(address, quantity)
Wire.requestFrom(address, quantity, stop)
其中,为接收数据的字节数; 为一个布尔值,1 :再请求完数据之后,发送一个停止信号,释放总线;0 :不发送停止信号,不释放总线,主设备可以再次请求。默认值为1。 返回值为从设备传输的字节数。
beginTransmission()
开启向从设备输出数据
Wire.beginTransmission(address);
endTransmission()
用来结束对从设备的数据输入。其中,里面可以加上参数stop,如果stop为1,则会在传输结束之后再发送一个结束信号,从而释放总线;如果stop为0,则表明在传输数据之后不发送结束信号,不释放总线。不加这个参数时,默认值为1。
Wire.endTransmission()
Wire.endTransmission(stop)
其返回值有5种情况: 0 :传输成功 1 :数据太长,无法装入缓冲区 2 :在传输地址时接收到NACK(非应答信号) 3 :在传输数据时接收到NACK 4 :其他错误
write()
使主设备传输到从设备的数据。
Wire.write(value)
Wire.write(string)
Wire.write(data, length)
value:单个字节 string:字符串,一串数据 data:一个数组 length:传输数据的字节长度
需要注意的是:传输数据时一般是先begin,再write,再end。参考下面这个例程。
#include <Wire.h>
byte val = 0;
void setup()
{
Wire.begin(); // join i2c bus
}
void loop()
{
Wire.beginTransmission(44); // transmit to device #44 (0x2c)
// device address is specified in datasheet
Wire.write(val); // sends value byte
Wire.endTransmission(); // stop transmitting
val++; // increment value
if(val == 64) // if reached 64th position (max)
{
val = 0; // start over from lowest value
}
delay(500);
}
available()
返回能够读入的数据字节数,一般来说这个函数的调用要紧接着函数requestFrom()
之后,如果是从设备,要紧接着onReceive()
函数。
Wire.available()
函数返回值为能够读入的数据。
read()
主设备读入从设备的数据字节数 返回值为读到的。
主设备读入数据时,一般要按照下面这个例程来进行。
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop()
{
Wire.requestFrom(2, 6); // request 6 bytes from slave device #2
while(Wire.available()) // slave may send less than requested
{
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
delay(500);
}
setClock()
设置传输时钟。单位为Hz
Wire.setClock(clockFrequency)
100KHz :标准模式(clockFrequency = 100000,下面类似。) 400KHz :快速模式 部分支持: 10KHz :慢速模式 1MHz : 快速模式Plus 3.4HMz :高速模式
onRequest()
&onReceive()
设置主设备请求从设备发送数据时执行的函数;设置从设备接收到数据时执行的函数。
Wire.onReceive(handler)
Wire.onRequest(handler)
其内部的参数为一个函数,且要求这个函数没有参数,没有返回值。
4. 老旧的库——Wprogram.h
这个库现在一般不用了,因为它并入了Arduino.h
文件中。记录一下。
二、Arduino作为编程器下载&USBasp下载
此前因为意外,不小心烧了一块板子,其结果就是插上电脑会弹出下面这个窗口,同时Arduino IDE中端口选项是灰色的。总而言之,这块板不能再通过USB烧入程序了。 但是我不甘心啊,之前也遇到过这样的问题,但是当时因为没有时间,加上烧的是UNO,不是很贵,所以没研究。而这次烧的可是Arduino Mega,一块可以买两三块UNO,所以这块板子一直留了下来,因为我始终坚信这块板子的芯片没坏。 我的猜测是这块板子是CH340芯片坏掉了,导致电脑无法识别,但是内部芯片没问题,那Arduino除了用USB插电脑来下载程序,有没有其他的方式下载程序呢?有,而且还有两种。,下载器如下图所示。
(一)用Arduino作为编程器下载
首先需要准备另一块好的板子,型号不固定,我这有现成的UNO,故使用这块板子。
- 第一步就是把Arduino UNO变成一个编程器。方法就是在Arduino 特定的程序,直接在中就能找到。
- 下载完这个程序,此时的Arduino板就成为一个了,然后就是连线。对此,我们需要简单理解一下这种下载方式的原理,这种下载方式使用的协议为SPI,而SPI为四线协议,因为这里没有片选,所以只有三线,即,所以连线的主要任务就是将编程器的这三个引脚与需要烧入程序的板子之间进行连接。 这一点,建议去看Arduino ISP例程中的注释,如下图所示。 从图中可以看到,目标板还需要连接RESET引脚,这个引脚连接的编程器的 ,故连线对应关系如下表所示
编程器(UNO) | 目标板 |
---|---|
11 | MOSI |
12 | MISO |
13 | SCK |
5V,GND | 5V,GND |
注意和RX,TX连接方式区分开来!MOSI连接MOSI,MISO连接MISO!
所以在连线时,需要先了解目标板子的引脚分布,看哪些引脚对应的是SPI通信的三个引脚。一般来说,Arduino板子上会有6个ICSP的接口,如下图所示。这些接口实际上就是从边上的那几排接口中引出来的, 所以方便起见,可以直接看这六个引脚的分布,如下图所示(大部分Arduino的引脚顺序都是这样)
- 接好线之后,下面就是烧录程序了,将通过USB插到电脑上,打开需要下载到目标板的程序,然后按照下图设置一下。 设置完之后,不能直接点击上传按钮上传,而要在项目中选择,然后等待上传成功即可。
(二)使用USBasp下载程序
那假如手边没有其他的Arduino板,那又如何下载程序呢?还有一个办法,就是去买一个USBasp,总归要比再买一个Arduino UNO来得便宜。图片参考上面的某张图。 下面简单记录一下操作方法。
- 首先将USBasp插入到电脑中,然后电脑就会自动安装驱动,在设备管理器中也能看到新增的设备。 这里需要注意的是,如果显示驱动程序无法识别或者其他什么原因导致无法烧入程序的话,可以考虑重新安装一个的驱动程序,方法就是在网上下载一个名为的软件【官网链接】,然后找到USBasp,安装对应的驱动即可。
- ,一般买这个USBasp会送一根线,但这根线和Arduino中的ICSP端口不是对应的,其10线接口定义如下: 上图中,黑色小条对应实际插头的那个缺口。 然后就是和Arduino编程器一样对应连线即可。
- 。同样,烧入程序前先简单设置一下,如下图所示。 这里不知道为什么我这端口选项是灰色的,不能选,但烧入程序完全没问题,所以遇到这个问题的就不用纠结了,直接烧入就行。 和Arduino做编程器一样,这里也不能直接点击上传按钮,而要选择项目中的。
- 用USBasp下载程序 - 博客园
- [Arduino]烧写Arduino BootLoader的几种方法 - CSDN
- 使用usbasp烧写arduino - CSDN
- 【arduino】arduino ISP下载程序方法,用arduino uno给arduino nano下载程序 -CSDN
- 我修我自己——Arduino充当ISP烧录器修复Arduino记录 - 什么值得买社区
- 给Arduino烧录BootLoader引导程序,包括Atmega 16U2(通信芯片),Atmega 328P(主控芯片)- CSDN
- Arduino uno作为ISP烧录器,烧录其他arduino板 - 简书
三、Arduino作为USB转TTL模块
因为要调试蓝牙模块,但是却缺了一个USB转TTL的模块,然后就想到用多串口的单片机实现,比如Arduino Mega,然后写了一个程序,如下所示:
void setup() {
Serial.begin(9600); //与电脑连接
Serial1.begin(9600);//与蓝牙模块连接
}
void loop() {
send_data();
receive_data();
}
char send_data()
{
while (Serial.available())
{
char a = Serial.read();
Serial1.write(a);
}
}
char receive_data()
{
while (Serial1.available())
{
char b = Serial1.read();
Serial.write(b);
}
}
但是很遗憾,这个程序烧入进去之后从电脑上发出AT指令,得到的回应只有\0,不知道为啥,然后就去网上找相关的资料,但没想到,程序没找到,倒是找到一个解决这个问题的另一种方法! 附:参考链接 首先,在Arduino中烧入以下程序:
void setup() {
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP); //将串口的两个引脚设置为上拉输入
}
void loop() {
}
然后将蓝牙模块连接到上,而且务必注意:,这样,就可以通过电脑上的串口调试助手来调试蓝牙模块了,而且使用体验与USB转ttl模块完全一样!
四、EEPROM操作
最近才知道,原来Arduino和STC的51单片机一样,除了写入程序的flash之外,还内置了一个EEPROM,而且它还内置了一个库函数,方便用户直接调用写入读出等函数,非常友好。
使用参考
五、其他问题汇总
1. 电机与舵机不能同时运行?
此前在参加一个智能小车的比赛时,发现上舵机之后电机不会动,找了半天也没找到原因,最后经过别人的提醒,是因为舵机的原因,因为Arduino UNO中引脚9,10都能输出PWM,且二者共用一个定时器,如果引脚9作为舵机信号线使用,那么另一个引脚输出PWM的功能就会收到影响,因为舵机输出的PWM固定为50Hz,这样频率的PWM会导致直流电机运行不正常。解决办法就是换引脚,或者是使用detach()
函数。
2. Arduino程序烧入不上去?
有一个可以尝试的办法就是重新烧入Bootloader,即,方法就是插上USB线,然后点击 或者使用USBasp烧入,效果一样。
3. 多文件工程文档的建立 /*2022.3.14*/更新
相信对于习惯使用Keil创建51系列、STM32系列单片机工程文档的人来说,Arduino似乎就是一个异类,因为它一个程序似乎只能放在一个文件中,对于习惯以文件来管理外设的人来说会很不习惯。而我就是其中一个,因为一个项目稍有点复杂,我仔细研究了一下这个Arduino的文件逻辑。下面是一些记录。
- 首先Arduino是能够添加其他文件的,包括 ,都是支持的,但是它必须要有一个和它外面套的文件夹名相同的文件(估计这也是为什么它必须要求每个文件外面都要套一层同名文件夹)
- 虽然Arduino能够支持添加多种文件,但和一般的C51工程文档还是有点区别,不注意的话编译是无法通过的。
- 对于 文件,这个可能是最为常用的,因为一般Arduino的库文件就是这样一对的形式出现的。但是,相信很多人看到的都是,经过我的测试,如果在cpp文件中写其他函数或者引用其他库文件,都是会报错的,即。
- 对于 文件,首先确定一点,它们的使用逻辑和C51是一样的,但是,经过我的不完整测试,**它们不能在文件中include除Arduino.h外的所有自带库,而且不能引用工程下面的其他文件。**也就是只能写一些基本的digitalWrite之类的函数。
- 综上所述,似乎想要在Arduino中添加库文件很麻烦?确实,但还有一种是使用ino格式的文件,这种方法是我发现最为方便的方法了,,而且主ino里面不需要include。
4. 利用MATLAB开发Arduino
由于个人比较常用MATLAB,上次无意间看到利用MATLAB开发Arduino的方法,记录一下。 参考链接1 参考链接2 参考链接3
- arduino硬件支持包可联网直接下载(有时无法成功下载,只能翻墙才行)。获取安装包步骤:①在matlab主页→在附加功能项目→点击硬件支持包→点击matlab support package for Arduino Hardware下载(需要注册一个matlab账户,大多数情况下需要墙才可下载成功,添加到路径。
- 。文件下载链接见上文参考链接1。到此软硬件配置完毕。
- 。在MATLAB命令行中输入:a = arduino(“COM4”),(注意:COM口自己选对),等待片刻会显示连接成功。
5. 软件复位
在写一些程序时,有时候想要程序在不受外界操作之下自动进行程序复位,即所谓的软件复位。经过查找资料,找到两种方式,一种是通过给reset引脚单独接一个数字引脚,这样需要复位时,只需要将这个引脚输出值改为低电平就行;还有一种方式是使用Arduino自带的一个软件复位函数,其实例程序如下所示。
void(* resetFunc) (void) = 0; //指将resetFunc这个函数的地址设置为0,即初始地址
void setup() {
Serial.begin(9600);
Serial.println("How to Reset Arduino Programmatically");
delay(200);
}
void loop()
{
Serial.println("A");
delay(1000);
Serial.println("B");
delay(1000);
Serial.println("Now we are Resetting Arduino Programmatically");
Serial.println();
delay(1000);
resetFunc(); //相当于强制使得程序跳转到初始位置开始执行
Serial.println("Arrduino will never reach there.");
}