Arduino-语法基础学习

介绍

这里以 Arduino Nano Every 这个板子为示例.

基本程序结构

Arduino 程序都用 .ino 为后缀, 其基本结构为:

1
2
3
4
5
6
7
void setup() {
// 初始化代码,只执行一次
}

void loop() {
// 主循环代码,会反复执行
}
  • setup() 函数一般用于设置引脚模式, 初始化串口通信, 启用模块等
  • loop() 函数用于处理数据, 控制输入输出

Serial 库

Serial 库实现了 UART/USART 通信, 一般配合 serial monitor 做调试. 大多情况下不需要手动包含 Serial.h, 因为其已经包含在 Arduino.h 中.

示例1: 在 serial monitor 打印信息

1
2
3
4
5
6
7
8
void setup() {
Serial.begin(9600); // 初始化串口通信,波特率9600
}

void loop() {
Serial.println("Hello, Arduino!"); // 打印一行消息到串口监视器
delay(1000); // 每秒发送一次
}

示例2: 接收输入以控制流程

Arduino 会先将外部发来的串口数据放在 “串口缓冲区” 中.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int ledPin = 13;  // LED 连接到引脚13

void setup() {
pinMode(ledPin, OUTPUT); // 设置LED引脚为输出模式
Serial.begin(9600); // 初始化串口通信
Serial.println("请输入 'on' 或 'off' 控制 LED:");
}

void loop() {
if (Serial.available() > 0) {
String command = Serial.readStringUntil('\n'); // 读取整行指令
command.trim(); // 去除多余空格或换行符

if (command == "on") {
digitalWrite(ledPin, HIGH); // 打开LED
Serial.println("LED 已打开");
} else if (command == "off") {
digitalWrite(ledPin, LOW); // 关闭LED
Serial.println("LED 已关闭");
} else {
Serial.println("无效指令,请输入 'on' 或 'off'");
}
}
}
  • pinMode() 函数用于控制引脚模式, 接收两个参数
    1. 引脚, 通常是一个整数, 比如这里的 13
    2. 模式, 如 INPUT, OUTPUT,
  • digitalWrite() 函数向引脚写入一个值, 用于控制开断, 同样接收两个参数
    1. 引脚
    2. HIGH 表示打开, LOW 表示关断
  • Serial.available() 用于检查串口缓冲区中是否有可读取得数据, 返回可读取得字节数
  • Serial.read() 可读取一个字节, 其返回一个 0-255 之间的整数, 表示接收到的单个字节数据的 ASCII 编码 (比如输入 1, 读取到的其实是 49, 即 1 的 ASCII 编码值), 若想返回 char, 可强制类型转换
  • Serial.readStringUntil('\n') 可读取一行

Wire 库

Wire 库实现了 I2C 通信.

1
#include <Wire.h>

对于 Nano board 而言, 相关的引脚为:

  • A4, SDA (Data line)
  • A5, SCL (Clock line)

需要注意 Wire.onRequest()Wire.onReceive() 函数都只能在 slave 上是用.

示例1: master 从 slave 读取指定长度的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Wire Controller Reader
// by Nicholas Zambetti [http://www.zambetti.com](http://www.zambetti.com)

// Demonstrates use of the Wire library
// Reads data from an I2C/TWI peripheral device
// Refer to the "Wire Peripheral Sender" example for use with this

// Created 29 March 2006

// This example code is in the public domain.


#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(8, 6); // request 6 bytes from peripheral device #8

while (Wire.available()) { // peripheral may send less than requested
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}

delay(500);
}
  • Wire.begin() 不加参数说明是 master
  • Wire.requestFrom() 用来指定请求的字节数以及 slave 地址
  • Wire.available() 同样用于检查缓冲区中是否接收到了数据

示例2: master 向 slave 发送数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <Wire.h>

void setup() {
Wire.begin(); // 初始化 I2C 作为主设备
Serial.begin(9600); // 初始化串口,用于调试
}

void loop() {
Wire.beginTransmission(8); // 开始传输,目标地址为 8
Wire.write("Hello"); // 加入数据
byte result = Wire.endTransmission(); // 结束传输

if (result == 0) {
Serial.println("传输成功");
} else {
Serial.println("传输失败");
}

delay(1000); // 等待1秒后再发送
}

示例3: slave 用回调函数发送和接收数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <Wire.h>

void setup() {
Wire.begin(8); // 设置从设备地址为 8
Wire.onReceive(I2C_RxHandler); // 设置接收回调函数
Wire.onRequest(I2C_TxHandler); // 设置请求回调函数
}

void loop() {
// 主循环可以执行其他任务
}

void I2C_RxHandler(int numBytes) {
while (Wire.available()) {
char c = Wire.read(); // 读取接收到的数据
// 处理数据,例如保存或响应
}
}

void I2C_TxHandler() {
Wire.write("Data"); // 向主设备发送数据
}
  • Wire.onReceive(<function_name>) 当设备接收到数据是自动调用
  • Wire.onRequest(<function_name>) 当设备接收到读取请求时自动调用
  • Wire.write() 用于发送数据

处理模拟信号

读取模拟信号值

1
2
3
4
5
6
7
8
9
10
11
12
int analogPin = A3; // potentiometer wiper (middle terminal) connected to analog pin 3
// outside leads to ground and +5V
int val = 0; // variable to store the value read

void setup() {
Serial.begin(9600); // setup serial
}

void loop() {
val = analogRead(analogPin); // read the input pin
Serial.println(val); // debug value
K}K

SPI 库

1
#include <SPI.h>

对于 Arduino nano board 而言, 相关引脚为:

  • D13, SCK (Clock line)
  • D12, MOSI (Master Outout Slave Input)
  • D11, MISO (Master Input Slave Output)
  • D10, CS/SS (Client Select, Slave Select)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <Arduino.h>
#include <SPI.h>
#define LEDpin 2

/* Globals */
uint16_t analog_val;
uint8_t lower_val, upper_val;
int y;
int time=0;

void setup() {
Serial.begin(9600); // opens and configures the USB serial port for baudrate 115200
/* This does some magic which is necessary on the Nano Every */
SPI.begin();
/* Enable SPI, put it in Slave mode, set MSB first */
SPI0.CTRLA = (SPI_DORD_bm & (SPI_ENABLE_bm & (~SPI_MASTER_bm)));
/* disable "Slave Select Disable" --> to ensure it will stay slave */
SPI0.CTRLB &= ~(SPI_SSD_bm);
/* Set Mode 0 (is default though) */
SPI0.CTRLB |= (SPI_MODE_0_gc);
SPI0.INTCTRL = SPI_IE_bm; /* SPI Interrupt enable */


pinMode(MISO, OUTPUT);
pinMode(SCK, INPUT);
pinMode(MOSI, INPUT);
pinMode(SS, INPUT);
}

void loop() {
analog_val = analogRead(A1);
//analog_val =784;
lower_val = analog_val;
upper_val = (analog_val >> 8) ;
digitalWrite(LEDpin, HIGH);
delay(time);
digitalWrite(LEDpin, LOW);
delay(time);
delay(80);

}

// SPI interrupt routine
ISR(SPI0_INT_vect) {
byte c = SPI0.DATA;

switch(c){
case(0x83):
{
time = 1000;
break;
}

case(0x82):
{
time = 750;
break;
}


case(0x81):
{
time = 500;
break;
}

case(0x80):
{
time = 250;
//Serial.println("pin always high");
break;
}
case(0x0):
{
SPI0.DATA = lower_val;
//Serial.println("lower val");
break;
}
case(0x1):
{
SPI0.DATA = (analog_val >> 8);
//Serial.println("upper_val");
}
break;
}

SPI0.INTFLAGS = SPI_IF_bm; /* Clear the Interrupt flag by writing 1 */
}
  • SPI.begin(), 启用 SPI
  • SPI0, 是一个 SPI 模块(包含一些列寄存器等), 一般会有多个, 以便多 SPI 通信, 比如 SPI1, SPI2
    • CTRLA (“ConTRoL A”), 表示控制寄存器 A, 负责设置 SPI 的模式
    • _bm 后缀的实施 bitmask, 用来方便设置寄存器的位
    • SPI_DORD_bm (“Data ORDer”), 设置 LSB 先发送, 而不是默认的 MSB
    • SPI_ENABLE_bm 表示启用 SPI 模块
    • ~SPI_MASTER_bm 将其设为 slave
    • CTRLB 表示控制寄存器 B, 用来设置 SPI 的一些附加功能, 如时钟极性
    • SPI_SSD_bm (“Slave Select Disable”), 设置为 1, 则不会自动设置 SS 引脚的拉低和拉高
    • _gc 后缀 “Group Constant”, 用于设置 SPI 的工作模式
    • SPI_MODE_0_gc 表示 MODE 0, 即空闲时低电平, 采样为上升沿
    • INTCTRL (“INTerrupt ConTRoL”), 是中断控制寄存器, 用于配置 SPI 中断的启用和优先级
    • SPI_IE_bm (“Interrupt Enable”), 用于启用中断
  • SPI0.DATA, 数据寄存器, 存储 SPI 所接收的数据, 如果给该寄存器赋值, 则会发送数据
  • SPI0.INTFLAGS, 中断标志寄存器
    • SPI_IF_bm (Interrupt Finish), 当其设置为 1 时, 表示中断完成, 等待下一次触发

Arduino-语法基础学习
http://example.com/2024/10/18/Arduino-语法基础学习/
作者
Jie
发布于
2024年10月18日
许可协议