当前位置: 首页 > news >正文

Arduino:UNO板的接口和应用

目录

        前置知识点:

        一、数字接口

        基本数字IO接口封装函数:

        案例:按钮控制流水灯

        高级数字IO接口封装函数:

        二、模拟接口

         模拟IO接口的封装函数:

        三、串行通信接口

        基础串行通信接口封装函数:

        案例:串行控制全彩RGB灯颜色

        IC2总线接口及应用

        案例:简易聊天器

        SPI通信接口及应用

        SPI类库函数:

        四、外部中断接口及应用

        基础外部中断函数:

        五、EEPROM概述

         基础库函数:


前置知识点:

        在TTL门电路中,把高于3.5V的电压规定为逻辑高电平,把小于0.3V的电压规定为逻辑低电平。

        上拉电阻(电阻接+5V):可以将输入引脚的不确定状态,固定在高电平的确定状态。

        下拉电阻(电阻接GND):可以将输入引脚的不确定状态,固定在高电平的确定状态。

        模拟电路:时间上和幅度上都连续变化的信号。

        数字电路:时间上和幅度上都断续变化的信号。

一、数字接口

        Arduino Uno的数字引脚编号为0~13,数字引脚可设置为INPUT(默认状态)、OUTPUT、INPUT_PULLUP三种模式。INPUT_PULLUP模式利用了Arduino微控制器自带的内部上拉电阻。

基本数字IO接口封装函数:

函数解释
digitalRead(pin)读取引脚电平
digitalWrite(pin,value)设置引脚电平
pinMode(pin,model)设置引脚模式

value:有两种取值其中HIGH为高电平,LOW为低电平。

model:有三种取值分别为INPUT、OUTPUT、INPUT_PULLUP

案例:按钮控制流水灯

代码:

int key_pin = 7;         //按键引脚
int led_first_pin = 2;  //第一个LED引脚
int num = 3;             //LED的个数
void setup() {pinMode(key_pin, INPUT);for (int i = led_first_pin; i < led_first_pin + num; i++) {pinMode(i, OUTPUT);}
}
void loop() {int val;for (int i = led_first_pin; i < led_first_pin + num; i++) {val = digitalRead(key_pin);  //如果松开按键,立刻停止流水灯的进程if (val == 0) {break;}digitalWrite(i, HIGH);delay(500);}for (int i = led_first_pin; i < led_first_pin + num; i++) {val = digitalRead(key_pin);  //如果松开按键,立刻停止流水灯的进程if (val == 0) {break;}digitalWrite(i, LOW);delay(500);}if (val == 0) {  //当松开按键时,立刻熄灭所有LEDfor (int i = led_first_pin; i < led_first_pin + num; i++) {digitalWrite(i, LOW);}}
}

电路图:

连接图: 

高级数字IO接口封装函数:

函数解释
pulseIn(pin,value,[timeout])读取一个引脚脉冲的持续时间。
pulseInLong(pin,value,[timeout])
shiftIn(dataPin,clockPin,bitOrder)串行读入数据一次一位,读入时钟引脚为高电平,读入后时钟引脚为低电平。bitOrder值有两种:MSBFIRST(高位先入),LSBFIRST(低位先入)
shiftOut(dataPin,clockPin,bitOrder,value)串行输出数据一次一位,读入时钟引脚为高电平,读入后时钟引脚为低电平。bitOrder值有两种:MSBFIRST(高位先入),LSBFIRST(低位先入)
tone(pin,frequency,duration)指定引脚输出占空比50%的方波,可以产生固定频率的PWM信号来驱动扬声器发声。
noTone(pin)停止发出声音的引脚。

二、模拟接口

          Arduino Uno的模拟引脚编号为A0~A5,可以读取模拟信号,信号范围是0~5V,Arduino板支持A/D转化,可以将0~5V的电压转化成0~1023数字引脚名称前标有~的引脚为支持PWM的输出引脚,这些引脚可以通过数字信号控制模拟信号。PWM方式指定电压是0~255,0是低,255是高,按占空比计算。占空比指的是在方形波的一个周期内,高电平信号持续时间占周期比。

        模拟引脚可设置为INPUT(默认状态)、OUTPUT、INPUT_PULLUP三种模式。INPUT_PULLUP模式利用了Arduino微控制器自带的内部上拉电阻。

 模拟IO接口的封装函数:

函数解释
analogReference(tyoe)配置模拟引脚的参考电压
analogRead(pin)读取并转化指定模拟引脚的电压
analogWrite(pin,value)通过PWM方式在指定引脚输出模拟量,调用该方法之前不需要调用pinMode()函数设置该引脚为输出。

三、串行通信接口

        波特率指的是bit/s。串口是用于传输数据的接口,代码对象为Serial,Arduino Uno通过数字引脚0(RX)和1(TX)与计算机的USB接口进行通信。

串行通信接口及其应用:

函数解释
if(Serial)测试指定串口是否准备好。
Serial.available()读取从串口接受到的字节数(存在串口缓冲区中的字节数)。
Serial.availableForWrite()不阻塞写操作,读取写到串行缓冲区的字节数。
Serial.begin(speed,[config])设置串口波特率。
Serial.end()禁止窗口通信。
Serial.find(target)在串口缓冲区查找字符串。
Serial.findUntil(target,terminal)在串口缓冲区查找起始串,读取到结束串为止。
Serial.flush()等待发送的串行数据传送完毕。
Serial.parseFloat()从串口缓存中读取第一个有效的浮点数。
Serial.parseInt()从串口缓存中读取第一个有效的整数。
Serial.peek()读取串口缓冲区中的第一个字节或字符,不对缓冲区内容修改,连续调用返回相同字符串。
Serial.print(val,[format])发送字符串数据到串口,串口显示打印。
Serial.println(val,[format])发送字符串数据到串口,串口显示打印,多了\n。
Serial.read()一次读取一个字符,读完后删除已读数据。
Serial.readBytes(buffer,length)读取输入的串口字符到缓冲区。
Serial.readBytesUntil(character,buffer,length)从串口缓冲区读数据到一个数组,读到结束字符为止,结束字符不返回。
Serial.readString()从串口缓冲区读取全部数据到字符串型变量中。
Serial.readStringUntil()从串口缓冲区读取数据到字符串型变量中,读到结束字符停止。
Serial.write()发送二进制数据到串口。
Serial.setTimeout()设置串口操作的超时时间。
Serial.serialEvent()串口数据准备好时,触发的事件函数。

具体解析

Serial.print(val,[format])/Serial.println(val,[format])

        发送字符串到串口,数据会被自动换行成字符串,串口显示打印数据 ,在使用该函数之前需要指定波特率。

        value(val):可以是字符串、整数、浮点数(默认保留2位小数)。

        format:指明数字进制,BIN二进制,OCT八进制,DEC十进制,HEX十六进制。指明小数数位,0无小数,1保留一位小数。

Serial.write(val)/Serial.write(buf,len)

        发送原始二进制到串口,数据为原始数据,串口显示打印数据 ,在使用该函数之前需要指定波特率。

        buf:多个字节组成的数组。

        len:数组长度。

        value(val):可以是字符串、整数、浮点数(默认保留2位小数)。

案例:串行控制全彩RGB灯颜色

效果视频:

电路图:

连接图:

代码:


int i;                 //保存PWM需要输入的值
String Digital = "";  //保存数字
String LED=" ";         //用于判断指定LED颜色对应的引脚
boolean stringComplete = false; //用于判断数据读取是否完成void setup()
{Serial.begin(9600);
}
void loop()
{while(Serial.available()){//读取新的字符char inChar = Serial.read();//如果是英文则存到变量LED中,如果是中文则存到inString中if(isDigit(inChar)){Digital+=inChar;}else if(inChar == '!'){stringComplete = true;Serial.println("Complete!");i= Digital.toInt();}else {LED=inChar;}}if (stringComplete){if(LED == "A"){analogWrite(9,i);}else if (LED == "B"){analogWrite(10,i);}else if (LED == "C"){analogWrite(11,i);}//清空数据,为下次读取做准备stringComplete =false;Digital= "";LED=""; } 
}//使用串口事件
//读取并分离字母和数字

IC2总线接口及应用

        I2C总线只有两根双向信号线,一根是数据线SDA(Uno板上是A4),另一根是时钟线SCL(Uno板上是A5),这两根总线均要通过上拉电阻器与正电源相连。当总线空闲时,两根信号线都是高电平

        注意:使用I2C通信需要引入Wire库。

主设备函数解释
Wire.begin([address])初始化Wire库,将I2C设备作为主设备(未指定从地址)或从设备接入总线。
Wire.beginTransmission(address)启动一个已知地址的I2C从设备通信。
Wire.write(value,[length])写数据到发送队列。length在发送数组时使用。
Wire.endTransmission()结束I2C从设备的数据发送,将发送队列的字符串发给从设备。
Wire.available()对主设备,在调用requestForm()后接收到缓冲区的字节数。
Wire.requestForm(address,quantity,stop)设置主设备的接收缓冲区大小,主设备要求从设备发送的字节数。
Wire.read()从接收缓冲区读取一个字节。
Wire.setClock(clockFrequency)修改I2C的通信时钟频率。最低100Hz。
Wire.onReceive(handler)

当从设备接收来自主设备的数据时,注册一个处理函数。

handler 函数举例:void myhandler(int num)。其中num代表从主设备接收到的字节数。

Wire.onRequest(handler)

当从设备接收来自主设备的发送数据请求时,注册一个处理函数。handler 函数举例:void myhandler()

案例:简易聊天器

效果视频:

电路图

连接图

代码:

//主设备
#include<Wire.h>
String str="";//信息存储void setup() {Wire.begin();Serial.begin(9600);
}void loop() {String value="";while(Serial.available()){char x=Serial.read();value+=x;}if(value==""){receive();}else{send(value);}}
void receive(){String value="";int flag=0;Wire.requestFrom(8,200);while(Wire.available()){flag=1;char c=Wire.read();if(c=='!'){while(Wire.available()){c=Wire.read();}break;}value+=c;}if(value!=""){Serial.println(value);//Serial.print("Receive Success!");}delay(500);
}
void send(String value){Wire.beginTransmission(8);const char* p =value.c_str();Wire.write((char *)p);Wire.endTransmission();//Serial.print("Send Success!");delay(500);
}
//从设备
#include<Wire.h>void setup() {Wire.begin(8);Serial.begin(9600);Wire.onRequest(send);Wire.onReceive(receive);
}void loop() {delay(1000);
}
void receive(int howMany){int flag=0;while(Wire.available()){flag=1;char c=Wire.read();if(c=='!'){while(Wire.available()){c=Wire.read();}}else{Serial.print(c);}}if(flag){Serial.println("");}
}
void send(){String str="";//信息存储while(Serial.available()){char x=Serial.read();//if(x=='!'){//break;//}else{str+=x;//}}str+='!';const char* p =str.c_str();Wire.write((char*)p);delay(500);
}

SPI通信接口及应用

        SPI是在物理上通过与微处理控制单元(MCU)连接的同步串行端口SSP模块来实现数据通信的,它允许MCU以全双工的同步串行方式与各种外围设备进行高速数据通信。

        SPI主要应用在可擦除只读存储器(EEPROM)、闪存(Flash)、实时时钟(RTC)、模数转换器(ADC)、数字信号处理器(DSP)以及数模转换器(DAC)中。

        SPI占芯片的四个引脚,分别为SCLK时钟信号线(用于同步数据传输)MOSI主机发送从机接收数据线(用于主机向从机发送数据)MISO主机接收从机发送数据线(用于从机向主机发送数据)SS片选线(用于确定要进行通信的主机,低电平有效)。SPI还有最重要的两项设置分别为时钟极性和时钟相位,主从设备的时钟极性和时钟相位应该保持一致

        时钟极性(CPOL或UCCKPL):用于设置传输空闲时的电平。

        时钟相位(CPHA或UCCKPH):用于设置读取数据和发送数据的时钟沿。

SPI针对这两项设置有四种模型,如下表所示。

SPI的4种模式
模式CPOLCPHA数据发送数据接收
SPI_MODE000下降沿上升沿
SPI_MODE101上升沿下降沿
SPI_MODE210上升沿下降沿
SPI_MODE311下降沿上升沿

        作为主设备的Uno板SS引脚要设置成OUTPUT,要不然自动进入从模式。Uno板的各个SPI引脚分配如下:

MOSIMISOSCK(SCLK)SSLevel
111213105V

SPI类库函数:

函数解释
SPI.begin()初始化,设置SCK、MOSI和SS为输出,将SCK和MOSI拉为低电平,SS拉为高电平等。
SPI.end()完全关闭SPI接口,释放所占用的资源。
SPI.beginTransaction(mySettings)用被定义的SPISettings对象初始化 SPI总线
SPI.endTransaction()结束一个SPI事务
SPI.transfer()和SPI.transfer16()传输、接收和发送数据
SPI.usingInterrupt(InterruptNumber)注册中断号

具体解析

SPI.transfer()和SPI.transfer16()

SPI.transfer():用于传输单个字节或多个字节。

        语法:byte receivedData = SPI.transfer(byte data);

        语法:byte receivedData = SPI.transfer(byte[ ] buffer ,int size);

SPI.transfer16():用于传输16位的数据(两个字节)。

        语法:uint16_t receivedData = SPI.transfer16(uint16_t data);

注意:一个字节占8比特。

uint16_t receivedData = SPI.transfer16(0x1234); // 发送 16 位数据 0x1234,并接收返回的 16 位数据

SPI.beginTransaction(mySettings)

SPISettings对象语法格式:

        SPISettings mySetting(speedMaximum,dataOrder,dataMode);

        参数说明:

                speedMaximum:通信的最大速度,参考SPI芯片的频率。

                dataOrder:MSBFIRST(高位先送)或LSBFIRST(低位先送)。

                dataMode:SPI_MODE0、SPI_MODE1、SPI_MODE2、SPI_MODE3。

SPISettings mySPISettings(4000000, MSBFIRST, SPI_MODE0); 
void setup() {  SPI.begin(); // 启动SPI  // 使用SPISettings  SPI.beginTransaction(mySPISettings);  // 发送数据  digitalWrite(SS_PIN, LOW); // 选择从设备  SPI.transfer(data); // 发送数据  digitalWrite(SS_PIN, HIGH); // 释放从设备  SPI.endTransaction(); // 结束SPI事务  
}   

四、外部中断接口及应用

        中断服务程序ISRs所用的函数是CPU响应特定中断时强制执行的函数,它不能有参数和任何返回值,Adruino的外部中断引脚为2、3。

基础外部中断函数:

函数解释
attachInterrupt(digitalPinToInterrupt(pin),ISR,mode)设置一个外部中断
detachInterrupt(interrupt)关闭某个已启用的中断号
interrupts()开中断
noInterrupts()停止已经设置好的中断,使程序不受中断影响。

 具体解释:

attachInterrupt(digitalPinToInterrupt(pin),ISR,mode)

digitalPinToInerrupt(pin):将实际的数字引脚转换为指定的中断号。

ISR:中断服务函数名。

mode:定义中断触发方式,定义如下。

        LOW:当引脚为低电平时,触发中断。

        CHANGE:当引脚变化时,触发中断。

        RISING:当引脚产生低到高的跳变时,触发中断。

        FALLING:当引脚产生高到低的跳变时,触发中断。

        HIGH:当引脚为高电平时,触发中断。

五、EEPROM概述

        Arduino板基于AVR的微控制器包含EEPROM,以字节为单位进行数据读写,掉电不会丢失数据,用来记录和保存参数。

 基础库函数:

函数解释
EEPROM.read(address)从EEPROM的对应地址读取一个字节。
EEPROM.write(address,value)在指定的地址写入一个字节的数据。
EEPROM.update(address,value)在指定的地址更新一个字节的数据。
EEPROM.put(address,data)在指定的地址更新任意类型的数据或对象。
EEPROM.get(address,data)从EEPROM中读取任意类型的数据或对象。


http://www.mrgr.cn/news/93019.html

相关文章:

  • unity学习62,尝试做第一个小游戏项目:flappy bird
  • Spring MVC 返回数据
  • CentOS 7.9 安装 ClickHouse 文档
  • python学习第三天
  • 【Transformer优化】什么是稀疏注意力?
  • ubuntu离线安装nvidia-container-runtime
  • NUDT Paper LaTeX 模板使用
  • Solana 核心概念全解析:账户、交易、合约与租约,高流量区块链技术揭秘!
  • GitLab常用操作
  • 第二节:基于Winform框架的串口助手小项目---创建界面《C#编程》
  • HarmonyOS NEXT开发进阶(十一):应用层架构介绍
  • unity pico开发二:连接头盔,配置手柄按键事件
  • 【和春笋一起学C++】逻辑操作符和条件操作符
  • MySQL快速搭建主从复制
  • 【C++指南】一文总结C++类和对象【中】
  • Nginx1.19.2不适配OPENSSL3.0问题
  • NL2SQL-基于Dify+阿里通义千问大模型,实现自然语音自动生产SQL语句
  • 小白向:如何使用dify官方市场“ECharts图表生成”工具插件——dify入门案例
  • 【动手学强化学习】番外2-多智能体强化学习算法框架之“MARLlib”学习
  • PPT 小黑第38套