当前位置:网站首页>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;
}
边栏推荐
- [slam] orb-slam3 parsing - track () (3)
- ESBuild & SWC浅谈: 新一代构建工具
- SAP ALV颜色代码对应颜色(整理)
- Shell pass parameters
- Svg drag point crop image JS effect
- Performance analysis of user login TPS low and CPU full
- 【Rust 笔记】18-宏
- 3857 Mercator coordinate system converted to 4326 (WGS84) longitude and latitude coordinates
- Add one to non negative integers in the array
- ArabellaCPC 2019(补题)
猜你喜欢
2022工作中遇到的问题四
2.1 rtthread pin设备详解
深入探究指针及指针类型
JS music online playback plug-in vsplayaudio js
2.2 STM32 GPIO操作
JS音乐在线播放插件vsPlayAudio.js
Buuctf question brushing notes - [geek challenge 2019] easysql 1
My C language learning record (blue bridge) -- under the pointer
Mysql database operation
Redo file corruption repair
随机推荐
NR modulation 1
Pointer written test questions ~ approaching Dachang
3.2 rtthread 串口设备(V2)详解
Recommended foreign websites for programmers to learn
Tomb. Weekly update of Finance (February 7 - February 13)
Deep parsing pointer and array written test questions
【Rust 笔记】18-宏
Leetcode problem solving -- 173 Binary search tree iterator
resulttype和resultmap的区别和应用场景
Crazy, thousands of netizens are exploding the company's salary
Jenkins basic knowledge ----- detailed explanation of 03pipeline code
银行核心业务系统性能测试方法
多态day02
The solution of permission denied (750 permissions should be used with caution)
Derivation of anti Park transform and anti Clarke transform formulas for motor control
JS音乐在线播放插件vsPlayAudio.js
Microsoft Research, UIUC & Google research | antagonistic training actor critic based on offline training reinforcement learning
施努卡:什么是视觉定位系统 视觉系统如何定位
Python implementation of maddpg - (1) openai maddpg environment configuration
Exness foreign exchange: the governor of the Bank of Canada said that the interest rate hike would be more moderate, and the United States and Canada fell slightly to maintain range volatility