数字输入输出

在使用输入或输出功能前,你需要先通过pinMode() 函数配置引脚的模式为输入模式或输出模式。

端口初始化函数

//端口初始化
pinMode(pin, mode)
void pinMode(uint8_t, uint8_t);

参数

  • pin: 为指定配置的引脚编号

  • mode:

    为指定的配置模式 通常可用模式有三种:

    • INPUT: 输入模式 (DDRx=0xFF)
    • OUTPUT: 输出模式 (DDRx=0x00)
    • INPUT_PULLUP: 输入上拉模式 (DDRx=0xFF;PORTx=0xFF)

输出电平函数

//输出电平函数
digitalWrite(pin, value)
void digitalWrite(uint8_t, uint8_t);

参数

  • pin: 为指定输出的引脚编号;
  • value: 为你要指定输出的电平
    • HIGH: 指定输出高电平(1)
    • LOW: 指定输出低电平(0)(PORTx)

读取电平函数

//读取输入电平函数
digitalRead(pin)
int digitalRead(uint8_t);

参数

  • pin: 为指定读取状态的引脚编号。(PINx)

返回值

  • 获取到的信号状态,1为高电平,0为低电平。

模拟输入输出

模拟输入引脚是带有ADC(Analog-to-Digital Converter,模数转换器)功能的引脚。 它可以将外部输入的模拟信号转换为芯片运算时可以识别的数字信号,从而实现读入模拟值的功能。

模拟信号输入函数

//模拟信号输入函数
analogRead(pin)
int analogRead(uint8_t);

参数

  • pin: 是指定要读取模拟值的引脚,被指定的引脚必须是模拟输入引脚。 如analogRead(A0),即是读取A0引脚上的模拟值。

返回值

Arduino Uno模拟输入功能有10位精度,即可以将0~5V的电压信号转换为0~1023的整数形式表示。

模拟信号输出(PWM)函数

Arduino Uno中,提供PWM功能的引脚为3、5、6、9、10、11。 在analogWrite()analogRead()函数内部,已经完成了引脚的初始化,因此不用在Setup() 函数中进行初始化操作。

//模拟信号输出函数
analogWrite(pin,value)
void analogWrite(uint8_t, int);

参数

  • pin: 是指定要输出PWM波的引脚;
  • value: 指定是PWM的脉冲宽度,范围为0~255。

模拟电压输出函数

//模拟电压输出函数
analogReference()
void analogReference(uint8_t mode);

功能

  • 为模拟电压输入设置参考值;

形式

  • analogReference(type)

参数

type有以下几个选项:

  • DEFAULT: 默认参考值5v (在5V的 板子上 ) 或者 3.3 v (在3.3V 的Arduino板子上);
  • INTERNAL: 内置参考值, 在 ATmega168 或者ATmega328板子上为1.1v;在ATmega8 板子上为2.56v (在Arduino Mega板子上不可获得)。
  • INTERNAL1V1: 内置的1.1V 参考值 (只在Arduino Mega板子上有效 )
  • INTERNAL2V56: 内置的2.56V 参考值 (只在Arduino Mega板子上有效)
  • EXTERNAL: 在AREF引脚加的电压(0 ~ 5V)将作为参考值 。 AREF外接电源后不能使用其他的基准源,使用时会引起片内基准源与外部参考源短路

返回值

  • -none

注意

改变参考值的时候,刚开始的读数可能不准确。 不要用低于0v或高于5v的电压加在AREF引脚。如果使用加在AREF的外部电压作为参考那一定要在调用analogRead()之前设置analogReferenceEXTERNAL,否则可能毁坏芯片。 也可以使用一个5千欧的电阻连接外部参考电压到AREF引脚,这样可以方便地在内外参考电压间转换,不过请注意电阻将改变原先你想要的参考值,因为在AREF引脚内部有个32千欧的内置电阻。这样两个电阻就可以分压了,例如:加的是2.5v,那么在AREF引脚的电压就是:2.5 * 32 / (32 + 5) = ~2.2V 。

高级输入输出

输出50%方波函数

tone()主要用于Arduino连接蜂鸣器或扬声器发声。可以让指定引脚产生一个占空比为50%的指定频率的方波。

//输出50%方波函数
tone()
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);

语法

tone(pin, frequency) 
tone(pin, frequency, duration)

参数

  • pin: 需要输出方波的引脚
  • frequency: 输出的频率,unsigned int型
  • duration: 方波持续的时间,单位毫秒。如果没有该参数,Arduino将持续发出设定的音调,直到你改变发声频率或者使用noTone() 函数停止发声。

停止输出50%方波函数

//停止输出50%方波函数
noTone(pin)
void noTone(uint8_t _pin);

语法

  • noTone(pin)

参数

  • pin: 需要停止方波输出的引脚

检测脉冲宽度函数

例如当要检测高电平脉冲时,pulseIn() 会等待指定引脚输入的电平变高,当变高后开始记时,直到输入电平变低,停止计时。 pulseln()函数会返回这个脉冲信号持续的时间,即这个脉冲的宽度。 函数还可以设定超时时间。如果超过设定时间,仍未检测到脉冲,则会退出pulseIn()函数并返回0。 当没有设定超时时间时,pulseIn()会默认1秒钟的超时时间。

//检测脉冲宽度函数
pulseIn()
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);

语法

  • pulseIn(pin, value)
  • pulseIn(pin, value, timeout)

参数

  • pin:需要读取脉冲的引脚
  • value:需要读取的脉冲类型,HIGH或LOW
  • timeout:超时时间,单位微秒,数据类型为无符号长整型。

返回值

  • 返回脉冲宽度,单位微秒,数据类型为无符号长整型。如果在指定时间内没有检测到脉冲,则返回0。

外部中断函数

对中断引脚进行初始化配置,以开启Arduino的外部中断功能

//中断配置函数
attachInterrupt(pin, ISR, mode)

参数

  • pin:中断引脚,部分为中断源标号
型号 编号 int.0 int.1 int.2 int.3 int.4 int.5
UNO 2 3
Mega2560 2 3 21 20 19 18
Leonardo 3 2 0 1
Due 所有IO口均可 所有IO口均可 所有IO口均可 所有IO口均可 所有IO口均可 所有IO口均可
  • ISR: 中断函数名
  • mode: 中断模式
    • LOW: 低电平触发
    • CHANGE: 变化时触发
    • RISING: 低电平变为高电平时触发
    • FALLING: 高电平变低电平时触发

示例

attachInterrupt(2, Hello, LOW); 

该语句会开启Arduino Uno的 2号引脚(中断编号0)的外部中断功能,并指定下降沿时触发该中断。 当2号引脚上电平由高变低后,该中断会被触发,Arduino即会运行Hello() 函数中的语句。

关闭中断函数

中断分离函数,关闭中断功能。

detachInterrupt(pin)

参数

  • pin: 需要禁用中断的引脚。 ### 示例

detachInterrupt(2)

外部中断寄存器模式

外部中断控制寄存器- EICRA

ISC11 ISC10 ISC01 ISC00

INT0:(ISC11&ISC10)

INT1:(ISC01&ISC00)

  • 00:低电平触发
  • 01:逻辑变化触发
  • 10:下降沿触发
  • 11:上升沿触发

外部中断屏蔽寄存器- EIMSK

INT1 INT0
  • 0:中断关闭
  • 1:中断使能外部中断标志位寄存器- EIFR
INTF1 INTF0

当中断触发标志位置高,执行ISR或向标志位写’1’时标志位重置

中断函数总结

单片机的中断可以描述为:由于某一随机事件的发生,单片机暂停在原程序的运行,转而执行另一个程序(随机事件),处理完毕之后又自动回到断点处继续执行。

其中, 中断源、主程序、中断服务程序简述如下:

  • 中断源:引起中断的原因,或能够发生中断请求的来源。
  • 主程序:单片机现在运行的程序。
  • 中断服务程序:处理中断请求的程序。
  • interrupts()noInterrupts()在Arduino中,interrupts函数和noInterrupts函数分别负责打开与关闭中断,这两个函数均为无返回值的函数,无参数。
  • attachInterrrupt(interrupt,function,mode)该函数用于设置外部中断,有三个参数,分别表示中断源、中断处理函数和触发模式,它们的具体含义如下:
    • 中断源:可选0、1,对应2或3号数字引脚。
    • 中断处理函数:指定中断的处理函数,是一段程序,当中断发生时执行该子程序部分,其中参数为函数的指针。
    • 触发模式:有四种类型-LOW(低电平触发)、CHANGE(跳变时触发)、RISING(上升沿触发)、FALLING(下降沿触发)。
    • detachInterrupt(interrupt)用于取消中断。

示例

