我们使用arduino开发时,最长遇到的是对端口管脚的拉高拉低,代码如下
void setup() {pinMode(13,OUTPUT);
}void loop() {digitalWrite(13,HIGH);
}
上面还最简单io控制代码,其中引脚我们使用了数字13,但是这个13对应着哪个引脚呢?我们一般会有开发板的示意图
上面的Dx就对应着引脚数字。这个还好理解。
但是当我们使用STM32开发板时候怎么对应呢?我们知道STM32不是简单的GPIO+数字的方式,而是还有ABCDE等,这样我们就不能简单的认为1对应GPIO1了。
下面我们根据源码分析一下这个数字是如何转为引脚地址的。
ESP8266
esp8266的简单
在3.1.2\cores\esp8266\core_esp8266_wiring_digital.cpp文件中有定义
volatile uint32_t* const esp8266_gpioToFn[16] PROGMEM = { &GPF0, &GPF1, &GPF2, &GPF3, &GPF4, &GPF5, &GPF6, &GPF7, &GPF8, &GPF9, &GPF10, &GPF11, &GPF12, &GPF13, &GPF14, &GPF15 };
这里的GPFx就是真正的引脚地址,非常规律的从0到15,就好像特意为arduino设计的一样。
STM32
stm32就是我说的无法一一对应的问题了,我们先来跟踪代码,在pinMode函数中有一个转换的函数
void pinMode(uint32_t ulPin, uint32_t ulMode)
{PinName p = digitalPinToPinName(ulPin);
这一行就是引脚转换的函数,继续跟踪到2.7.1\cores\arduino\pins_arduino.h文件
#define digitalPinToPinName(p) ((((uint32_t)(p) & PNUM_MASK) < NUM_DIGITAL_PINS) ? \(PinName)(digitalPin[(uint32_t)(p) & PNUM_MASK] | ((p) & ALTX_MASK)) : NC)
这里实际上是将引脚的数字p当做了digitalPin数组的角标,那么我们就需要知道数组的内容就知道引脚数字和引脚地址的对应关系了。
这个数组有很多个,因为stm32有很多系列,每个系列的不同封装可能包含的引脚都不一样,所以对于每个系列的每个封装都要进行各自的定义。我们以F103R系列为例,看一下数组的定义
在文件2.7.1\variants\STM32F1xx\F103R(C-D-E)T\variant_generic.cpp
// Digital PinName array
const PinName digitalPin[] = {PA_0, // D0/A0PA_1, // D1/A1PA_2, // D2/A2PA_3, // D3/A3PA_4, // D4/A4PA_5, // D5/A5PA_6, // D6/A6PA_7, // D7/A7PA_8, // D8PA_9, // D9PA_10, // D10PA_11, // D11PA_12, // D12PA_13, // D13PA_14, // D14PA_15, // D15PB_0, // D16/A8PB_1, // D17/A9PB_2, // D18PB_3, // D19PB_4, // D20PB_5, // D21PB_6, // D22PB_7, // D23PB_8, // D24PB_9, // D25PB_10, // D26PB_11, // D27PB_12, // D28PB_13, // D29PB_14, // D30PB_15, // D31PC_0, // D32/A10PC_1, // D33/A11PC_2, // D34/A12PC_3, // D35/A13PC_4, // D36/A14PC_5, // D37/A15PC_6, // D38PC_7, // D39PC_8, // D40PC_9, // D41PC_10, // D42PC_11, // D43PC_12, // D44PC_13, // D45PC_14, // D46PC_15, // D47PD_0, // D48PD_1, // D49PD_2 // D50
};
如此可以看出每个引脚数字对应的引脚是什么了,例如我们使用digitalWrite(0,HIGH);实际上就是将GPIOA0引脚拉高了。
ESP32
在esp32中我们使用和ESP8266相似的方式
这里的GPIOx就对应这引脚数字。
我们同样在代码中找到相似的转换的地方,我们发现这个单片机设置引脚的方式已经被封装在了ESP-IDF(Espressif IoT Development Framework)中。引脚数字 pinNumber
,然后将其转换为 gpio_num_t
类型的 GPIO 矩阵索引 gpioPin
。最后,使用 gpio_config
函数来配置该引脚的模式。也就是说我们需要找到gpio_num_t
类型的定义,就可以找到引脚的对应关系。
在2.0.11\tools\sdk\esp32c3\include\hal\include\hal\gpio_types.h文件中
#if CONFIG_IDF_TARGET_ESP32
typedef enum {GPIO_NUM_NC = -1, /*!< Use to signal not connected to S/W */GPIO_NUM_0 = 0, /*!< GPIO0, input and output */GPIO_NUM_1 = 1, /*!< GPIO1, input and output */GPIO_NUM_2 = 2, /*!< GPIO2, input and output */GPIO_NUM_3 = 3, /*!< GPIO3, input and output */GPIO_NUM_4 = 4, /*!< GPIO4, input and output */GPIO_NUM_5 = 5, /*!< GPIO5, input and output */GPIO_NUM_6 = 6, /*!< GPIO6, input and output */GPIO_NUM_7 = 7, /*!< GPIO7, input and output */GPIO_NUM_8 = 8, /*!< GPIO8, input and output */GPIO_NUM_9 = 9, /*!< GPIO9, input and output */GPIO_NUM_10 = 10, /*!< GPIO10, input and output */GPIO_NUM_11 = 11, /*!< GPIO11, input and output */GPIO_NUM_12 = 12, /*!< GPIO12, input and output */GPIO_NUM_13 = 13, /*!< GPIO13, input and output */GPIO_NUM_14 = 14, /*!< GPIO14, input and output */GPIO_NUM_15 = 15, /*!< GPIO15, input and output */GPIO_NUM_16 = 16, /*!< GPIO16, input and output */GPIO_NUM_17 = 17, /*!< GPIO17, input and output */GPIO_NUM_18 = 18, /*!< GPIO18, input and output */GPIO_NUM_19 = 19, /*!< GPIO19, input and output */GPIO_NUM_20 = 20, /*!< GPIO20, input and output */GPIO_NUM_21 = 21, /*!< GPIO21, input and output */GPIO_NUM_22 = 22, /*!< GPIO22, input and output */GPIO_NUM_23 = 23, /*!< GPIO23, input and output */GPIO_NUM_25 = 25, /*!< GPIO25, input and output */GPIO_NUM_26 = 26, /*!< GPIO26, input and output */GPIO_NUM_27 = 27, /*!< GPIO27, input and output */GPIO_NUM_28 = 28, /*!< GPIO28, input and output */GPIO_NUM_29 = 29, /*!< GPIO29, input and output */GPIO_NUM_30 = 30, /*!< GPIO30, input and output */GPIO_NUM_31 = 31, /*!< GPIO31, input and output */GPIO_NUM_32 = 32, /*!< GPIO32, input and output */GPIO_NUM_33 = 33, /*!< GPIO33, input and output */GPIO_NUM_34 = 34, /*!< GPIO34, input mode only */GPIO_NUM_35 = 35, /*!< GPIO35, input mode only */GPIO_NUM_36 = 36, /*!< GPIO36, input mode only */GPIO_NUM_37 = 37, /*!< GPIO37, input mode only */GPIO_NUM_38 = 38, /*!< GPIO38, input mode only */GPIO_NUM_39 = 39, /*!< GPIO39, input mode only */GPIO_NUM_MAX,
/** @endcond */
} gpio_num_t;
如此一看,esp32更像是为了arduino的使用方式设计的了。
只有STM32需要去找到每个的对应关系。