当前位置:网站首页>2. GPIO related operations
2. GPIO related operations
2022-07-06 03:25:00 【rou252051452】
1、 summary
STM32 Of GPIO Operations are classified into RTT Of pin In the device , In this paper, the reference RTT About PIN Relevant instructions of the equipment (RT-Thread Document center ) Write and test . It involves the following aspects
- GPIO Pin acquisition
- GPIO Output control
- GPIO Input to get
- GPIO External interrupt implementation of
2、 Acquisition of pin number
RT-Thread The pin number provided should be distinguished from the pin number of the chip , They are not the same concept , The pin number is determined by PIN Device driver definition , Related to specific chips . The official provided 3 There are three ways to get the pin number :
- Use API
- Use a macro to define
- View driver file
2.1 Drive file update
API Get the method through the function rt_pin_get Realization , The procedure is as follows
rt_base_t rt_pin_get(const char *name)
{
RT_ASSERT(_hw_pin.ops != RT_NULL);
RT_ASSERT(name[0] == 'P');
if(_hw_pin.ops->pin_get == RT_NULL)
{
return -RT_ENOSYS;
}
return _hw_pin.ops->pin_get(name);
}
Check the initialization phase pair _hw_pin->ops The settings of are as follows
const static struct rt_pin_ops _stm32_pin_ops =
{
stm32_pin_mode,
stm32_pin_write,
stm32_pin_read,
stm32_pin_attach_irq,
stm32_pin_dettach_irq,
stm32_pin_irq_enable,
};
struct rt_pin_ops
{
void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode);
void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_base_t value);
int (*pin_read)(struct rt_device *device, rt_base_t pin);
rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_int32_t pin,
rt_uint32_t mode, void (*hdr)(void *args), void *args);
rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_int32_t pin);
rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled);
rt_base_t (*pin_get)(const char *name);
};
Above ops Not in China pin_get How to implement the function , So we need to update drv_gpio Driver file . Use C:\RT-ThreadStudio\repo\Extract\Board_Support_Packages\RealThread\STM32H750-RT-ART-Pi\1.2.1\libraries\drivers Of drv_gpio.c Replace the driver file in the directory , Synchronize updates .h file . Check the updated content as follows
const static struct rt_pin_ops _stm32_pin_ops =
{
stm32_pin_mode,
stm32_pin_write,
stm32_pin_read,
stm32_pin_attach_irq,
stm32_pin_dettach_irq,
stm32_pin_irq_enable,
stm32_pin_get,
};
2.2 Realization way
2.2.1 Use API
static rt_uint32_t reset_pin = 0;
reset_pin = rt_pin_get("PF.9");
rt_base_t rt_pin_get(const char *name)
{
RT_ASSERT(_hw_pin.ops != RT_NULL);
RT_ASSERT(name[0] == 'P');
if(_hw_pin.ops->pin_get == RT_NULL)
{
return -RT_ENOSYS;
}
return _hw_pin.ops->pin_get(name);
}
As shown above ,rt_pin_get First, check whether the input string is a letter P start , The function finally called is _hw_pin.ops->pin_get(name); The contents are as follows :
static rt_base_t stm32_pin_get(const char *name)
{
rt_base_t pin = 0;
int hw_port_num, hw_pin_num = 0;
int i, name_len;
name_len = rt_strlen(name);
if ((name_len < 4) || (name_len >= 6)) // Perform string length verification PA.0 PA.15 The shortest 4, The longest 5
{
return -RT_EINVAL;
}
if ((name[0] != 'P') || (name[2] != '.')) // The first string must be P The third must be .
{
return -RT_EINVAL;
}
if ((name[1] >= 'A') && (name[1] <= 'Z')) // The port range is A-Z
{
hw_port_num = (int)(name[1] - 'A'); // Port number calculation ,A-Z Convert to 0-25
}
else
{
return -RT_EINVAL;
}
for (i = 3; i < name_len; i++) // According to the... Of the string 4 Number conversion PA.0=0 PA.15 = 15
{
hw_pin_num *= 10;
hw_pin_num += name[i] - '0';
}
pin = PIN_NUM(hw_port_num, hw_pin_num); // Process the last pin number
return pin;
}
Finally, call the macro definition as follows to obtain the pin number
#define PIN_NUM(port, no) (((((port) & 0xFu) << 4) | ((no) & 0xFu)))
The calculation results are shown in the following table , follow-up IO And so on
name | port | no | result | name | port | no | result |
PA.0 | 0 | 0 | 0 | PC.0 | 2 | 0 | 32 |
PA.1 | 0 | 1 | 1 | PC.1 | 2 | 1 | 33 |
PA.2 | 0 | 2 | 2 | PC.2 | 2 | 2 | 34 |
PA.3 | 0 | 3 | 3 | PC.3 | 2 | 3 | 35 |
PA.4 | 0 | 4 | 4 | PC.4 | 2 | 4 | 36 |
PA.5 | 0 | 5 | 5 | PC.5 | 2 | 5 | 37 |
PA.6 | 0 | 6 | 6 | PC.6 | 2 | 6 | 38 |
PA.7 | 0 | 7 | 7 | PC.7 | 2 | 7 | 39 |
PA.8 | 0 | 8 | 8 | PC.8 | 2 | 8 | 40 |
PA.9 | 0 | 9 | 9 | PC.9 | 2 | 9 | 41 |
PA.10 | 0 | 10 | 10 | PC.10 | 2 | 10 | 42 |
PA.11 | 0 | 11 | 11 | PC.11 | 2 | 11 | 43 |
PA.12 | 0 | 12 | 12 | PC.12 | 2 | 12 | 44 |
PA.13 | 0 | 13 | 13 | PC.13 | 2 | 13 | 45 |
PA.14 | 0 | 14 | 14 | PC.14 | 2 | 14 | 46 |
PA.15 | 0 | 15 | 15 | PC.15 | 2 | 15 | 47 |
PB.0 | 1 | 0 | 16 | PD.0 | 3 | 0 | 48 |
PB.1 | 1 | 1 | 17 | PD.1 | 3 | 1 | 49 |
PB.2 | 1 | 2 | 18 | PD.2 | 3 | 2 | 50 |
PB.3 | 1 | 3 | 19 | PD.3 | 3 | 3 | 51 |
PB.4 | 1 | 4 | 20 | PD.4 | 3 | 4 | 52 |
PB.5 | 1 | 5 | 21 | PD.5 | 3 | 5 | 53 |
PB.6 | 1 | 6 | 22 | PD.6 | 3 | 6 | 54 |
PB.7 | 1 | 7 | 23 | PD.7 | 3 | 7 | 55 |
PB.8 | 1 | 8 | 24 | PD.8 | 3 | 8 | 56 |
PB.9 | 1 | 9 | 25 | PD.9 | 3 | 9 | 57 |
PB.10 | 1 | 10 | 26 | PD.10 | 3 | 10 | 58 |
PB.11 | 1 | 11 | 27 | PD.11 | 3 | 11 | 59 |
PB.12 | 1 | 12 | 28 | PD.12 | 3 | 12 | 60 |
PB.13 | 1 | 13 | 29 | PD.13 | 3 | 13 | 61 |
PB.14 | 1 | 14 | 30 | PD.14 | 3 | 14 | 62 |
PB.15 | 1 | 15 | 31 | PD.15 | 3 | 15 | 63 |
2.2.2 Use a macro to define
#define LED0_PIN GET_PIN(F, 9)
#define __STM32_PORT(port) GPIO##port##_BASE
#if defined(SOC_SERIES_STM32MP1)
#define GET_PIN(PORTx,PIN) (GPIO##PORTx == GPIOZ) ? (176 + PIN) : ((rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x1000UL) )) + PIN))
#else
#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN)
#endif
Macro definition | PORTx | 16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) ) | PIN | result | |
GET_PIN(A, 0) | GPIOA_BASE | D3_AHB1PERIPH_BASE + 0x0000UL | 0 | 0 | 0 |
GET_PIN(A, 1) | GPIOA_BASE | D3_AHB1PERIPH_BASE + 0x0000UL | 0 | 0 | 0 |
GET_PIN(A, 2) | GPIOA_BASE | D3_AHB1PERIPH_BASE + 0x0000UL | 0 | 0 | 0 |
GET_PIN(A, 3) | GPIOA_BASE | D3_AHB1PERIPH_BASE + 0x0000UL | 0 | 0 | 0 |
GET_PIN(B, 0) | GPIOB_BASE | D3_AHB1PERIPH_BASE + 0x0400UL | 1 | 0 | 16 |
GET_PIN(B, 1) | GPIOB_BASE | D3_AHB1PERIPH_BASE + 0x0400UL | 1 | 1 | 17 |
GET_PIN(B, 2) | GPIOB_BASE | D3_AHB1PERIPH_BASE + 0x0400UL | 1 | 2 | 18 |
Results and API The implementation results are the same .
2.2.3 View driver file
This method updates the driver file drv_gpio There is no official document description of the view drive mode , There is no detailed description here .
3、GPIO Output control
We control the LED Light to verify GPIO The output function of .
#include "rtthread.h"
#include "rtdevice.h"
#include "board.h"
#define LED0 GET_PIN(B, 0)
void example_gpio()
{
rt_pin_mode(LED0,PIN_MODE_OUTPUT); // Set the pin to output
rt_pin_write(LED0,PIN_LOW);
}
MSH_CMD_EXPORT(example_gpio, example_gpio)
4、GPIO Input control
Control the core board by on-board buttons LED The light is on and off , Press and the rear light will be on , The light goes out after loosening
#include "rtthread.h"
#include "rtdevice.h"
#include "board.h"
#define LED0 GET_PIN(B, 0)
void example_gpio()
{
static rt_uint32_t key = 0;
rt_pin_mode(LED0,PIN_MODE_OUTPUT); // Set the pin to output
rt_pin_write(LED0,PIN_LOW);
key = rt_pin_get("PA.0"); // Get pin number
rt_pin_mode(key,PIN_MODE_INPUT); // Set the pin as input
while(1)
{
if(rt_pin_read(key) == PIN_HIGH) // Read input status
{
rt_pin_write(LED0,PIN_LOW);
}
else
{
rt_pin_write(LED0,PIN_HIGH);
}
rt_thread_mdelay(1000);
}
}
MSH_CMD_EXPORT(example_gpio, example_gpio)
5、GPIO interrupt
Control the core board by on-board buttons LED The light is on and off , Press to interrupt the rising edge , Light on . The falling edge is interrupted after loosening , The light goes out
6、 Detailed explanation of driving process
6.1 Mode setting
The function called by mode setting is rt_pin_mode, The function finally called is ops->pin_mode, by drv_gpio.c Medium stm32_pin_mode function , The details are as follows
static void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
{
GPIO_InitTypeDef GPIO_InitStruct;
// Identify whether the port number is legal
if (PIN_PORT(pin) >= PIN_STPORT_MAX)
{
return;
}
/*
Conduct GPIO Initialize the relevant assignment of the structure
The default configuration is push-pull output , High speed , No up and down
*/
GPIO_InitStruct.Pin = PIN_STPIN(pin);
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
/*
Modify relevant contents according to the input mode parameters .
*/
if (mode == PIN_MODE_OUTPUT)
{
/* output setting */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
}
else if (mode == PIN_MODE_INPUT)
{
/* input setting: not pull. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
}
else if (mode == PIN_MODE_INPUT_PULLUP)
{
/* input setting: pull up. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
}
else if (mode == PIN_MODE_INPUT_PULLDOWN)
{
/* input setting: pull down. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
}
else if (mode == PIN_MODE_OUTPUT_OD)
{
/* output setting: od. */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
}
/*
Conduct GPIO initialization , According to the macro definition PIN_STPORT Identify GPIOx The address of
*/
HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct);
}
6.2 Output level control
The function called by the output level is rt_pin_write, The function finally called is ops->pin_write, by drv_gpio.c Medium stm32_pin_write function , The details are as follows
static void stm32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
{
GPIO_TypeDef *gpio_port;
uint16_t gpio_pin;
// Convert the pin serial number to port and pin Information , call HAL Library function for output
if (PIN_PORT(pin) < PIN_STPORT_MAX)
{
gpio_port = PIN_STPORT(pin);
gpio_pin = PIN_STPIN(pin);
HAL_GPIO_WritePin(gpio_port, gpio_pin, (GPIO_PinState)value);
}
}
6.3 Input level acquisition
The function called by the input level acquisition is rt_pin_read, The function finally called is ops->pin_read, by drv_gpio.c Medium stm32_pin_read function , The details are as follows
static int stm32_pin_read(rt_device_t dev, rt_base_t pin)
{
GPIO_TypeDef *gpio_port;
uint16_t gpio_pin;
int value = PIN_LOW;
// Convert the pin serial number to port and pin Information , call HAL Library function to obtain input information
if (PIN_PORT(pin) < PIN_STPORT_MAX)
{
gpio_port = PIN_STPORT(pin);
gpio_pin = PIN_STPIN(pin);
value = HAL_GPIO_ReadPin(gpio_port, gpio_pin);
}
return value;
}
6.4 Binding pin interrupt callback function
The binding interrupt function calls rt_pin_attach_irq, The function finally called is ops->pin_attach_irq, by drv_gpio.c Medium stm32_pin_attach_irq function , The details are as follows
It just went on rtt Next pin The interrupt pin mode of the device and the assignment of the interrupt callback function , No substantive STM32 The bottom of the HAL Library Configuration .
static rt_err_t stm32_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
rt_uint32_t mode, void (*hdr)(void *args), void *args)
{
rt_base_t level;
rt_int32_t irqindex = -1;
// Identify whether the port is correct
if (PIN_PORT(pin) >= PIN_STPORT_MAX)
{
return -RT_ENOSYS;
}
// Identify the interrupt source 0-15
irqindex = bit2bitno(PIN_STPIN(pin));
if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
{
return RT_ENOSYS;
}
level = rt_hw_interrupt_disable();
if (pin_irq_hdr_tab[irqindex].pin == pin &&
pin_irq_hdr_tab[irqindex].hdr == hdr &&
pin_irq_hdr_tab[irqindex].mode == mode &&
pin_irq_hdr_tab[irqindex].args == args)
{
rt_hw_interrupt_enable(level);
return RT_EOK;
}
if (pin_irq_hdr_tab[irqindex].pin != -1)
{
rt_hw_interrupt_enable(level);
return RT_EBUSY;
}
pin_irq_hdr_tab[irqindex].pin = pin;
pin_irq_hdr_tab[irqindex].hdr = hdr;
pin_irq_hdr_tab[irqindex].mode = mode;
pin_irq_hdr_tab[irqindex].args = args;
rt_hw_interrupt_enable(level);
return RT_EOK;
}
Concrete HAL The bottom driver of the library is configured in rt_pin_irq_enable Function , The final calling function of this function is stm32_pin_irq_enable The contents are as follows :
static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
rt_uint32_t enabled)
{
const struct pin_irq_map *irqmap;
rt_base_t level;
rt_int32_t irqindex = -1;
GPIO_InitTypeDef GPIO_InitStruct;
// distinguish IO Is it legal
if (PIN_PORT(pin) >= PIN_STPORT_MAX)
{
return -RT_ENOSYS;
}
// To interrupt , Carry out the configuration of yes .
if (enabled == PIN_IRQ_ENABLE)
{
// Get pin serial number
irqindex = bit2bitno(PIN_STPIN(pin));
if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
{
return RT_ENOSYS;
}
level = rt_hw_interrupt_disable();
//pin_irq_hdr_tab The content is in stm32_pin_attach_irq Assignment was made .
if (pin_irq_hdr_tab[irqindex].pin == -1)
{
rt_hw_interrupt_enable(level);
return RT_ENOSYS;
}
// Get the interrupt sequence number according to the pin EXTI0_IRQn-EXTI4_IRQn or EXTI9_5_IRQn
irqmap = &pin_irq_map[irqindex];
// To configure GPIO Initialize structure
/* Configure GPIO_InitStructure */
GPIO_InitStruct.Pin = PIN_STPIN(pin);
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
switch (pin_irq_hdr_tab[irqindex].mode)
{
case PIN_IRQ_MODE_RISING:
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
break;
case PIN_IRQ_MODE_FALLING:
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
break;
case PIN_IRQ_MODE_RISING_FALLING:
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
break;
}
HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct);
// Set interrupt priority , To interrupt
HAL_NVIC_SetPriority(irqmap->irqno, 5, 0);
HAL_NVIC_EnableIRQ(irqmap->irqno);
pin_irq_enable_mask |= irqmap->pinbit;
rt_hw_interrupt_enable(level);
}
// No interruptions
else if (enabled == PIN_IRQ_DISABLE)
{
irqmap = get_pin_irq_map(PIN_STPIN(pin));
if (irqmap == RT_NULL)
{
return RT_ENOSYS;
}
level = rt_hw_interrupt_disable();
// Reset GPIO
HAL_GPIO_DeInit(PIN_STPORT(pin), PIN_STPIN(pin));
pin_irq_enable_mask &= ~irqmap->pinbit;
if ((irqmap->pinbit >= GPIO_PIN_5) && (irqmap->pinbit <= GPIO_PIN_9))
{
if (!(pin_irq_enable_mask & (GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9)))
{
HAL_NVIC_DisableIRQ(irqmap->irqno);
}
}
else if ((irqmap->pinbit >= GPIO_PIN_10) && (irqmap->pinbit <= GPIO_PIN_15))
{
if (!(pin_irq_enable_mask & (GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15)))
{
HAL_NVIC_DisableIRQ(irqmap->irqno);
}
}
else
{
HAL_NVIC_DisableIRQ(irqmap->irqno);
}
rt_hw_interrupt_enable(level);
}
else
{
return -RT_ENOSYS;
}
return RT_EOK;
}
边栏推荐
- Overview of OCR character recognition methods
- Data and Introspection__ dict__ Attributes and__ slots__ attribute
- Deno介绍
- Derivation of anti Park transform and anti Clarke transform formulas for motor control
- 3.1 rtthread 串口设备(V1)详解
- Research on cooperative control of industrial robots
- Safety science to | travel, you must read a guide
- StrError & PERROR use yyds dry inventory
- NR modulation 1
- SD卡报错“error -110 whilst initialising SD card
猜你喜欢
暑期刷题-Day3
2.2 STM32 GPIO操作
Performance test method of bank core business system
Four logs of MySQL server layer
Pointer for in-depth analysis (problem solution)
Remote Sensing Image Super-resolution and Object Detection: Benchmark and State of the Art
[risc-v] external interrupt
I sorted out a classic interview question for my job hopping friends
Princeton University, Peking University & UIUC | offline reinforcement learning with realizability and single strategy concentration
How to do function test well
随机推荐
遥感图像超分辨重建综述
three. JS page background animation liquid JS special effect
Python implementation of maddpg - (1) openai maddpg environment configuration
Tomb. Weekly update of Finance (February 7 - February 13)
Derivation of anti Park transform and anti Clarke transform formulas for motor control
Edcircles: a real time circle detector with a false detection control translation
Leetcode problem solving -- 99 Restore binary search tree
Item 10: Prefer scoped enums to unscoped enums.
如何做好功能测试
继承day01
Four logs of MySQL server layer
I sorted out a classic interview question for my job hopping friends
Distributed service framework dobbo
[slam] orb-slam3 parsing - track () (3)
Restful style
canvas切积木小游戏代码
八道超经典指针面试题(三千字详解)
Data and Introspection__ dict__ Attributes and__ slots__ attribute
Shell pass parameters
Svg drag point crop image JS effect