#define EXINT_LOW				0b00//低电平触发
#define EXINT_CHANGE		0b01//逻辑变化触发
#define EXINT_FALL				0b10//下降沿触发
#define EXINT_RISE				0b11//上升沿触发
void SetInterrupt()//外部中断
{
	cli();
	// Set EXINT0(pin->PD2), EXINT1(pin->PD3) to Mode INPUT_PULLUP 
	DDRD &= ~((1 << PD2) | (1 << PD3));
	PORTD |= ((1 << PD2) | (1 << PD3));

	// Set EXINT Mode to catch FALLING EDGE 下降沿触发中断
	EICRA |= (EXINT_FALL << ISC00);
	EICRA |= (EXINT_FALL << ISC10);
	// Enable EXINT
	EIMSK |= ((1 << INT1) | (1 << INT0));//启用外部中断
sei();
}
// EXINT0(p2)
ISR(INT0_vect)
{
}

// EXINT1(p3)
ISR(INT1_vect)
{
}

串口

串口设置

Serial.begin();

说明

  • 开启串口,通常置于setup()函数中。

语法

  • Serial.begin(speed);

  • Serial.begin(speed,config);

参数

  • speed: 波特率,一般取值300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600,115200

  • config: 设置数据位、校验位和停止位。例如Serial.begin(speed,Serial_8N1); Serial_8N1中:8表示8个数据位,N表示没有校验,1表示有1个停止位。

返回

  • None

示例

void setup() 
{ 
	Serial.begin(9600); // opensserial port, sets data rate to 9600 bps 
}

Serial.end();

说明

  • 禁止串口传输函数。此时串口传输的pin脚可以作为数字IO脚使用。

语法

  • Serial.end()

参数

  • None

返回

  • None

清空串口缓存

Serial.flush();

说明

  • 1.0版本之前为清空串口缓存,现在该函数作用为等待输出数据传送完毕。如果要清空串口缓存的话,可以使用:while(Serial.read() >= 0)来代替。

语法

  • Serial.flush ()

参数

  • None

返回

  • None

while(Serial.read()>= 0)

说明

  • 因Serial.read()函数读取串口缓存中的一个字符,并删除已读字符。因此可以用这句代码来清空串口缓存。实验代码详见下文代码。

语法

  • while(Serial.read() >=0){}

参数

  • None

返回

  • None

输出串口数据

Serial.print();

说明

  • 串口输出数据函数,写入字符串数据到串口。

语法

  • Serial.print(val)

  • Serial.print(val,format)

参数

  • val: 打印的值,任意数据类型

  • format: 输出的数据格式,包括整数类型和浮点型数据的小数点位数。

示例

Serial.print(78, BIN) 得到 "1001110"
Serial.print(78, OCT) 得到 "116"
Serial.print(78, DEC) 得到 "78"
Serial.print(78, HEX) 得到 "4E"
Serial.print(1.23456, 0) 得到 "1"
Serial.print(1.23456, 2) 得到 "1.23"
Serial.print(1.23456, 4) 得到 "1.2346"
Serial.print('N') 得到 "N"
Serial.print("Hello world.") 得到 "Hello world."

Serial.println();

说明

写入字符串数据,并换行。实验代码详见下文。

语法

  • Serial.println(val)
  • Serial.println(val,format)

参数

  • val: 打印的值,任意数据类型

  • format: 输出的数据格式,包括整数类型和浮点型数据的小数点位数。

返回

  • 字节

Serial.SerialEvent();

说明

  • 串口数据准备好时触发的事件函数,即串口数据准备好调用该函数。

语法

  • Serial.serialEvent{//statements}

参数

  • statements: 任何有效的语句。

读串口缓存区数据

Serial.available();

说明

  • 判断串口缓冲器的状态函数,用以判断数据是否送达串口。注意使用时通常用delay(100)以保证串口字符接收完毕,即保证Serial.available()返回的是缓冲区准确的可读字节数。

语法

  • Serial.available();

参数

  • None

返回

  • 返回缓冲区可读字节数目

示例

void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}//clear serialbuffer
}
 
void loop() {
   if (Serial.available() > 0) {
    delay(100); // 等待数据传完
    int numdata = Serial.available();
    Serial.print("Serial.available = :");
    Serial.println(numdata);
  }
  while(Serial.read()>=0){} //清空串口缓存
}
img

Serial.read();

说明

  • 读取串口数据,一次读一个字符,读完后删除已读数据。

语法

  • Serial.read();

参数

  • None

返回

  • 返回串口缓存中第一个可读字节,当没有可读数据时返回-1,整数类型。

示例

char comchar;
 
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}/ /clear serialbuffer
}
 
void loop() {
  // read data from serial port
 
  while(Serial.available()>0){
    comchar = Serial.read();//读串口第一个字节
    Serial.print("Serial.read: ");
    Serial.println(comchar);
    delay(100); 
    }
 }
img

从实验结果可以看出:Serial.read()每次从串口缓存中读取第一个字符,并将读过的字符删除。

Serial.peek();

说明

  • 读串口缓存中下一字节的数据(字符型),但不从内部缓存中删除该数据。也就是说,连续的调用peek()将返回同一个字符。而调用read()则会返回下一个字符。

语法

  • Serial.peek();

参数

  • None

返回

  • 返回串口缓存中下一字节(字符)的数据,如果没有返回-1,整数int型

示例

char comchar;
 
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}//clear serialbuffer
}
 
void loop() {
  // read data from serial port
 
  while(Serial.available()>0){
    comchar = Serial.peek();
    Serial.print("Serial.peek: ");
    Serial.println(comchar);
    delay(100); 
    }
 }
img

从实验结果可以看出:Serial.peek()每次从串口缓存中读取一个字符,并不会将读过的字符删除。第二次读取时仍然为同一个字符。

Serial.readBytes(buffer,length);

说明

  • 从串口读取指定长度length的字符到缓存数组buffer。

语法

  • Serial.readBytes(buffer,length);

参数

  • buffer: 缓存变量

  • length:设定的读取长度

返回

  • 返回存入缓存的字符数,0表示没有有效数据。

示例

char buffer[18];
int numdata=0;
 
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}//clear serial port
}
 
void loop() {
  // read data from serial port
  if(Serial.available()>0){
      delay(100);
      numdata = Serial.readBytes(buffer,3);
      Serial.print("Serial.readBytes:");
      Serial.println(buffer);    
    }
    // clear serial buffer
  while(Serial.read() >= 0){}
  for(int i=0; i<18; i++){
        buffer[i]='\0';
    }
}

实验结果

img
img

从串口缓存读取指定长度为3的字节。

Serial.readBytesUntil(character,buffer,length);

说明

  • 从串口缓存读取指定长度的字符到数组buffer,遇到终止字符character后停止。

语法

  • Serial.readBytesUntil(character ,buffer,length);

参数

  • character : 查找的字符 (char)

  • buffer: 存储读取数据的缓存(char[] 或byte[])

  • length:设定的读取长度

返回

  • 返回存入缓存的字符数,0表示没有有效数据。

示例

char buffer[18];
char character = ','; //终止字符
int numdata=0;
 
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}//clear serialport
}
 
void loop() {
  // read data from serial port
  if(Serial.available()>0){
      delay(100);
      numdata =Serial.readBytesUntil(character,buffer,3);
      Serial.print("Serial.readBytes:");
      Serial.println(buffer);    
    }
    // clear serial buffer
  while(Serial.read() >= 0){}
  for(int i=0; i<18; i++){
        buffer[i]='\0';
    }
}

实验结果

从串口缓存中读取3个字符,当遇到","时终止读取。

Serial.readString();

说明

  • 从串口缓存区读取全部数据到一个字符串型变量。

语法

  • Serial.readString();

参数

  • None

返回

  • 返回从串口缓存区中读取的一个字符串。

示例

String comdata = "";
 
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){} //clear serialbuffer
}
 
void loop() {
  // read data from serial port
  if(Serial.available()>0){
      delay(100);
      comdata = Serial.readString();
      Serial.print("Serial.readString:");
      Serial.println(comdata);
    }
    comdata = "";
}

实验结果

img

从实验结果可以看出:Serial.readString()从串口缓存中读取字符至字符串。

Serial.readStringUntil();

说明

  • 从串口缓存区读取字符到一个字符串型变量,直至读完或遇到某终止字符。

语法

  • Serial.readStringUntil(terminator)

参数

  • terminator:终止字符(cha型)

返回

  • 从串口缓存区中读取的整个字符串,直至检测到终止字符。

示例

String comdata = "";
char terminator = ',';
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){} //clear serialbuffer
}
 
void loop() {
  // read data from serial port
  if(Serial.available()>0){
      delay(100);
      comdata =Serial.readStringUntil(terminator);
     Serial.print("Serial.readStringUntil: ");
      Serial.println(comdata);
    }
    while(Serial.read()>= 0){}
}

实验结果

img

从串口读取所有字符存放于字符串comdata,直至遇到字符","时终止读取。

