关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

闪烁的小灯

先看一个是arduino原生库点亮一个小灯的程序实现:

关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

一个发光二极管一端接1k的电阻再接地,另外一端接在arduino的13号口,当13口输出高电平的时候灯亮,当13口输出低电平的时候灯熄灭,原理就是这个简单,写过avr c代码的同学肯定都知道,一般对某个端口或者引脚操作都是使用DDRX,PORTX,PINX来操作的,为什么这里可以直接用数字来操作呢?是怎么对AVR做二次封装的?

我们先来看一个最常见的函数:

pinMode(pin, mode)

  • pinMode()函数用于将特定针脚配置为输入或输出。
  • pin - 你希望设置模式的引脚编号
  • mode - INPUT,OUTPUT或INPUT_PULLUP
  • 输入为INPUT;可以使用INPUT_PULLUP模式启用内部上拉电阻。此外,INPUT模式显式禁止内部上拉。输出为OUTPUT,注意INPUT和OUTPUT都要全部大写

看一下pinMode(pin, mode)在库中的位置:

关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

看一下函数原型:

关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

arduino本质上是一个AVR单片机,对于AVR单片机对某个端口或者引脚操作需要使用DDRX,PORTX,PINX来操作的,具体可参考教程《 》,继续我的疑问为什么这里可以直接用数字来操作呢?

在这里可以看出主要函数就是这4个了:digitalPinToBitMask,digitalPinToPort,portModeRegister,portOutputRegister。

看下面几个宏:在arduino.h文件中定义的:

关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

先看一下:函数pgm_read_byte,pgm_read_word。

其实就是在GCCAVR读取flash常量到ram变量中。

关键的地方不是pgm_read_byte这个函数,而是pgm_read_byte这个函数里面的参数:digital_pin_to_port_PGM,digital_pin_to_bit_mask_PGM,pgm_read_word里面的参数:port_to_output_PGM, port_to_mode_PGM。

说到这个我们得要看另外一点知识了,要看看Pins_arduino.h这个文件,因为这几个函数都在这个.h里面定义的。

针对不同芯片定义的引脚头文件------Pins_arduino.h

arduino已经支持很多种板类型,在arduino ide的下拉菜单中我们就可以看到很多了。单片机代码中,需要对各个管脚,各种定时器,接口进行操作,由于不同单片机管脚和功能不一样,导致代码不能共用。那么问题来了?arduino是怎么做到用一份代码就可以分别在不同类型的板子跑起来呢?

其实arduino实现了一个框架,针对不同的芯片,把相同的部分提供一套通用机制,不同的部分抽象出来,制定一套规则,只要所有的芯片都遵守这个规则,就可以正常的工作起来。原理是简单的了。

再来看Pins_arduino.h文件:

关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

这就是为啥有这么多个Pins_arduino.h文件的原因。那么我们需要看哪个呢?这就需要看boards.txt文件了,我使用的是Arduino UNO 板子那么有:

关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

这就很明显了我就需要找standard文件夹下面的Pins_arduino.h文件。

那我们就来看一下这个头文件里面的部分内容:文件太长就不贴出来了。

在回到开始,主要看看digital_pin_to_port_PGM,digital_pin_to_bit_mask_PGM,port_to_output_PGM,port_to_mode_PGM这几个参数。

先看arduino与ATmega328p的管脚连接图:ATmega328p一般是32管脚的,我在网上没有找到,找一个ATmega328管脚图,基本上是一样的,

关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

  • digital_pin_to_port_PGM
关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

这其实就我们在arduino uno板子上看到的20个端口,0~7 是PD口的,8~13为PB口的,A5~A0是PC口的。把他们都放在一个数组里面,这个数组存放的管脚信息,通过映射我们就知道了arduino上的口操作的是哪个端口。是PD还是PB还是PC端口。

  • digital_pin_to_bit_mask_PGM
关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

前面我们知道是哪个端口了,但是我们还不确定是这个端口的哪一位,我知道是D口了,但是我不知道是D几口,那么这个数组存放的就是端口的位。D端口的8位全部用完,B端口用了6位,C端口也用了6位。

  • port_to_output_PGM
关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

我们知道avr输出高低电平是PORTxn控制的。那就把它放进来就好了。

  • port_to_mode_PGM
关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

avr的io口是一个标准的双向口,一个管脚到底是输出还是输入是由DDRxn控制。

顺便在说一下这个:

  • port_to_input_PGM
关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

avr的输入,其实就是对管脚电平的检测了。

整体来说arduino是先把各个芯片的端口和引脚的映射关系都定义成几个表格,这几个表格把引脚所在的位置作为索引,在使用的时候通过引脚位置,通过查表得到对应的功能寄存器。然后就可以设置输出输入模式,设置输入输出电平,对于arduino来说只需要告诉它需要操作哪个引脚,以及要怎么操作。而不需要去关心这个引脚在哪个port上,是在PORTA还是在PORTB,更不用关心这个芯片是什么型号。

系统的串一下pinMode(pin, mode)函数

看注释:

关于Arduino 对端口或引脚编程可以直接用数字来操作的分析

看到这是不是明朗了很多,那就对了,哈哈



分享到:


相關文章: