Arduino是一款时尚流行的开源软件&硬件平台,其开发入门简单,是众多DIY玩家及创客的首选。目前,Arduino也开始进入了中小学的创客课程。然而在与很多玩家、学生或是创客老师交流的过程中,总能听到这样的疑问:Arduino到底是不是单片机?Arduino和单片机有什么区别?玩Arduino是不是必须与单片机结合?Arduino是不是只能给小朋友或者DIY玩家玩玩,做不了产品?为了诉清这些疑问,特此发表一下我的见解。

首先给出一个明确的回答:玩Arduino就是在玩单片机,和玩“51”或“STM32”一样,都是玩单片机。既然都是单片机,那么它们的开发过程其实都是一样的,都要经过:编程—编译—烧录的过程。而它们最大的差异就在编程这个环节,而后面的编译和烧录都是一样的,也就是说,无论你用什么编程:C语言、汇编、图形,都要经过编译,得到由0和1组成的机器码,最后再把机器码烧录到单片机内部,单片机才能执行我们设计的程序。下面我们开始深入并且通俗地来说说Arduino。

Arduino系列的开发板,我们常用的NANO及UNO板,板载的单片机就是ATMEL(爱特梅尔)的mega328p单片机,而MEGA板则板载mega2560单片机,我们通常叫它AVR单片机。下面围绕NANO板来论述。

Arduino NANO板

ATMEL MEGA328P单片机

从上图我们可以看到,NANO板上的引脚(端口)旁边都标注一些编号:D2,D3…D13;A0,A1…A7;TX1、RX0;而这些固定编号的引脚都通过电路板上的“走线”一一对应地连接到mega328p单片机的引脚,这个“对应关系”我们也可以从Arduino官方提供的电路原理图上看到,如下图:

NANO板—mega328p引脚映射图

图中“红色框”部分为NANO板上标注出的引脚编号,它的顺序由“Arduino”定义;“蓝色框”部分为mega328p芯片的引脚编号,这个由芯片生产厂商定义;“绿色框”为mega328p单片机的引脚分组骗号,也由芯片生产厂商定义。下面给出mega328p的引脚图:

MEGA328P单片机引脚图

综合以上两图,我们可以看到完整的引脚映射。例如,NANO板的D2引脚连接的是mega328p芯片的第32号引脚,该引脚属于mega328p单片机引脚分组的D组第2号引脚(PD2)。这里的引脚分组,对应的则是芯片内部引脚控制寄存器,D组的8个引脚(PD0-PD7)由一个寄存器进行控制,也就是说,如果我们要控制PD0-PD7中任意一个引脚,都要对D组的寄存器进行赋值控制。下面我们来看看用NANO板的D2引脚来控制一个LED闪烁(假设高电平点亮,也就是将D2引脚的电平设置为高,且延时函数delay()已定义),不同的代码实现。

首先是Arduino IDE(Arduino官方开发环境)的C代码:

int led_0= 2;

pinMode(led_0,OUTPUT);

digitalWrite(led_0,HIGH);

delay(1000);

digitalWrite(led_0,LOW);

delay(1000);

或者: int led_0= 2;

pinMode(led_0,OUTPUT);

digitalWrite(led_0, 1);

delay(1000);

digitalWrite(led_0, 0);

delay(1000);

接下来是AVR寄存器操作C代码:

DDRD |= 0x04;

PORTD |= 0X04;

delay(1000);

PORTD &= ~0X04;

delay(1000);

或者: DDRD |= BIT(2);

PORTD |= BIT(2);

delay(1000);

PORTD &= ~BIT(2);

delay(1000);

最后来看看图形代码(Krobot-啃萝卜):

以上几种代码都实现了NANO板D2引脚控制的LED闪烁的效果。但其中最为直观的就是图形代码,其次就是Arduino IDE中的C代码。在图形编程中我们只要确定LED连接到了板上的几号引脚,然后拖动相应的图标并设置一下参数就可以完成程序编写;而在Arduino IDE中,是要稍有英语基础,也可以直观的对板上的引脚编号进行“数字写”操作(digitalWrite)就可以完成程序的编写。而直接操作AVR寄存器,则需要结合芯片引脚图,确定需要操作的引脚编号,然后从芯片手册中查找到相应的寄存器,对相应的寄存器进行操作才能实现同样的效果,而这也就是单片机编程最为复杂繁琐的地方,成百上千的寄存器,以及寄存器中各数据位的定义无形成为了入门单片机的一个门槛,让很多初学者“望而却步”。

那么,这几种代码之间存在着怎样的联系呢?实际上,AVR指令集编写的代码是图形和Arduino IDE代码的核心。我们首先来说说ArduinoIDE。Arduino的创始团队首先建立硬件平台,这个平台包括所有Arduino所有系列的开发板,并且这些开发板的引脚定义建立了一个“统一”的机制;然后根据芯片型号及引脚定义机制,基于AVR指令集编写了所有操作的底层代码,这些代码中提供了我们可以访问或调用的函数接口,让开发者避开了繁琐的寄存器操作,从而单片机的编程开发变得简单了很多。例如UART串口(serial)的操作,我们在ArduinoIDE中开发,只需知道我们要使用的串口编号是多少(NANO、UNO默认只有串口0,而mega则有4个串口:serial0-serial3),然后简单的在初始化setup()中调用函数Serial.begin(波特率)即可完成串口启动及波特率的设置,而其背后实质上已经对相关的寄存器进行了操作。因此,Arduino实质上是包括了一系列硬件系统的定义及打包好的底层驱动程序,这些打包好的底层驱动程序,我们可以称它们为“库”或者“库函数”,Arduino也可以看作是AVR单片机的“库开发”,而对硬件系统的定义及库函数也保证了同一个代码可以快速地“移植”到不同的单片机中,例如上面的代码在可以在NANO中运行也可以在mega中运行,只要保证LED接到板上标注的2号引脚,在烧录程序之前正确设置“开发板型号”就可以在不同的板上实现同样的效果。以上所提到的“库”称为Arduino官方库即底层驱动,我们可以在ArduinoIDE根目录的文件夹中找到一个名为“hardware”(即硬件)的文件夹,里面存放的就是底层驱动代码。同时,在这个根目录下,还有一个文件夹:“libraries”,即“库”,这个库则是基于底层库二次开发的或是基于AVR指令集开发的非官方库函数,也称为第三方库,主要是一些外部传感器、模块的驱动程序,这部分库函数我们可以从网络上下载别人写好的,也可以自己写,写好的库函数按照一定的规则存放在这个文件夹中就可以使用了。下面以mpu6050陀螺仪的驱动为例,再次说明。

首先,官方驱动库中提供了I2C总线的驱动库(即Wire库),然后我们可以在网上找到一个基于Wire库开发的I2C读写操作的库和一个基于I2C读写操作库开发的mpu6050驱动库。在使用mpu6050时,我们的重点是得到三轴加速度值及三轴角速度值,而要得到这6个数据,我们要通过I2C总线访问陀螺仪内部的12个寄存器,并且在上电初始化时,还必须通过I2C总线去设置陀螺仪内部的一些寄存器,才能从陀螺仪获得正确的数据,而这一系列操作是比较繁琐的,对于初学者即便是使用了官方的驱动库,也会被I2C的时序搞得晕头转向。而有了mpu6050对应的库函数以后,我们甚至可以不知道I2C是个啥,也不知道陀螺仪里有些什么“稀奇古怪”的寄存器,就稀里糊涂地得到了陀螺仪的数据。这就是库的“魅力”所在。

而图形编程,也是建立在“库”的基础之上的,有些图形化编程界面是ArduinoIDE的插件,有些图形编程软件的文件里,都附带一个ArduinoIDE。对于这一块,我了解得也不是足够深入,因此不作过多的讨论了。

总而言之,玩Arduino就是玩单片机,玩的就是基于库函数的AVR单片机开发,而目前Arduino官方也推出了搭载ARM内核单片机的开发板及相关的库函数,例如DUE板(引脚与MEGA2560板一致)、STAR OTTO板(国内暂未上市,搭载STM32F469单片机),这些都是32位的单片机,运算处理速度比我们常用的那些板(NANO、UNO、mega2560)要高出很多,借助“库”的帮助,我们依然可以轻松入门。

Arduino mega2560板

Arduino DUE板

Arduino STAR OTTO板

库函数给入门开发带来了极大的方便,那么,我们是不是可以完完全全地依赖“库”呢?我的看法是:如果只是搞一搞简单的小制作,做一些简单的流程化控制,搞搞科普展示或者青少年的简单体验课程,那么依靠图形或是完完全全地依赖库,是没有任何问题的。但如果要做一些较为复杂的产品设计,那还是应该深入地学习一下,即便不直接操作寄存器,也应该了解一个库是如何编写的,库里有哪些函数、变量是可以调用的,哪些函数、变量是库“私有”的(不可调用),它的执行效率如何,再者,还应该深入了解一下:系统时钟、I2C总线时序、SPI总线时序、UATR串口(Serial)、外部中断、定时中断及计数、ADC功能(模拟-数字转换),DAC(数字-模拟转换)及PWM(脉冲宽度调制)。掌握了这些知识就可以对自己的开发有一个更好的把握,就可以决策哪些地方可以用什么库,哪些地方需要自己写驱动,哪些库可以进行怎样的修改,或者自己该如何写库,以满足设计要求。系统实时性是单片机开发的一个重要指标,比如无人机的飞控系统、自平衡小车控制系统,都有很高的实时性及时序要求,这是算法实现的基本保障,而如果忽略了这个问题,不管用什么单片机、用什么编程,最终得出只能是被视为“玩玩”的东西。就性能而言,Arduino使用的AVR系列单片机,在8位机中算是比较强大的了,处理速度和内部存储空间都是比较“宽裕”的。其实很多电子产品中都有AVR的“身影”,例如很多航模无人机使用的无刷电机控制器,锂电池保姆充电器,还有大名鼎鼎、风靡全球的开源无人机飞控系统—APM都是AVR“干的”,而且APM还是基于Arduino开发的。当然了,AVR跟STM32或NXP系列相比,那肯定是相差甚远的,要知道那是32位的,而且系统时钟频率一般都72M或更高,运算处理速度是相当快的,而且还有更丰富的片上资源。但是,并不是所有系统都需要这样高性能的芯片,为项目选择合适的芯片才是最好的。

最后总结,玩Arduino,就是玩单片机。至于“玩”到什么程度,完全取决于自己的需求。如果玩得深入,Arduino可以帮助我们深入地理解“库”的概念,从而顺利过渡到STM32的库开发学习。

以上就是我个人的理解,有不对的地方敬请批评指正,共同学习,共同进步。

arduino i2c 如何写16位寄存器_Arduino之我见相关推荐

  1. arduino i2c 如何写16位寄存器_Arduino只是拿来玩的?你错了!教你用它自制一个非常实用的小产品|智能灌溉控制器...

    利用动态水循环,具有下雨探测,日出探测功能,智能灌溉你的院子或花园. 一定要看文章最后哦,结尾有惊喜! 部件和材料 Arduino NANO开发板 1块 IO扩展板 1块 IO扩展模块包 1套 app ...

  2. arduino i2c 如何写16位寄存器_arduino入门

    硬件:Arduino Uno是基于ATmega328P(数据表)的微控制器板.它具有14个数字输入/输出引脚(其中6个可用作PWM输出),6个模拟输入,工作电压5v,输入电压7-12v. 串行:0(R ...

  3. arduino i2c 如何写16位寄存器_基于STM32使用I2C读取传感器数据

    撑腰会儿:I2C通信协议介绍​zhuanlan.zhihu.com 上文介绍了I2C协议的基本结构,今天,使用STM32和LM75A温度传感器来实现I2C读取信息. 首先,为了使用I2C读取传感器测量 ...

  4. arduino i2c 如何写16位寄存器_树莓派3B开发Go语言(二)寄存器版本GPIO

    作者:爪爪熊 链接:https://www.jianshu.com/p/0495c0554a63 來源:简书 之前将go语言的运行环境给搭建起来了,但是没有开始真正的试试Go 语言操作树莓派硬件的效果 ...

  5. I2C总线时序图: 8位设备地址 16位寄存器地址 16位数据

    有关I2C总线时序,下面的文章写得很好,推荐阅读 https://www.cnblogs.com/BitArt/archive/2013/05/28/3103917.html#commentform ...

  6. 汇编语言——16位寄存器实现32位二进制数左移4位。

    问题描述 16位寄存器实现32位二进制数左移4位. 源代码 MOV CL, 04 SHL DX, CL MOV BL, AH SHL AX, CL SHR BL, CL OR DL, BL 说明:  ...

  7. msp430f2618写16位双通道 SPI接口DA DAC8552 精确度超高

    直接上代码,我就不做太多解释了.. #include "msp430x26x.h" #include "DAC8552.H" //=============== ...

  8. kernel:max92xx加串解串示例代码[可读取16位寄存器地址]

    主要逻辑函数就是max92xx_i2c_read/write /*!* @file max92xx.c** @brief max92xx GMSL1 DSI Serializer/DESerializ ...

  9. 16位汇编相关寄存器

    文章目录 1 寄存器的组成部分 1.1 8086寄存器组成 1.2 8086处理器是小端模式 2 X86 16位汇编所涉及的寄存器 3 寄存器的用法 3.1 DS和ES 3.2 CS和IP 1 寄存器 ...

最新文章

  1. 给老婆写个Python教程
  2. 黑马程序员-JAVA基础-IO流之流操作规律及读写转换流
  3. 基于android的家庭财务通 .apk,毕业论文(设计)基于Android的家庭财务管家的设计与实现.doc...
  4. opencv mat相关资料整理
  5. linux开机自动打开全屏,如何修改Linux开机启动logo并使其全屏显示?
  6. MSDN Magazine推出Custom Report Item示例ProgressTracker CRI
  7. go使用for...range遍历数组
  8. 百练4148:生理周期
  9. ROS 常用命令汇总(不定期更新)
  10. 控制台服务编写 Linux,一步步搭建ubuntu server console(控制台,字符模式)开发环境...
  11. wordpress WBOLT 百度推送管理 3.4.6 Pro
  12. 各种设计模式对比及编程思想总结
  13. 【软件项目管理】需求规格说明可以包括系统的运行环境
  14. Android自定义PreferenceScreen的Layout布局,并获取控件
  15. javascript获取浏览器窗口大小 获取屏幕,浏览器,网页高度宽度
  16. H2O机器学习:一种强大的可扩展的人工智能和深度学习技术
  17. 文本文档写html图片显示不出来,word文档几种不显示图片的解决方法
  18. PSPACE完全性学习笔记
  19. 工作上遇到问题,但又不敢问领导,该怎么办
  20. 13_android编译ijkplayer

热门文章

  1. click F5 refresh button on detail page - how to get the usable OData model
  2. GM6 PageSet request didn't have target application url
  3. SAP ui5 sap.ui.getCore().getUIArea
  4. SAP UI5 /UI5/IF_UI5_REP_PERSISTENCE - why I cannot deploy app to GM6
  5. Fiori 里周期性检查window size大小的变化
  6. CRM里把用户分配给一个position的执行调试
  7. ABAP Access global variable in another program
  8. linux中grep命令查找目录下,linux中查找grep与find命令的使用
  9. db2有主键时默认hash分区_彻底搞懂 MySQL 分区!
  10. 有效的数独Python解法