Serial.parseFloat();

说明

  • 读串口缓存区第一个有效的浮点型数据,数字将被跳过。当读到第一个非浮点数时函数结束。

语法

  • Serial.parseFloat()

参数

  • None

返回

  • 返回串口缓存区第一个有效的浮点型数据,数字将被跳过。

示例

float comfloat;
 
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}//clear serialbuffer
}
 
void loop() {
  // read data from serial port
  if(Serial.available()>0){
      delay(100);
      comfloat = Serial.parseFloat();
      Serial.print("Serial.parseFloat:");
      Serial.println(comfloat);
    }
    // clear serial buffer
    while(Serial.read() >= 0){}
}

实验结果

img

从实验结果可以看出:Serial. parseFloat()从串口缓存中读取第一个有效的浮点数,第一个有效数字之前的负号也将被读取,独立的负号将被舍弃。

Serial.parseInt()

说明

  • 从串口接收数据流中读取第一个有效整数(包括负数)。

注意

  • 非数字的首字符或者负号将被跳过

  • 当可配置的超时值没有读到有效字符时,或者读不到有效整数时,分析停止

  • 如果超时且读不到有效整数时,返回0

语法

Serial.parseInt()

Serial.parseInt(charskipChar)

参数

  • skipChar用于在搜索中跳过指定字符(此用法未知)

返回

  • 返回下一个有效整型值。

示例

int comInt;
 
voidsetup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}//clear serialbuffer
}
 
void loop() {
  // read data from serial port
  if(Serial.available()>0){
      delay(100);
      comInt = Serial.parseInt();
      Serial.print("Serial.parseInt:");
      Serial.println(comInt);
    }
    // clear serial buffer
    while(Serial.read() >= 0){}
}

实验结果

img

从实验结果可以看出:Serial. parseInt()从串口缓存中读取第一个有效整数,第一个有效数字之前的负号也将被读取,独立的负号将被舍弃。

串口查找指定字符串

Serial.find()

说明

  • 从串口缓存区读取数据,寻找目标字符串target(char型)

语法

  • char target[] = ”目标字符串”;

  • Serial.find(target);

参数

  • target: 目标字符串(char型)

返回

  • 找到目标字符串返回真,否则为假

示例

char target[] ="test";
 
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}//clear serialbuffer
}
 
void loop() {
  // read data from serial port
   if(Serial.available()>0){
      delay(100);
      if( Serial.find(target)){
         Serial.print("find traget:");
         Serial.println(target);       
        }
     }
    // clear serial buffer
    while(Serial.read() >= 0){}
}

实验结果

img

串口输入字符中只要有test,函数返回真,打印出目标字符串”test”,否则返回假,不打印任何值。

Serial.findUntil(target,terminal);

说明

  • 从串口缓存区读取数据,寻找目标字符串target(char型数组),直到出现给定字符串terminal(char型),找到为真,否则为假。

语法

  • Serial.findUntil(target,terminal);

参数

  • target : 目标字符串(char型)

  • terminal : 结束搜索字符串(char型)

返回

  • 如果在找到终止字符terminal之前找到目标字符target,返回真,否则返回假。

示例

char target[] ="test";
char terminal[] ="end";
 
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}//clear serialbuffer
}
 
void loop() {
  // read data from serial port
   if(Serial.available()>0){
      delay(100);
      if( Serial.findUntil(target,terminal)){
         Serial.print("find traget:");
         Serial.println(target);
        }
     }
    // clear serial buffer
    while(Serial.read() >= 0){}
}

实验结果

img

如果串口缓存中有目标字符”test”,返回真,但如果先遇到终止字符串”end”则函数立即终止,不论字符串后面有没有目标字符”test”。

向串口写数据

Serial.write();

说明

  • 串口输出数据函数。写二进制数据到串口。

语法

  • Serial.write(val)

  • Serial.write(str)

  • Serial.write(buf, len)

参数

  • val: 字节

  • str: 一串字节

  • buf: 字节数组

  • len: buf的长度

返回

  • 字节长度

示例

void setup(){ 
Serial.begin(9600); 
}
void loop(){ 
  Serial.write(45); // send a byte with thevalue 45 
  int bytesSent = Serial.write(“hello”); //sendthe string “hello” and return the length of the string. 
}

参考链接:

https://blog.csdn.net/qq_42863355/article/details/102759709

https://blog.csdn.net/iracer/article/details/50334041

https://blog.csdn.net/GuanFuXinCSDN/article/details/104144362